one 1.2.69 → 1.2.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/__mocks__/@react-navigation/native-stack.cjs +29 -0
- package/dist/cjs/__mocks__/@react-navigation/native-stack.js +24 -0
- package/dist/cjs/__mocks__/@react-navigation/native-stack.js.map +6 -0
- package/dist/cjs/__mocks__/@react-navigation/native-stack.native.js +38 -0
- package/dist/cjs/__mocks__/@react-navigation/native-stack.native.js.map +1 -0
- package/dist/cjs/__mocks__/@react-navigation/native.js +45 -0
- package/dist/cjs/__mocks__/@react-navigation/native.js.map +1 -0
- package/dist/cjs/__mocks__/expo-linking.cjs +36 -0
- package/dist/cjs/__mocks__/expo-linking.js +25 -0
- package/dist/cjs/__mocks__/expo-linking.js.map +6 -0
- package/dist/cjs/__mocks__/expo-linking.native.js +47 -0
- package/dist/cjs/__mocks__/expo-linking.native.js.map +1 -0
- package/dist/cjs/__mocks__/expo-modules-core.cjs +36 -0
- package/dist/cjs/__mocks__/expo-modules-core.js +31 -0
- package/dist/cjs/__mocks__/expo-modules-core.js.map +6 -0
- package/dist/cjs/__mocks__/expo-modules-core.native.js +67 -0
- package/dist/cjs/__mocks__/expo-modules-core.native.js.map +1 -0
- package/dist/cjs/__mocks__/react-native-screens.cjs +28 -0
- package/dist/cjs/__mocks__/react-native-screens.js +22 -0
- package/dist/cjs/__mocks__/react-native-screens.js.map +6 -0
- package/dist/cjs/__mocks__/react-native-screens.native.js +31 -0
- package/dist/cjs/__mocks__/react-native-screens.native.js.map +1 -0
- package/dist/cjs/__mocks__/react-native.js +49 -0
- package/dist/cjs/__mocks__/react-native.js.map +1 -0
- package/dist/cjs/cli/build.cjs +9 -1
- package/dist/cjs/cli/build.js +8 -1
- package/dist/cjs/cli/build.js.map +1 -1
- package/dist/cjs/cli/build.native.js +13 -1
- package/dist/cjs/cli/build.native.js.map +1 -1
- package/dist/cjs/fork/NavigationContainer.js.map +1 -1
- package/dist/cjs/fork/NavigationContainer.native.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/layouts/Stack.cjs +75 -6
- package/dist/cjs/layouts/Stack.js +44 -4
- package/dist/cjs/layouts/Stack.js.map +2 -2
- package/dist/cjs/layouts/Stack.native.js +81 -6
- package/dist/cjs/layouts/Stack.native.js.map +1 -1
- package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.cjs +40 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.js +35 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.native.js +43 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderComponent.cjs +90 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderComponent.js +68 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderComponent.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderComponent.native.js +99 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderComponent.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderLeft.cjs +35 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderLeft.js +30 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderLeft.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderLeft.native.js +40 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderLeft.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderRight.cjs +35 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderRight.js +30 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderRight.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderRight.native.js +40 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderRight.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.cjs +35 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.js +30 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.native.js +38 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderTitle.cjs +65 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderTitle.js +52 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderTitle.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderTitle.native.js +68 -0
- package/dist/cjs/layouts/stack-utils/StackHeaderTitle.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/StackScreen.cjs +57 -0
- package/dist/cjs/layouts/stack-utils/StackScreen.js +43 -0
- package/dist/cjs/layouts/stack-utils/StackScreen.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/StackScreen.native.js +64 -0
- package/dist/cjs/layouts/stack-utils/StackScreen.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/__tests__/composition.test.cjs +455 -0
- package/dist/cjs/layouts/stack-utils/__tests__/composition.test.js +406 -0
- package/dist/cjs/layouts/stack-utils/__tests__/composition.test.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js +480 -0
- package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js.map +1 -0
- package/dist/cjs/layouts/stack-utils/index.cjs +47 -0
- package/dist/cjs/layouts/stack-utils/index.js +36 -0
- package/dist/cjs/layouts/stack-utils/index.js.map +6 -0
- package/dist/cjs/layouts/stack-utils/index.native.js +50 -0
- package/dist/cjs/layouts/stack-utils/index.native.js.map +1 -0
- package/dist/cjs/layouts/withLayoutContext.cjs +2 -1
- package/dist/cjs/layouts/withLayoutContext.js +2 -2
- package/dist/cjs/layouts/withLayoutContext.js.map +1 -1
- package/dist/cjs/layouts/withLayoutContext.native.js +3 -2
- package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
- package/dist/cjs/useLoader.cjs +4 -2
- package/dist/cjs/useLoader.js +4 -2
- package/dist/cjs/useLoader.js.map +1 -1
- package/dist/cjs/useLoader.native.js +4 -2
- package/dist/cjs/useLoader.native.js.map +1 -1
- package/dist/cjs/utils/children.cjs +46 -0
- package/dist/cjs/utils/children.js +47 -0
- package/dist/cjs/utils/children.js.map +6 -0
- package/dist/cjs/utils/children.native.js +76 -0
- package/dist/cjs/utils/children.native.js.map +1 -0
- package/dist/cjs/utils/style.cjs +28 -0
- package/dist/cjs/utils/style.js +24 -0
- package/dist/cjs/utils/style.js.map +6 -0
- package/dist/cjs/utils/style.native.js +31 -0
- package/dist/cjs/utils/style.native.js.map +1 -0
- package/dist/esm/__mocks__/@react-navigation/native-stack.js +8 -0
- package/dist/esm/__mocks__/@react-navigation/native-stack.js.map +6 -0
- package/dist/esm/__mocks__/@react-navigation/native-stack.mjs +6 -0
- package/dist/esm/__mocks__/@react-navigation/native-stack.mjs.map +1 -0
- package/dist/esm/__mocks__/@react-navigation/native-stack.native.js +12 -0
- package/dist/esm/__mocks__/@react-navigation/native-stack.native.js.map +1 -0
- package/dist/esm/__mocks__/@react-navigation/native.js +18 -0
- package/dist/esm/__mocks__/@react-navigation/native.js.map +1 -0
- package/dist/esm/__mocks__/expo-linking.js +9 -0
- package/dist/esm/__mocks__/expo-linking.js.map +6 -0
- package/dist/esm/__mocks__/expo-linking.mjs +10 -0
- package/dist/esm/__mocks__/expo-linking.mjs.map +1 -0
- package/dist/esm/__mocks__/expo-linking.native.js +18 -0
- package/dist/esm/__mocks__/expo-linking.native.js.map +1 -0
- package/dist/esm/__mocks__/expo-modules-core.js +15 -0
- package/dist/esm/__mocks__/expo-modules-core.js.map +6 -0
- package/dist/esm/__mocks__/expo-modules-core.mjs +10 -0
- package/dist/esm/__mocks__/expo-modules-core.mjs.map +1 -0
- package/dist/esm/__mocks__/expo-modules-core.native.js +38 -0
- package/dist/esm/__mocks__/expo-modules-core.native.js.map +1 -0
- package/dist/esm/__mocks__/react-native-screens.js +6 -0
- package/dist/esm/__mocks__/react-native-screens.js.map +6 -0
- package/dist/esm/__mocks__/react-native-screens.mjs +4 -0
- package/dist/esm/__mocks__/react-native-screens.mjs.map +1 -0
- package/dist/esm/__mocks__/react-native-screens.native.js +4 -0
- package/dist/esm/__mocks__/react-native-screens.native.js.map +1 -0
- package/dist/esm/__mocks__/react-native.js +19 -0
- package/dist/esm/__mocks__/react-native.js.map +1 -0
- package/dist/esm/cli/build.js +8 -1
- package/dist/esm/cli/build.js.map +1 -1
- package/dist/esm/cli/build.mjs +9 -1
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +13 -1
- package/dist/esm/cli/build.native.js.map +1 -1
- package/dist/esm/fork/NavigationContainer.js.map +1 -1
- package/dist/esm/fork/NavigationContainer.mjs.map +1 -1
- package/dist/esm/fork/NavigationContainer.native.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/layouts/Stack.js +45 -1
- package/dist/esm/layouts/Stack.js.map +1 -1
- package/dist/esm/layouts/Stack.mjs +59 -1
- package/dist/esm/layouts/Stack.mjs.map +1 -1
- package/dist/esm/layouts/Stack.native.js +65 -1
- package/dist/esm/layouts/Stack.native.js.map +1 -1
- package/dist/esm/layouts/stack-utils/StackHeaderBackButton.js +19 -0
- package/dist/esm/layouts/stack-utils/StackHeaderBackButton.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackHeaderBackButton.mjs +16 -0
- package/dist/esm/layouts/stack-utils/StackHeaderBackButton.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderBackButton.native.js +16 -0
- package/dist/esm/layouts/stack-utils/StackHeaderBackButton.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderComponent.js +71 -0
- package/dist/esm/layouts/stack-utils/StackHeaderComponent.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackHeaderComponent.mjs +66 -0
- package/dist/esm/layouts/stack-utils/StackHeaderComponent.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderComponent.native.js +72 -0
- package/dist/esm/layouts/stack-utils/StackHeaderComponent.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderLeft.js +14 -0
- package/dist/esm/layouts/stack-utils/StackHeaderLeft.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackHeaderLeft.mjs +11 -0
- package/dist/esm/layouts/stack-utils/StackHeaderLeft.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderLeft.native.js +13 -0
- package/dist/esm/layouts/stack-utils/StackHeaderLeft.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderRight.js +14 -0
- package/dist/esm/layouts/stack-utils/StackHeaderRight.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackHeaderRight.mjs +11 -0
- package/dist/esm/layouts/stack-utils/StackHeaderRight.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderRight.native.js +13 -0
- package/dist/esm/layouts/stack-utils/StackHeaderRight.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.js +14 -0
- package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.mjs +11 -0
- package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.native.js +11 -0
- package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderTitle.js +37 -0
- package/dist/esm/layouts/stack-utils/StackHeaderTitle.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackHeaderTitle.mjs +41 -0
- package/dist/esm/layouts/stack-utils/StackHeaderTitle.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackHeaderTitle.native.js +41 -0
- package/dist/esm/layouts/stack-utils/StackHeaderTitle.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/StackScreen.js +33 -0
- package/dist/esm/layouts/stack-utils/StackScreen.js.map +6 -0
- package/dist/esm/layouts/stack-utils/StackScreen.mjs +33 -0
- package/dist/esm/layouts/stack-utils/StackScreen.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/StackScreen.native.js +38 -0
- package/dist/esm/layouts/stack-utils/StackScreen.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/__tests__/composition.test.js +431 -0
- package/dist/esm/layouts/stack-utils/__tests__/composition.test.js.map +6 -0
- package/dist/esm/layouts/stack-utils/__tests__/composition.test.mjs +456 -0
- package/dist/esm/layouts/stack-utils/__tests__/composition.test.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/__tests__/composition.test.native.js +478 -0
- package/dist/esm/layouts/stack-utils/__tests__/composition.test.native.js.map +1 -0
- package/dist/esm/layouts/stack-utils/index.js +33 -0
- package/dist/esm/layouts/stack-utils/index.js.map +6 -0
- package/dist/esm/layouts/stack-utils/index.mjs +16 -0
- package/dist/esm/layouts/stack-utils/index.mjs.map +1 -0
- package/dist/esm/layouts/stack-utils/index.native.js +16 -0
- package/dist/esm/layouts/stack-utils/index.native.js.map +1 -0
- package/dist/esm/layouts/withLayoutContext.js +2 -1
- package/dist/esm/layouts/withLayoutContext.js.map +1 -1
- package/dist/esm/layouts/withLayoutContext.mjs +2 -1
- package/dist/esm/layouts/withLayoutContext.mjs.map +1 -1
- package/dist/esm/layouts/withLayoutContext.native.js +2 -1
- package/dist/esm/layouts/withLayoutContext.native.js.map +1 -1
- package/dist/esm/useLoader.js +4 -2
- package/dist/esm/useLoader.js.map +1 -1
- package/dist/esm/useLoader.mjs +4 -2
- package/dist/esm/useLoader.mjs.map +1 -1
- package/dist/esm/useLoader.native.js +4 -2
- package/dist/esm/useLoader.native.js.map +1 -1
- package/dist/esm/utils/children.js +33 -0
- package/dist/esm/utils/children.js.map +6 -0
- package/dist/esm/utils/children.mjs +19 -0
- package/dist/esm/utils/children.mjs.map +1 -0
- package/dist/esm/utils/children.native.js +46 -0
- package/dist/esm/utils/children.native.js.map +1 -0
- package/dist/esm/utils/style.js +8 -0
- package/dist/esm/utils/style.js.map +6 -0
- package/dist/esm/utils/style.mjs +5 -0
- package/dist/esm/utils/style.mjs.map +1 -0
- package/dist/esm/utils/style.native.js +5 -0
- package/dist/esm/utils/style.native.js.map +1 -0
- package/package.json +9 -9
- package/src/__mocks__/@react-navigation/native-stack.ts +32 -0
- package/src/__mocks__/@react-navigation/native.ts +21 -0
- package/src/__mocks__/expo-linking.ts +6 -0
- package/src/__mocks__/expo-modules-core.ts +11 -0
- package/src/__mocks__/react-native-screens.ts +17 -0
- package/src/__mocks__/react-native.ts +20 -0
- package/src/cli/build.ts +27 -2
- package/src/fork/NavigationContainer.tsx +2 -0
- package/src/index.ts +10 -0
- package/src/layouts/Stack.tsx +96 -1
- package/src/layouts/stack-utils/README.md +211 -0
- package/src/layouts/stack-utils/StackHeaderBackButton.tsx +34 -0
- package/src/layouts/stack-utils/StackHeaderComponent.tsx +136 -0
- package/src/layouts/stack-utils/StackHeaderLeft.tsx +29 -0
- package/src/layouts/stack-utils/StackHeaderRight.tsx +29 -0
- package/src/layouts/stack-utils/StackHeaderSearchBar.tsx +21 -0
- package/src/layouts/stack-utils/StackHeaderTitle.tsx +79 -0
- package/src/layouts/stack-utils/StackScreen.tsx +69 -0
- package/src/layouts/stack-utils/__tests__/composition.test.tsx +643 -0
- package/src/layouts/stack-utils/index.tsx +45 -0
- package/src/layouts/withLayoutContext.tsx +6 -2
- package/src/router/router.ts +1 -1
- package/src/useLoader.ts +14 -6
- package/src/utils/children.ts +74 -0
- package/src/utils/style.ts +17 -0
- package/types/__mocks__/@react-navigation/native-stack.d.ts +30 -0
- package/types/__mocks__/@react-navigation/native-stack.d.ts.map +1 -0
- package/types/__mocks__/@react-navigation/native.d.ts +17 -0
- package/types/__mocks__/@react-navigation/native.d.ts.map +1 -0
- package/types/__mocks__/expo-linking.d.ts +9 -0
- package/types/__mocks__/expo-linking.d.ts.map +1 -0
- package/types/__mocks__/expo-modules-core.d.ts +11 -0
- package/types/__mocks__/expo-modules-core.d.ts.map +1 -0
- package/types/__mocks__/react-native-screens.d.ts +14 -0
- package/types/__mocks__/react-native-screens.d.ts.map +1 -0
- package/types/__mocks__/react-native.d.ts +12 -0
- package/types/__mocks__/react-native.d.ts.map +1 -0
- package/types/cli/build.d.ts.map +1 -1
- package/types/fork/NavigationContainer.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/layouts/Stack.d.ts +14 -3
- package/types/layouts/Stack.d.ts.map +1 -1
- package/types/layouts/stack-utils/StackHeaderBackButton.d.ts +17 -0
- package/types/layouts/stack-utils/StackHeaderBackButton.d.ts.map +1 -0
- package/types/layouts/stack-utils/StackHeaderComponent.d.ts +36 -0
- package/types/layouts/stack-utils/StackHeaderComponent.d.ts.map +1 -0
- package/types/layouts/stack-utils/StackHeaderLeft.d.ts +13 -0
- package/types/layouts/stack-utils/StackHeaderLeft.d.ts.map +1 -0
- package/types/layouts/stack-utils/StackHeaderRight.d.ts +13 -0
- package/types/layouts/stack-utils/StackHeaderRight.d.ts.map +1 -0
- package/types/layouts/stack-utils/StackHeaderSearchBar.d.ts +10 -0
- package/types/layouts/stack-utils/StackHeaderSearchBar.d.ts.map +1 -0
- package/types/layouts/stack-utils/StackHeaderTitle.d.ts +26 -0
- package/types/layouts/stack-utils/StackHeaderTitle.d.ts.map +1 -0
- package/types/layouts/stack-utils/StackScreen.d.ts +22 -0
- package/types/layouts/stack-utils/StackScreen.d.ts.map +1 -0
- package/types/layouts/stack-utils/index.d.ts +20 -0
- package/types/layouts/stack-utils/index.d.ts.map +1 -0
- package/types/layouts/withLayoutContext.d.ts.map +1 -1
- package/types/useLoader.d.ts.map +1 -1
- package/types/utils/children.d.ts +23 -0
- package/types/utils/children.d.ts.map +1 -0
- package/types/utils/style.d.ts +7 -0
- package/types/utils/style.d.ts.map +1 -0
|
@@ -44,6 +44,7 @@ import { useThenable } from './useThenable'
|
|
|
44
44
|
|
|
45
45
|
declare global {
|
|
46
46
|
// eslint-disable-next-line no-var
|
|
47
|
+
// @ts-ignore - Type differs between react-navigation versions
|
|
47
48
|
var REACT_NAVIGATION_DEVTOOLS: WeakMap<
|
|
48
49
|
NavigationContainerRef<any>,
|
|
49
50
|
{ readonly linking: LinkingOptions<any> }
|
|
@@ -147,6 +148,7 @@ function NavigationContainerInner(
|
|
|
147
148
|
// This will be used by the devtools
|
|
148
149
|
React.useEffect(() => {
|
|
149
150
|
if (refContainer.current) {
|
|
151
|
+
// @ts-ignore - Type differs between react-navigation versions in monorepo
|
|
150
152
|
REACT_NAVIGATION_DEVTOOLS.set(refContainer.current, {
|
|
151
153
|
get linking() {
|
|
152
154
|
return {
|
package/src/index.ts
CHANGED
|
@@ -72,6 +72,16 @@ export { href } from './href'
|
|
|
72
72
|
export { Stack } from './layouts/Stack'
|
|
73
73
|
export { Tabs } from './layouts/Tabs'
|
|
74
74
|
export { Protected, type ProtectedProps } from './views/Protected'
|
|
75
|
+
// Stack header compositional API types
|
|
76
|
+
export type {
|
|
77
|
+
StackHeaderProps,
|
|
78
|
+
StackHeaderBackButtonProps,
|
|
79
|
+
StackHeaderTitleProps,
|
|
80
|
+
StackHeaderLeftProps,
|
|
81
|
+
StackHeaderRightProps,
|
|
82
|
+
StackHeaderSearchBarProps,
|
|
83
|
+
StackScreenProps,
|
|
84
|
+
} from './layouts/stack-utils'
|
|
75
85
|
// utilities
|
|
76
86
|
export { withLayoutContext } from './layouts/withLayoutContext'
|
|
77
87
|
export { Link } from './link/Link'
|
package/src/layouts/Stack.tsx
CHANGED
|
@@ -4,16 +4,111 @@ import {
|
|
|
4
4
|
type NativeStackNavigationEventMap,
|
|
5
5
|
type NativeStackNavigationOptions,
|
|
6
6
|
} from '@react-navigation/native-stack'
|
|
7
|
+
import React, { Children, useMemo, type ComponentProps } from 'react'
|
|
7
8
|
|
|
9
|
+
import {
|
|
10
|
+
StackScreen,
|
|
11
|
+
StackHeader,
|
|
12
|
+
StackHeaderComponent,
|
|
13
|
+
StackHeaderSearchBar,
|
|
14
|
+
appendScreenStackPropsToOptions,
|
|
15
|
+
type StackScreenProps,
|
|
16
|
+
} from './stack-utils'
|
|
8
17
|
import { withLayoutContext } from './withLayoutContext'
|
|
18
|
+
import { isChildOfType } from '../utils/children'
|
|
19
|
+
import { Protected } from '../views/Protected'
|
|
20
|
+
import { Screen } from '../views/Screen'
|
|
9
21
|
|
|
10
22
|
const NativeStackNavigator = createNativeStackNavigator().Navigator
|
|
11
23
|
|
|
12
|
-
|
|
24
|
+
const RNStack = withLayoutContext<
|
|
13
25
|
NativeStackNavigationOptions,
|
|
14
26
|
typeof NativeStackNavigator,
|
|
15
27
|
StackNavigationState<ParamListBase>,
|
|
16
28
|
NativeStackNavigationEventMap
|
|
17
29
|
>(NativeStackNavigator)
|
|
18
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Pre-process children to convert StackScreen (with Header children) to Screen (with options).
|
|
33
|
+
* This allows the Header Composition API to work in layout files.
|
|
34
|
+
*/
|
|
35
|
+
function mapChildren(children: React.ReactNode): React.ReactNode {
|
|
36
|
+
return Children.toArray(children)
|
|
37
|
+
.map((child, index) => {
|
|
38
|
+
if (isChildOfType(child, StackScreen)) {
|
|
39
|
+
// convert StackScreen to Screen with options extracted from Header children
|
|
40
|
+
const options = appendScreenStackPropsToOptions({}, child.props)
|
|
41
|
+
const { children: _, ...rest } = child.props
|
|
42
|
+
return <Screen key={child.props.name ?? index} {...rest} options={options} />
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (isChildOfType(child, Protected)) {
|
|
46
|
+
// recursively process Protected children
|
|
47
|
+
return (
|
|
48
|
+
<Protected key={`protected-${index}`} guard={child.props.guard}>
|
|
49
|
+
{mapChildren(child.props.children)}
|
|
50
|
+
</Protected>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isChildOfType(child, StackHeaderComponent)) {
|
|
55
|
+
// Stack.Header at the Stack level is used for screenOptions, handled separately
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// pass through other children (like Screen)
|
|
60
|
+
return child
|
|
61
|
+
})
|
|
62
|
+
.filter(Boolean)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Stack navigator with support for Header Composition API.
|
|
67
|
+
* Wraps the base Stack to pre-process StackScreen children.
|
|
68
|
+
*/
|
|
69
|
+
const StackWithComposition = React.forwardRef<unknown, ComponentProps<typeof RNStack>>(
|
|
70
|
+
(props, ref) => {
|
|
71
|
+
const { children, screenOptions, ...rest } = props
|
|
72
|
+
|
|
73
|
+
// extract Stack.Header from children for screenOptions
|
|
74
|
+
const screenOptionsWithHeader = useMemo(() => {
|
|
75
|
+
const stackHeader = Children.toArray(children).find((child) =>
|
|
76
|
+
isChildOfType(child, StackHeaderComponent)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if (stackHeader && isChildOfType(stackHeader, StackHeaderComponent)) {
|
|
80
|
+
const headerProps: StackScreenProps = { children: stackHeader }
|
|
81
|
+
if (screenOptions) {
|
|
82
|
+
if (typeof screenOptions === 'function') {
|
|
83
|
+
return (...args: Parameters<typeof screenOptions>) => {
|
|
84
|
+
const opts = screenOptions(...args)
|
|
85
|
+
return appendScreenStackPropsToOptions(opts, headerProps)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return appendScreenStackPropsToOptions(screenOptions, headerProps)
|
|
89
|
+
}
|
|
90
|
+
return appendScreenStackPropsToOptions({}, headerProps)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return screenOptions
|
|
94
|
+
}, [children, screenOptions])
|
|
95
|
+
|
|
96
|
+
// pre-process children to convert StackScreen to Screen
|
|
97
|
+
const processedChildren = useMemo(() => mapChildren(children), [children])
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<RNStack {...rest} ref={ref} screenOptions={screenOptionsWithHeader}>
|
|
101
|
+
{processedChildren}
|
|
102
|
+
</RNStack>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
export const Stack = Object.assign(StackWithComposition, {
|
|
108
|
+
Screen: StackScreen,
|
|
109
|
+
Header: StackHeader,
|
|
110
|
+
Protected,
|
|
111
|
+
SearchBar: StackHeaderSearchBar,
|
|
112
|
+
})
|
|
113
|
+
|
|
19
114
|
export default Stack
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Stack Header Composition API
|
|
2
|
+
|
|
3
|
+
A declarative JSX API for configuring native stack headers in One.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Stack Header Composition API provides a more intuitive way to configure stack navigation headers using JSX components instead of the traditional options object. This is particularly useful for complex header configurations like large titles, custom buttons, and search bars.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
The components are available through the main `one` package:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { Stack } from 'one'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Core Components
|
|
18
|
+
|
|
19
|
+
| Component | Description |
|
|
20
|
+
|-----------|-------------|
|
|
21
|
+
| `Stack.Screen` | Screen wrapper with header composition support |
|
|
22
|
+
| `Stack.Header` | Main header configuration container |
|
|
23
|
+
| `Stack.Header.Title` | Configure title text and large title mode |
|
|
24
|
+
| `Stack.Header.Left` | Custom left header content |
|
|
25
|
+
| `Stack.Header.Right` | Custom right header content |
|
|
26
|
+
| `Stack.Header.BackButton` | Back button configuration |
|
|
27
|
+
| `Stack.Header.SearchBar` | Search bar configuration |
|
|
28
|
+
|
|
29
|
+
## Basic Usage
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { Stack } from 'one'
|
|
33
|
+
|
|
34
|
+
export default function Layout() {
|
|
35
|
+
return (
|
|
36
|
+
<Stack>
|
|
37
|
+
<Stack.Screen name="index">
|
|
38
|
+
<Stack.Header>
|
|
39
|
+
<Stack.Header.Title large>Welcome</Stack.Header.Title>
|
|
40
|
+
</Stack.Header>
|
|
41
|
+
</Stack.Screen>
|
|
42
|
+
</Stack>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Large Title with Blur Effect (iOS)
|
|
48
|
+
|
|
49
|
+
The classic iOS large title pattern with blur effect:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
<Stack.Screen name="feed">
|
|
53
|
+
<Stack.Header blurEffect="regular" style={{ backgroundColor: 'transparent' }}>
|
|
54
|
+
<Stack.Header.Title large>Feed</Stack.Header.Title>
|
|
55
|
+
</Stack.Header>
|
|
56
|
+
</Stack.Screen>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Custom Header Buttons
|
|
60
|
+
|
|
61
|
+
Add custom buttons to the left or right side of the header:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
<Stack.Screen name="profile">
|
|
65
|
+
<Stack.Header>
|
|
66
|
+
<Stack.Header.Title>Profile</Stack.Header.Title>
|
|
67
|
+
<Stack.Header.Left asChild>
|
|
68
|
+
<Button onPress={goBack}>Back</Button>
|
|
69
|
+
</Stack.Header.Left>
|
|
70
|
+
<Stack.Header.Right asChild>
|
|
71
|
+
<Button onPress={openSettings}>Settings</Button>
|
|
72
|
+
</Stack.Header.Right>
|
|
73
|
+
</Stack.Header>
|
|
74
|
+
</Stack.Screen>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Search Bar
|
|
78
|
+
|
|
79
|
+
Add an integrated search bar to the header:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
<Stack.Screen name="search">
|
|
83
|
+
<Stack.Header>
|
|
84
|
+
<Stack.Header.Title>Search</Stack.Header.Title>
|
|
85
|
+
<Stack.Header.SearchBar
|
|
86
|
+
placeholder="Search..."
|
|
87
|
+
onChangeText={handleSearch}
|
|
88
|
+
/>
|
|
89
|
+
</Stack.Header>
|
|
90
|
+
</Stack.Screen>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Back Button Configuration
|
|
94
|
+
|
|
95
|
+
Customize the back button appearance and behavior:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
<Stack.Screen name="detail">
|
|
99
|
+
<Stack.Header>
|
|
100
|
+
<Stack.Header.Title>Detail</Stack.Header.Title>
|
|
101
|
+
<Stack.Header.BackButton
|
|
102
|
+
displayMode="minimal"
|
|
103
|
+
hidden={false}
|
|
104
|
+
>
|
|
105
|
+
Back
|
|
106
|
+
</Stack.Header.BackButton>
|
|
107
|
+
</Stack.Header>
|
|
108
|
+
</Stack.Screen>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Custom Header Component
|
|
112
|
+
|
|
113
|
+
Replace the entire header with a custom component:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
<Stack.Screen name="custom">
|
|
117
|
+
<Stack.Header asChild>
|
|
118
|
+
<CustomHeader />
|
|
119
|
+
</Stack.Header>
|
|
120
|
+
</Stack.Screen>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Combining with Options
|
|
124
|
+
|
|
125
|
+
You can combine the composition API with the traditional options prop:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
<Stack.Screen
|
|
129
|
+
name="mixed"
|
|
130
|
+
options={{
|
|
131
|
+
animation: 'slide_from_right',
|
|
132
|
+
gestureEnabled: true,
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
<Stack.Header>
|
|
136
|
+
<Stack.Header.Title large>Mixed Config</Stack.Header.Title>
|
|
137
|
+
</Stack.Header>
|
|
138
|
+
</Stack.Screen>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## API Reference
|
|
142
|
+
|
|
143
|
+
### Stack.Header Props
|
|
144
|
+
|
|
145
|
+
| Prop | Type | Description |
|
|
146
|
+
|------|------|-------------|
|
|
147
|
+
| `hidden` | `boolean` | Hide the header entirely |
|
|
148
|
+
| `asChild` | `boolean` | Render children as the entire header |
|
|
149
|
+
| `blurEffect` | `'regular' \| 'prominent' \| ...` | iOS blur effect |
|
|
150
|
+
| `style` | `StyleProp` | Header style (backgroundColor, shadowColor) |
|
|
151
|
+
| `largeStyle` | `StyleProp` | Large title header style |
|
|
152
|
+
|
|
153
|
+
### Stack.Header.Title Props
|
|
154
|
+
|
|
155
|
+
| Prop | Type | Description |
|
|
156
|
+
|------|------|-------------|
|
|
157
|
+
| `children` | `string` | Title text |
|
|
158
|
+
| `large` | `boolean` | Enable large title mode |
|
|
159
|
+
| `style` | `StyleProp` | Title text style |
|
|
160
|
+
| `largeStyle` | `StyleProp` | Large title text style |
|
|
161
|
+
|
|
162
|
+
### Stack.Header.Left / Right Props
|
|
163
|
+
|
|
164
|
+
| Prop | Type | Description |
|
|
165
|
+
|------|------|-------------|
|
|
166
|
+
| `children` | `ReactNode` | Content to render |
|
|
167
|
+
| `asChild` | `boolean` | Required to render custom content |
|
|
168
|
+
|
|
169
|
+
### Stack.Header.BackButton Props
|
|
170
|
+
|
|
171
|
+
| Prop | Type | Description |
|
|
172
|
+
|------|------|-------------|
|
|
173
|
+
| `children` | `string` | Back button title |
|
|
174
|
+
| `hidden` | `boolean` | Hide the back button |
|
|
175
|
+
| `displayMode` | `'default' \| 'minimal' \| 'generic'` | Display mode |
|
|
176
|
+
| `withMenu` | `boolean` | Enable back button menu |
|
|
177
|
+
| `src` | `ImageSourcePropType` | Custom back button image |
|
|
178
|
+
| `style` | `TextStyle` | Back button title style |
|
|
179
|
+
|
|
180
|
+
### Stack.Header.SearchBar Props
|
|
181
|
+
|
|
182
|
+
Accepts all props from `react-native-screens` SearchBarProps.
|
|
183
|
+
|
|
184
|
+
## Comparison with Options API
|
|
185
|
+
|
|
186
|
+
**Traditional options API:**
|
|
187
|
+
```tsx
|
|
188
|
+
<Stack.Screen
|
|
189
|
+
name="index"
|
|
190
|
+
options={{
|
|
191
|
+
title: 'Welcome',
|
|
192
|
+
headerLargeTitle: true,
|
|
193
|
+
headerBlurEffect: 'regular',
|
|
194
|
+
headerRight: () => <Button>Action</Button>,
|
|
195
|
+
}}
|
|
196
|
+
/>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Composition API:**
|
|
200
|
+
```tsx
|
|
201
|
+
<Stack.Screen name="index">
|
|
202
|
+
<Stack.Header blurEffect="regular">
|
|
203
|
+
<Stack.Header.Title large>Welcome</Stack.Header.Title>
|
|
204
|
+
<Stack.Header.Right asChild>
|
|
205
|
+
<Button>Action</Button>
|
|
206
|
+
</Stack.Header.Right>
|
|
207
|
+
</Stack.Header>
|
|
208
|
+
</Stack.Screen>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Both approaches work, choose based on your preference. The composition API can be more readable for complex configurations.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
|
|
2
|
+
import type { ImageSourcePropType } from 'react-native'
|
|
3
|
+
import type { ScreenStackHeaderConfigProps } from 'react-native-screens'
|
|
4
|
+
|
|
5
|
+
export interface StackHeaderBackButtonProps {
|
|
6
|
+
children?: string
|
|
7
|
+
style?: NativeStackNavigationOptions['headerBackTitleStyle']
|
|
8
|
+
withMenu?: boolean
|
|
9
|
+
displayMode?: ScreenStackHeaderConfigProps['backButtonDisplayMode']
|
|
10
|
+
hidden?: boolean
|
|
11
|
+
src?: ImageSourcePropType
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Configuration component for the back button in stack headers.
|
|
16
|
+
*/
|
|
17
|
+
export function StackHeaderBackButton(_props: StackHeaderBackButtonProps) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function appendStackHeaderBackButtonPropsToOptions(
|
|
22
|
+
options: NativeStackNavigationOptions,
|
|
23
|
+
props: StackHeaderBackButtonProps
|
|
24
|
+
): NativeStackNavigationOptions {
|
|
25
|
+
return {
|
|
26
|
+
...options,
|
|
27
|
+
headerBackTitle: props.children,
|
|
28
|
+
headerBackTitleStyle: props.style,
|
|
29
|
+
headerBackImageSource: props.src,
|
|
30
|
+
headerBackButtonDisplayMode: props.displayMode,
|
|
31
|
+
headerBackButtonMenuEnabled: props.withMenu,
|
|
32
|
+
headerBackVisible: props.hidden !== undefined ? !props.hidden : undefined,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
|
|
2
|
+
import { Children, isValidElement, type ReactNode } from 'react'
|
|
3
|
+
import { StyleSheet, type ColorValue, type StyleProp } from 'react-native'
|
|
4
|
+
import type { ScreenStackHeaderConfigProps } from 'react-native-screens'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
appendStackHeaderBackButtonPropsToOptions,
|
|
8
|
+
StackHeaderBackButton,
|
|
9
|
+
} from './StackHeaderBackButton'
|
|
10
|
+
import { StackHeaderLeft, appendStackHeaderLeftPropsToOptions } from './StackHeaderLeft'
|
|
11
|
+
import {
|
|
12
|
+
StackHeaderRight,
|
|
13
|
+
appendStackHeaderRightPropsToOptions,
|
|
14
|
+
} from './StackHeaderRight'
|
|
15
|
+
import {
|
|
16
|
+
appendStackHeaderSearchBarPropsToOptions,
|
|
17
|
+
StackHeaderSearchBar,
|
|
18
|
+
} from './StackHeaderSearchBar'
|
|
19
|
+
import {
|
|
20
|
+
appendStackHeaderTitlePropsToOptions,
|
|
21
|
+
StackHeaderTitle,
|
|
22
|
+
} from './StackHeaderTitle'
|
|
23
|
+
import { isChildOfType } from '../../utils/children'
|
|
24
|
+
|
|
25
|
+
export interface StackHeaderProps {
|
|
26
|
+
children?: ReactNode
|
|
27
|
+
hidden?: boolean
|
|
28
|
+
asChild?: boolean
|
|
29
|
+
blurEffect?: ScreenStackHeaderConfigProps['blurEffect']
|
|
30
|
+
style?: StyleProp<{
|
|
31
|
+
color?: ColorValue
|
|
32
|
+
backgroundColor?: ScreenStackHeaderConfigProps['backgroundColor']
|
|
33
|
+
shadowColor?: undefined | 'transparent'
|
|
34
|
+
}>
|
|
35
|
+
largeStyle?: StyleProp<{
|
|
36
|
+
backgroundColor?: ScreenStackHeaderConfigProps['largeTitleBackgroundColor']
|
|
37
|
+
shadowColor?: undefined | 'transparent'
|
|
38
|
+
}>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Configuration component for stack headers.
|
|
43
|
+
* Use child components to configure different parts of the header.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <Stack.Header blurEffect="regular">
|
|
48
|
+
* <Stack.Header.Title large>My Title</Stack.Header.Title>
|
|
49
|
+
* <Stack.Header.Right asChild>
|
|
50
|
+
* <Button>Action</Button>
|
|
51
|
+
* </Stack.Header.Right>
|
|
52
|
+
* </Stack.Header>
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function StackHeaderComponent(_props: StackHeaderProps) {
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function appendStackHeaderPropsToOptions(
|
|
60
|
+
options: NativeStackNavigationOptions,
|
|
61
|
+
props: StackHeaderProps
|
|
62
|
+
): NativeStackNavigationOptions {
|
|
63
|
+
const flattenedStyle = StyleSheet.flatten(props.style)
|
|
64
|
+
const flattenedLargeStyle = StyleSheet.flatten(props.largeStyle)
|
|
65
|
+
|
|
66
|
+
if (props.hidden) {
|
|
67
|
+
return { ...options, headerShown: false }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (props.asChild) {
|
|
71
|
+
return { ...options, header: () => props.children }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const isTransparent = flattenedStyle?.backgroundColor === 'transparent'
|
|
75
|
+
const hasCustomShadow = flattenedStyle?.shadowColor !== undefined
|
|
76
|
+
const hasBackgroundColor = flattenedStyle?.backgroundColor !== undefined
|
|
77
|
+
const hasLargeBackgroundColor = flattenedLargeStyle?.backgroundColor !== undefined
|
|
78
|
+
|
|
79
|
+
let updatedOptions: NativeStackNavigationOptions = {
|
|
80
|
+
...options,
|
|
81
|
+
headerShown: !props.hidden,
|
|
82
|
+
headerBlurEffect: props.blurEffect,
|
|
83
|
+
// Set headerTransparent when backgroundColor is 'transparent'
|
|
84
|
+
// This works on both iOS and Android for normal headers
|
|
85
|
+
// Note: When using SearchBar on iOS, if you don't have a ScrollView with
|
|
86
|
+
// contentInsetAdjustmentBehavior="automatic", set headerTransparent: false in options
|
|
87
|
+
...(isTransparent && { headerTransparent: true }),
|
|
88
|
+
// Only set header styles when explicitly configured to avoid interfering with native defaults
|
|
89
|
+
...(hasBackgroundColor && {
|
|
90
|
+
headerStyle: { backgroundColor: flattenedStyle.backgroundColor as string },
|
|
91
|
+
}),
|
|
92
|
+
...(hasLargeBackgroundColor && {
|
|
93
|
+
headerLargeStyle: {
|
|
94
|
+
backgroundColor: flattenedLargeStyle.backgroundColor as string,
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
// Only set shadow visibility when explicitly configured
|
|
98
|
+
...(hasCustomShadow && {
|
|
99
|
+
headerShadowVisible: flattenedStyle?.shadowColor !== 'transparent',
|
|
100
|
+
}),
|
|
101
|
+
...(flattenedLargeStyle?.shadowColor !== undefined && {
|
|
102
|
+
headerLargeTitleShadowVisible: flattenedLargeStyle?.shadowColor !== 'transparent',
|
|
103
|
+
}),
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function appendChildOptions(
|
|
107
|
+
child: React.ReactElement,
|
|
108
|
+
options: NativeStackNavigationOptions
|
|
109
|
+
) {
|
|
110
|
+
let result = options
|
|
111
|
+
if (isChildOfType(child, StackHeaderTitle)) {
|
|
112
|
+
result = appendStackHeaderTitlePropsToOptions(result, child.props)
|
|
113
|
+
} else if (isChildOfType(child, StackHeaderLeft)) {
|
|
114
|
+
result = appendStackHeaderLeftPropsToOptions(result, child.props)
|
|
115
|
+
} else if (isChildOfType(child, StackHeaderRight)) {
|
|
116
|
+
result = appendStackHeaderRightPropsToOptions(result, child.props)
|
|
117
|
+
} else if (isChildOfType(child, StackHeaderBackButton)) {
|
|
118
|
+
result = appendStackHeaderBackButtonPropsToOptions(result, child.props)
|
|
119
|
+
} else if (isChildOfType(child, StackHeaderSearchBar)) {
|
|
120
|
+
result = appendStackHeaderSearchBarPropsToOptions(result, child.props)
|
|
121
|
+
} else {
|
|
122
|
+
console.warn(
|
|
123
|
+
`Warning: Unknown child element passed to Stack.Header: ${(child.type as { name: string }).name ?? child.type}`
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
return result
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Children.forEach(props.children, (child) => {
|
|
130
|
+
if (isValidElement(child)) {
|
|
131
|
+
updatedOptions = appendChildOptions(child, updatedOptions)
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return updatedOptions
|
|
136
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
export interface StackHeaderLeftProps {
|
|
5
|
+
children?: ReactNode
|
|
6
|
+
asChild?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration component for custom left header content.
|
|
11
|
+
* Use `asChild` to render custom components in the left header area.
|
|
12
|
+
*/
|
|
13
|
+
export function StackHeaderLeft(_props: StackHeaderLeftProps) {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function appendStackHeaderLeftPropsToOptions(
|
|
18
|
+
options: NativeStackNavigationOptions,
|
|
19
|
+
props: StackHeaderLeftProps
|
|
20
|
+
): NativeStackNavigationOptions {
|
|
21
|
+
if (!props.asChild) {
|
|
22
|
+
return options
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...options,
|
|
27
|
+
headerLeft: () => props.children,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
export interface StackHeaderRightProps {
|
|
5
|
+
children?: ReactNode
|
|
6
|
+
asChild?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration component for custom right header content.
|
|
11
|
+
* Use `asChild` to render custom components in the right header area.
|
|
12
|
+
*/
|
|
13
|
+
export function StackHeaderRight(_props: StackHeaderRightProps) {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function appendStackHeaderRightPropsToOptions(
|
|
18
|
+
options: NativeStackNavigationOptions,
|
|
19
|
+
props: StackHeaderRightProps
|
|
20
|
+
): NativeStackNavigationOptions {
|
|
21
|
+
if (!props.asChild) {
|
|
22
|
+
return options
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...options,
|
|
27
|
+
headerRight: () => props.children,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
|
|
2
|
+
import type { SearchBarProps } from 'react-native-screens'
|
|
3
|
+
|
|
4
|
+
export interface StackHeaderSearchBarProps extends SearchBarProps {}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration component for adding a search bar to stack headers.
|
|
8
|
+
*/
|
|
9
|
+
export function StackHeaderSearchBar(_props: StackHeaderSearchBarProps) {
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function appendStackHeaderSearchBarPropsToOptions(
|
|
14
|
+
options: NativeStackNavigationOptions,
|
|
15
|
+
props: StackHeaderSearchBarProps
|
|
16
|
+
): NativeStackNavigationOptions {
|
|
17
|
+
return {
|
|
18
|
+
...options,
|
|
19
|
+
headerSearchBarOptions: props,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
|
|
2
|
+
import { Platform, StyleSheet, type StyleProp, type TextStyle } from 'react-native'
|
|
3
|
+
|
|
4
|
+
import { convertFontWeightToStringFontWeight } from '../../utils/style'
|
|
5
|
+
|
|
6
|
+
export type StackHeaderTitleProps = {
|
|
7
|
+
children?: string
|
|
8
|
+
style?: StyleProp<{
|
|
9
|
+
fontFamily?: TextStyle['fontFamily']
|
|
10
|
+
fontSize?: TextStyle['fontSize']
|
|
11
|
+
fontWeight?: Exclude<TextStyle['fontWeight'], number>
|
|
12
|
+
color?: string
|
|
13
|
+
textAlign?: 'left' | 'center'
|
|
14
|
+
}>
|
|
15
|
+
largeStyle?: StyleProp<{
|
|
16
|
+
fontFamily?: TextStyle['fontFamily']
|
|
17
|
+
fontSize?: TextStyle['fontSize']
|
|
18
|
+
fontWeight?: Exclude<TextStyle['fontWeight'], number>
|
|
19
|
+
color?: string
|
|
20
|
+
}>
|
|
21
|
+
large?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Configuration component for stack header title.
|
|
26
|
+
* This component doesn't render anything - it's used to configure the header.
|
|
27
|
+
*/
|
|
28
|
+
export function StackHeaderTitle(_props: StackHeaderTitleProps) {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function appendStackHeaderTitlePropsToOptions(
|
|
33
|
+
options: NativeStackNavigationOptions,
|
|
34
|
+
props: StackHeaderTitleProps
|
|
35
|
+
): NativeStackNavigationOptions {
|
|
36
|
+
const flattenedStyle = StyleSheet.flatten(props.style)
|
|
37
|
+
const flattenedLargeStyle = StyleSheet.flatten(props.largeStyle)
|
|
38
|
+
|
|
39
|
+
// Build title style only if there are actual style properties
|
|
40
|
+
const titleStyle = flattenedStyle
|
|
41
|
+
? {
|
|
42
|
+
...flattenedStyle,
|
|
43
|
+
...(flattenedStyle?.fontWeight
|
|
44
|
+
? { fontWeight: convertFontWeightToStringFontWeight(flattenedStyle.fontWeight) }
|
|
45
|
+
: {}),
|
|
46
|
+
}
|
|
47
|
+
: undefined
|
|
48
|
+
|
|
49
|
+
// Build large title style only if there are actual style properties
|
|
50
|
+
const largeTitleStyle = flattenedLargeStyle
|
|
51
|
+
? {
|
|
52
|
+
...flattenedLargeStyle,
|
|
53
|
+
...(flattenedLargeStyle?.fontWeight
|
|
54
|
+
? {
|
|
55
|
+
fontWeight: convertFontWeightToStringFontWeight(
|
|
56
|
+
flattenedLargeStyle.fontWeight
|
|
57
|
+
),
|
|
58
|
+
}
|
|
59
|
+
: {}),
|
|
60
|
+
}
|
|
61
|
+
: undefined
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
...options,
|
|
65
|
+
title: props.children,
|
|
66
|
+
headerLargeTitle: props.large,
|
|
67
|
+
// Large titles on iOS require headerTransparent for proper scroll behavior
|
|
68
|
+
// Only set on iOS since headerLargeTitle is iOS-only
|
|
69
|
+
...(props.large && Platform.OS === 'ios' && { headerTransparent: true }),
|
|
70
|
+
headerTitleAlign: flattenedStyle?.textAlign,
|
|
71
|
+
// Only set styles when explicitly configured to avoid interfering with native defaults
|
|
72
|
+
...(titleStyle &&
|
|
73
|
+
Object.keys(titleStyle).length > 0 && { headerTitleStyle: titleStyle }),
|
|
74
|
+
...(largeTitleStyle &&
|
|
75
|
+
Object.keys(largeTitleStyle).length > 0 && {
|
|
76
|
+
headerLargeTitleStyle: largeTitleStyle,
|
|
77
|
+
}),
|
|
78
|
+
}
|
|
79
|
+
}
|