one 1.2.69 → 1.2.70

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.
Files changed (266) hide show
  1. package/dist/cjs/__mocks__/@react-navigation/native-stack.cjs +29 -0
  2. package/dist/cjs/__mocks__/@react-navigation/native-stack.js +24 -0
  3. package/dist/cjs/__mocks__/@react-navigation/native-stack.js.map +6 -0
  4. package/dist/cjs/__mocks__/@react-navigation/native-stack.native.js +38 -0
  5. package/dist/cjs/__mocks__/@react-navigation/native-stack.native.js.map +1 -0
  6. package/dist/cjs/__mocks__/@react-navigation/native.js +45 -0
  7. package/dist/cjs/__mocks__/@react-navigation/native.js.map +1 -0
  8. package/dist/cjs/__mocks__/expo-linking.cjs +36 -0
  9. package/dist/cjs/__mocks__/expo-linking.js +25 -0
  10. package/dist/cjs/__mocks__/expo-linking.js.map +6 -0
  11. package/dist/cjs/__mocks__/expo-linking.native.js +47 -0
  12. package/dist/cjs/__mocks__/expo-linking.native.js.map +1 -0
  13. package/dist/cjs/__mocks__/expo-modules-core.cjs +36 -0
  14. package/dist/cjs/__mocks__/expo-modules-core.js +31 -0
  15. package/dist/cjs/__mocks__/expo-modules-core.js.map +6 -0
  16. package/dist/cjs/__mocks__/expo-modules-core.native.js +67 -0
  17. package/dist/cjs/__mocks__/expo-modules-core.native.js.map +1 -0
  18. package/dist/cjs/__mocks__/react-native-screens.cjs +28 -0
  19. package/dist/cjs/__mocks__/react-native-screens.js +22 -0
  20. package/dist/cjs/__mocks__/react-native-screens.js.map +6 -0
  21. package/dist/cjs/__mocks__/react-native-screens.native.js +31 -0
  22. package/dist/cjs/__mocks__/react-native-screens.native.js.map +1 -0
  23. package/dist/cjs/__mocks__/react-native.js +49 -0
  24. package/dist/cjs/__mocks__/react-native.js.map +1 -0
  25. package/dist/cjs/fork/NavigationContainer.js.map +1 -1
  26. package/dist/cjs/fork/NavigationContainer.native.js.map +1 -1
  27. package/dist/cjs/index.js.map +1 -1
  28. package/dist/cjs/layouts/Stack.cjs +6 -1
  29. package/dist/cjs/layouts/Stack.js +5 -2
  30. package/dist/cjs/layouts/Stack.js.map +1 -1
  31. package/dist/cjs/layouts/Stack.native.js +6 -1
  32. package/dist/cjs/layouts/Stack.native.js.map +1 -1
  33. package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.cjs +40 -0
  34. package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.js +35 -0
  35. package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.js.map +6 -0
  36. package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.native.js +43 -0
  37. package/dist/cjs/layouts/stack-utils/StackHeaderBackButton.native.js.map +1 -0
  38. package/dist/cjs/layouts/stack-utils/StackHeaderComponent.cjs +90 -0
  39. package/dist/cjs/layouts/stack-utils/StackHeaderComponent.js +64 -0
  40. package/dist/cjs/layouts/stack-utils/StackHeaderComponent.js.map +6 -0
  41. package/dist/cjs/layouts/stack-utils/StackHeaderComponent.native.js +99 -0
  42. package/dist/cjs/layouts/stack-utils/StackHeaderComponent.native.js.map +1 -0
  43. package/dist/cjs/layouts/stack-utils/StackHeaderLeft.cjs +35 -0
  44. package/dist/cjs/layouts/stack-utils/StackHeaderLeft.js +30 -0
  45. package/dist/cjs/layouts/stack-utils/StackHeaderLeft.js.map +6 -0
  46. package/dist/cjs/layouts/stack-utils/StackHeaderLeft.native.js +40 -0
  47. package/dist/cjs/layouts/stack-utils/StackHeaderLeft.native.js.map +1 -0
  48. package/dist/cjs/layouts/stack-utils/StackHeaderRight.cjs +35 -0
  49. package/dist/cjs/layouts/stack-utils/StackHeaderRight.js +30 -0
  50. package/dist/cjs/layouts/stack-utils/StackHeaderRight.js.map +6 -0
  51. package/dist/cjs/layouts/stack-utils/StackHeaderRight.native.js +40 -0
  52. package/dist/cjs/layouts/stack-utils/StackHeaderRight.native.js.map +1 -0
  53. package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.cjs +35 -0
  54. package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.js +30 -0
  55. package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.js.map +6 -0
  56. package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.native.js +38 -0
  57. package/dist/cjs/layouts/stack-utils/StackHeaderSearchBar.native.js.map +1 -0
  58. package/dist/cjs/layouts/stack-utils/StackHeaderTitle.cjs +65 -0
  59. package/dist/cjs/layouts/stack-utils/StackHeaderTitle.js +46 -0
  60. package/dist/cjs/layouts/stack-utils/StackHeaderTitle.js.map +6 -0
  61. package/dist/cjs/layouts/stack-utils/StackHeaderTitle.native.js +68 -0
  62. package/dist/cjs/layouts/stack-utils/StackHeaderTitle.native.js.map +1 -0
  63. package/dist/cjs/layouts/stack-utils/StackScreen.cjs +57 -0
  64. package/dist/cjs/layouts/stack-utils/StackScreen.js +43 -0
  65. package/dist/cjs/layouts/stack-utils/StackScreen.js.map +6 -0
  66. package/dist/cjs/layouts/stack-utils/StackScreen.native.js +64 -0
  67. package/dist/cjs/layouts/stack-utils/StackScreen.native.js.map +1 -0
  68. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.cjs +455 -0
  69. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.js +406 -0
  70. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.js.map +6 -0
  71. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js +480 -0
  72. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js.map +1 -0
  73. package/dist/cjs/layouts/stack-utils/index.cjs +47 -0
  74. package/dist/cjs/layouts/stack-utils/index.js +36 -0
  75. package/dist/cjs/layouts/stack-utils/index.js.map +6 -0
  76. package/dist/cjs/layouts/stack-utils/index.native.js +50 -0
  77. package/dist/cjs/layouts/stack-utils/index.native.js.map +1 -0
  78. package/dist/cjs/layouts/withLayoutContext.cjs +2 -1
  79. package/dist/cjs/layouts/withLayoutContext.js +2 -2
  80. package/dist/cjs/layouts/withLayoutContext.js.map +1 -1
  81. package/dist/cjs/layouts/withLayoutContext.native.js +3 -2
  82. package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
  83. package/dist/cjs/utils/children.cjs +46 -0
  84. package/dist/cjs/utils/children.js +47 -0
  85. package/dist/cjs/utils/children.js.map +6 -0
  86. package/dist/cjs/utils/children.native.js +76 -0
  87. package/dist/cjs/utils/children.native.js.map +1 -0
  88. package/dist/cjs/utils/style.cjs +28 -0
  89. package/dist/cjs/utils/style.js +24 -0
  90. package/dist/cjs/utils/style.js.map +6 -0
  91. package/dist/cjs/utils/style.native.js +31 -0
  92. package/dist/cjs/utils/style.native.js.map +1 -0
  93. package/dist/esm/__mocks__/@react-navigation/native-stack.js +8 -0
  94. package/dist/esm/__mocks__/@react-navigation/native-stack.js.map +6 -0
  95. package/dist/esm/__mocks__/@react-navigation/native-stack.mjs +6 -0
  96. package/dist/esm/__mocks__/@react-navigation/native-stack.mjs.map +1 -0
  97. package/dist/esm/__mocks__/@react-navigation/native-stack.native.js +12 -0
  98. package/dist/esm/__mocks__/@react-navigation/native-stack.native.js.map +1 -0
  99. package/dist/esm/__mocks__/@react-navigation/native.js +18 -0
  100. package/dist/esm/__mocks__/@react-navigation/native.js.map +1 -0
  101. package/dist/esm/__mocks__/expo-linking.js +9 -0
  102. package/dist/esm/__mocks__/expo-linking.js.map +6 -0
  103. package/dist/esm/__mocks__/expo-linking.mjs +10 -0
  104. package/dist/esm/__mocks__/expo-linking.mjs.map +1 -0
  105. package/dist/esm/__mocks__/expo-linking.native.js +18 -0
  106. package/dist/esm/__mocks__/expo-linking.native.js.map +1 -0
  107. package/dist/esm/__mocks__/expo-modules-core.js +15 -0
  108. package/dist/esm/__mocks__/expo-modules-core.js.map +6 -0
  109. package/dist/esm/__mocks__/expo-modules-core.mjs +10 -0
  110. package/dist/esm/__mocks__/expo-modules-core.mjs.map +1 -0
  111. package/dist/esm/__mocks__/expo-modules-core.native.js +38 -0
  112. package/dist/esm/__mocks__/expo-modules-core.native.js.map +1 -0
  113. package/dist/esm/__mocks__/react-native-screens.js +6 -0
  114. package/dist/esm/__mocks__/react-native-screens.js.map +6 -0
  115. package/dist/esm/__mocks__/react-native-screens.mjs +4 -0
  116. package/dist/esm/__mocks__/react-native-screens.mjs.map +1 -0
  117. package/dist/esm/__mocks__/react-native-screens.native.js +4 -0
  118. package/dist/esm/__mocks__/react-native-screens.native.js.map +1 -0
  119. package/dist/esm/__mocks__/react-native.js +19 -0
  120. package/dist/esm/__mocks__/react-native.js.map +1 -0
  121. package/dist/esm/fork/NavigationContainer.js.map +1 -1
  122. package/dist/esm/fork/NavigationContainer.mjs.map +1 -1
  123. package/dist/esm/fork/NavigationContainer.native.js.map +1 -1
  124. package/dist/esm/index.js.map +1 -1
  125. package/dist/esm/index.mjs.map +1 -1
  126. package/dist/esm/index.native.js.map +1 -1
  127. package/dist/esm/layouts/Stack.js +5 -1
  128. package/dist/esm/layouts/Stack.js.map +1 -1
  129. package/dist/esm/layouts/Stack.mjs +6 -1
  130. package/dist/esm/layouts/Stack.mjs.map +1 -1
  131. package/dist/esm/layouts/Stack.native.js +6 -1
  132. package/dist/esm/layouts/Stack.native.js.map +1 -1
  133. package/dist/esm/layouts/stack-utils/StackHeaderBackButton.js +19 -0
  134. package/dist/esm/layouts/stack-utils/StackHeaderBackButton.js.map +6 -0
  135. package/dist/esm/layouts/stack-utils/StackHeaderBackButton.mjs +16 -0
  136. package/dist/esm/layouts/stack-utils/StackHeaderBackButton.mjs.map +1 -0
  137. package/dist/esm/layouts/stack-utils/StackHeaderBackButton.native.js +16 -0
  138. package/dist/esm/layouts/stack-utils/StackHeaderBackButton.native.js.map +1 -0
  139. package/dist/esm/layouts/stack-utils/StackHeaderComponent.js +61 -0
  140. package/dist/esm/layouts/stack-utils/StackHeaderComponent.js.map +6 -0
  141. package/dist/esm/layouts/stack-utils/StackHeaderComponent.mjs +66 -0
  142. package/dist/esm/layouts/stack-utils/StackHeaderComponent.mjs.map +1 -0
  143. package/dist/esm/layouts/stack-utils/StackHeaderComponent.native.js +72 -0
  144. package/dist/esm/layouts/stack-utils/StackHeaderComponent.native.js.map +1 -0
  145. package/dist/esm/layouts/stack-utils/StackHeaderLeft.js +14 -0
  146. package/dist/esm/layouts/stack-utils/StackHeaderLeft.js.map +6 -0
  147. package/dist/esm/layouts/stack-utils/StackHeaderLeft.mjs +11 -0
  148. package/dist/esm/layouts/stack-utils/StackHeaderLeft.mjs.map +1 -0
  149. package/dist/esm/layouts/stack-utils/StackHeaderLeft.native.js +13 -0
  150. package/dist/esm/layouts/stack-utils/StackHeaderLeft.native.js.map +1 -0
  151. package/dist/esm/layouts/stack-utils/StackHeaderRight.js +14 -0
  152. package/dist/esm/layouts/stack-utils/StackHeaderRight.js.map +6 -0
  153. package/dist/esm/layouts/stack-utils/StackHeaderRight.mjs +11 -0
  154. package/dist/esm/layouts/stack-utils/StackHeaderRight.mjs.map +1 -0
  155. package/dist/esm/layouts/stack-utils/StackHeaderRight.native.js +13 -0
  156. package/dist/esm/layouts/stack-utils/StackHeaderRight.native.js.map +1 -0
  157. package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.js +14 -0
  158. package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.js.map +6 -0
  159. package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.mjs +11 -0
  160. package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.mjs.map +1 -0
  161. package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.native.js +11 -0
  162. package/dist/esm/layouts/stack-utils/StackHeaderSearchBar.native.js.map +1 -0
  163. package/dist/esm/layouts/stack-utils/StackHeaderTitle.js +31 -0
  164. package/dist/esm/layouts/stack-utils/StackHeaderTitle.js.map +6 -0
  165. package/dist/esm/layouts/stack-utils/StackHeaderTitle.mjs +41 -0
  166. package/dist/esm/layouts/stack-utils/StackHeaderTitle.mjs.map +1 -0
  167. package/dist/esm/layouts/stack-utils/StackHeaderTitle.native.js +41 -0
  168. package/dist/esm/layouts/stack-utils/StackHeaderTitle.native.js.map +1 -0
  169. package/dist/esm/layouts/stack-utils/StackScreen.js +33 -0
  170. package/dist/esm/layouts/stack-utils/StackScreen.js.map +6 -0
  171. package/dist/esm/layouts/stack-utils/StackScreen.mjs +33 -0
  172. package/dist/esm/layouts/stack-utils/StackScreen.mjs.map +1 -0
  173. package/dist/esm/layouts/stack-utils/StackScreen.native.js +38 -0
  174. package/dist/esm/layouts/stack-utils/StackScreen.native.js.map +1 -0
  175. package/dist/esm/layouts/stack-utils/__tests__/composition.test.js +422 -0
  176. package/dist/esm/layouts/stack-utils/__tests__/composition.test.js.map +6 -0
  177. package/dist/esm/layouts/stack-utils/__tests__/composition.test.mjs +456 -0
  178. package/dist/esm/layouts/stack-utils/__tests__/composition.test.mjs.map +1 -0
  179. package/dist/esm/layouts/stack-utils/__tests__/composition.test.native.js +478 -0
  180. package/dist/esm/layouts/stack-utils/__tests__/composition.test.native.js.map +1 -0
  181. package/dist/esm/layouts/stack-utils/index.js +26 -0
  182. package/dist/esm/layouts/stack-utils/index.js.map +6 -0
  183. package/dist/esm/layouts/stack-utils/index.mjs +16 -0
  184. package/dist/esm/layouts/stack-utils/index.mjs.map +1 -0
  185. package/dist/esm/layouts/stack-utils/index.native.js +16 -0
  186. package/dist/esm/layouts/stack-utils/index.native.js.map +1 -0
  187. package/dist/esm/layouts/withLayoutContext.js +2 -1
  188. package/dist/esm/layouts/withLayoutContext.js.map +1 -1
  189. package/dist/esm/layouts/withLayoutContext.mjs +2 -1
  190. package/dist/esm/layouts/withLayoutContext.mjs.map +1 -1
  191. package/dist/esm/layouts/withLayoutContext.native.js +2 -1
  192. package/dist/esm/layouts/withLayoutContext.native.js.map +1 -1
  193. package/dist/esm/utils/children.js +33 -0
  194. package/dist/esm/utils/children.js.map +6 -0
  195. package/dist/esm/utils/children.mjs +19 -0
  196. package/dist/esm/utils/children.mjs.map +1 -0
  197. package/dist/esm/utils/children.native.js +46 -0
  198. package/dist/esm/utils/children.native.js.map +1 -0
  199. package/dist/esm/utils/style.js +8 -0
  200. package/dist/esm/utils/style.js.map +6 -0
  201. package/dist/esm/utils/style.mjs +5 -0
  202. package/dist/esm/utils/style.mjs.map +1 -0
  203. package/dist/esm/utils/style.native.js +5 -0
  204. package/dist/esm/utils/style.native.js.map +1 -0
  205. package/package.json +9 -9
  206. package/src/__mocks__/@react-navigation/native-stack.ts +32 -0
  207. package/src/__mocks__/@react-navigation/native.ts +21 -0
  208. package/src/__mocks__/expo-linking.ts +6 -0
  209. package/src/__mocks__/expo-modules-core.ts +11 -0
  210. package/src/__mocks__/react-native-screens.ts +17 -0
  211. package/src/__mocks__/react-native.ts +20 -0
  212. package/src/fork/NavigationContainer.tsx +2 -0
  213. package/src/index.ts +10 -0
  214. package/src/layouts/Stack.tsx +7 -1
  215. package/src/layouts/stack-utils/README.md +211 -0
  216. package/src/layouts/stack-utils/StackHeaderBackButton.tsx +34 -0
  217. package/src/layouts/stack-utils/StackHeaderComponent.tsx +123 -0
  218. package/src/layouts/stack-utils/StackHeaderLeft.tsx +29 -0
  219. package/src/layouts/stack-utils/StackHeaderRight.tsx +29 -0
  220. package/src/layouts/stack-utils/StackHeaderSearchBar.tsx +21 -0
  221. package/src/layouts/stack-utils/StackHeaderTitle.tsx +72 -0
  222. package/src/layouts/stack-utils/StackScreen.tsx +66 -0
  223. package/src/layouts/stack-utils/__tests__/composition.test.tsx +634 -0
  224. package/src/layouts/stack-utils/index.tsx +35 -0
  225. package/src/layouts/withLayoutContext.tsx +3 -2
  226. package/src/router/router.ts +1 -1
  227. package/src/utils/children.ts +72 -0
  228. package/src/utils/style.ts +17 -0
  229. package/types/__mocks__/@react-navigation/native-stack.d.ts +30 -0
  230. package/types/__mocks__/@react-navigation/native-stack.d.ts.map +1 -0
  231. package/types/__mocks__/@react-navigation/native.d.ts +17 -0
  232. package/types/__mocks__/@react-navigation/native.d.ts.map +1 -0
  233. package/types/__mocks__/expo-linking.d.ts +9 -0
  234. package/types/__mocks__/expo-linking.d.ts.map +1 -0
  235. package/types/__mocks__/expo-modules-core.d.ts +11 -0
  236. package/types/__mocks__/expo-modules-core.d.ts.map +1 -0
  237. package/types/__mocks__/react-native-screens.d.ts +14 -0
  238. package/types/__mocks__/react-native-screens.d.ts.map +1 -0
  239. package/types/__mocks__/react-native.d.ts +12 -0
  240. package/types/__mocks__/react-native.d.ts.map +1 -0
  241. package/types/fork/NavigationContainer.d.ts.map +1 -1
  242. package/types/index.d.ts +1 -0
  243. package/types/index.d.ts.map +1 -1
  244. package/types/layouts/Stack.d.ts +10 -0
  245. package/types/layouts/Stack.d.ts.map +1 -1
  246. package/types/layouts/stack-utils/StackHeaderBackButton.d.ts +17 -0
  247. package/types/layouts/stack-utils/StackHeaderBackButton.d.ts.map +1 -0
  248. package/types/layouts/stack-utils/StackHeaderComponent.d.ts +36 -0
  249. package/types/layouts/stack-utils/StackHeaderComponent.d.ts.map +1 -0
  250. package/types/layouts/stack-utils/StackHeaderLeft.d.ts +13 -0
  251. package/types/layouts/stack-utils/StackHeaderLeft.d.ts.map +1 -0
  252. package/types/layouts/stack-utils/StackHeaderRight.d.ts +13 -0
  253. package/types/layouts/stack-utils/StackHeaderRight.d.ts.map +1 -0
  254. package/types/layouts/stack-utils/StackHeaderSearchBar.d.ts +10 -0
  255. package/types/layouts/stack-utils/StackHeaderSearchBar.d.ts.map +1 -0
  256. package/types/layouts/stack-utils/StackHeaderTitle.d.ts +26 -0
  257. package/types/layouts/stack-utils/StackHeaderTitle.d.ts.map +1 -0
  258. package/types/layouts/stack-utils/StackScreen.d.ts +22 -0
  259. package/types/layouts/stack-utils/StackScreen.d.ts.map +1 -0
  260. package/types/layouts/stack-utils/index.d.ts +20 -0
  261. package/types/layouts/stack-utils/index.d.ts.map +1 -0
  262. package/types/layouts/withLayoutContext.d.ts.map +1 -1
  263. package/types/utils/children.d.ts +23 -0
  264. package/types/utils/children.d.ts.map +1 -0
  265. package/types/utils/style.d.ts +7 -0
  266. package/types/utils/style.d.ts.map +1 -0
@@ -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,123 @@
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 { StackHeaderRight, appendStackHeaderRightPropsToOptions } from './StackHeaderRight'
12
+ import {
13
+ appendStackHeaderSearchBarPropsToOptions,
14
+ StackHeaderSearchBar,
15
+ } from './StackHeaderSearchBar'
16
+ import { appendStackHeaderTitlePropsToOptions, StackHeaderTitle } from './StackHeaderTitle'
17
+ import { isChildOfType } from '../../utils/children'
18
+
19
+ export interface StackHeaderProps {
20
+ children?: ReactNode
21
+ hidden?: boolean
22
+ asChild?: boolean
23
+ blurEffect?: ScreenStackHeaderConfigProps['blurEffect']
24
+ style?: StyleProp<{
25
+ color?: ColorValue
26
+ backgroundColor?: ScreenStackHeaderConfigProps['backgroundColor']
27
+ shadowColor?: undefined | 'transparent'
28
+ }>
29
+ largeStyle?: StyleProp<{
30
+ backgroundColor?: ScreenStackHeaderConfigProps['largeTitleBackgroundColor']
31
+ shadowColor?: undefined | 'transparent'
32
+ }>
33
+ }
34
+
35
+ /**
36
+ * Configuration component for stack headers.
37
+ * Use child components to configure different parts of the header.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * <Stack.Header blurEffect="regular">
42
+ * <Stack.Header.Title large>My Title</Stack.Header.Title>
43
+ * <Stack.Header.Right asChild>
44
+ * <Button>Action</Button>
45
+ * </Stack.Header.Right>
46
+ * </Stack.Header>
47
+ * ```
48
+ */
49
+ export function StackHeaderComponent(_props: StackHeaderProps) {
50
+ return null
51
+ }
52
+
53
+ export function appendStackHeaderPropsToOptions(
54
+ options: NativeStackNavigationOptions,
55
+ props: StackHeaderProps
56
+ ): NativeStackNavigationOptions {
57
+ const flattenedStyle = StyleSheet.flatten(props.style)
58
+ const flattenedLargeStyle = StyleSheet.flatten(props.largeStyle)
59
+
60
+ if (props.hidden) {
61
+ return { ...options, headerShown: false }
62
+ }
63
+
64
+ if (props.asChild) {
65
+ return { ...options, header: () => props.children }
66
+ }
67
+
68
+ const isTransparent = flattenedStyle?.backgroundColor === 'transparent'
69
+ const hasCustomShadow = flattenedStyle?.shadowColor !== undefined
70
+ const hasBackgroundColor = flattenedStyle?.backgroundColor !== undefined
71
+ const hasLargeBackgroundColor = flattenedLargeStyle?.backgroundColor !== undefined
72
+
73
+ let updatedOptions: NativeStackNavigationOptions = {
74
+ ...options,
75
+ headerShown: !props.hidden,
76
+ headerBlurEffect: props.blurEffect,
77
+ // Set headerTransparent when backgroundColor is 'transparent'
78
+ // This works on both iOS and Android for normal headers
79
+ // Note: When using SearchBar on iOS, if you don't have a ScrollView with
80
+ // contentInsetAdjustmentBehavior="automatic", set headerTransparent: false in options
81
+ ...(isTransparent && { headerTransparent: true }),
82
+ // Only set header styles when explicitly configured to avoid interfering with native defaults
83
+ ...(hasBackgroundColor && {
84
+ headerStyle: { backgroundColor: flattenedStyle.backgroundColor as string },
85
+ }),
86
+ ...(hasLargeBackgroundColor && {
87
+ headerLargeStyle: { backgroundColor: flattenedLargeStyle.backgroundColor as string },
88
+ }),
89
+ // Only set shadow visibility when explicitly configured
90
+ ...(hasCustomShadow && { headerShadowVisible: flattenedStyle?.shadowColor !== 'transparent' }),
91
+ ...(flattenedLargeStyle?.shadowColor !== undefined && {
92
+ headerLargeTitleShadowVisible: flattenedLargeStyle?.shadowColor !== 'transparent',
93
+ }),
94
+ }
95
+
96
+ function appendChildOptions(child: React.ReactElement, options: NativeStackNavigationOptions) {
97
+ let result = options
98
+ if (isChildOfType(child, StackHeaderTitle)) {
99
+ result = appendStackHeaderTitlePropsToOptions(result, child.props)
100
+ } else if (isChildOfType(child, StackHeaderLeft)) {
101
+ result = appendStackHeaderLeftPropsToOptions(result, child.props)
102
+ } else if (isChildOfType(child, StackHeaderRight)) {
103
+ result = appendStackHeaderRightPropsToOptions(result, child.props)
104
+ } else if (isChildOfType(child, StackHeaderBackButton)) {
105
+ result = appendStackHeaderBackButtonPropsToOptions(result, child.props)
106
+ } else if (isChildOfType(child, StackHeaderSearchBar)) {
107
+ result = appendStackHeaderSearchBarPropsToOptions(result, child.props)
108
+ } else {
109
+ console.warn(
110
+ `Warning: Unknown child element passed to Stack.Header: ${(child.type as { name: string }).name ?? child.type}`
111
+ )
112
+ }
113
+ return result
114
+ }
115
+
116
+ Children.forEach(props.children, (child) => {
117
+ if (isValidElement(child)) {
118
+ updatedOptions = appendChildOptions(child, updatedOptions)
119
+ }
120
+ })
121
+
122
+ return updatedOptions
123
+ }
@@ -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,72 @@
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
+ ? { fontWeight: convertFontWeightToStringFontWeight(flattenedLargeStyle.fontWeight) }
55
+ : {}),
56
+ }
57
+ : undefined
58
+
59
+ return {
60
+ ...options,
61
+ title: props.children,
62
+ headerLargeTitle: props.large,
63
+ // Large titles on iOS require headerTransparent for proper scroll behavior
64
+ // Only set on iOS since headerLargeTitle is iOS-only
65
+ ...(props.large && Platform.OS === 'ios' && { headerTransparent: true }),
66
+ headerTitleAlign: flattenedStyle?.textAlign,
67
+ // Only set styles when explicitly configured to avoid interfering with native defaults
68
+ ...(titleStyle && Object.keys(titleStyle).length > 0 && { headerTitleStyle: titleStyle }),
69
+ ...(largeTitleStyle &&
70
+ Object.keys(largeTitleStyle).length > 0 && { headerLargeTitleStyle: largeTitleStyle }),
71
+ }
72
+ }
@@ -0,0 +1,66 @@
1
+ 'use client'
2
+
3
+ import type { NativeStackNavigationOptions } from '@react-navigation/native-stack'
4
+ import { Children, isValidElement, useMemo, type PropsWithChildren } from 'react'
5
+
6
+ import {
7
+ StackHeaderComponent,
8
+ appendStackHeaderPropsToOptions,
9
+ type StackHeaderProps,
10
+ } from './StackHeaderComponent'
11
+ import { Screen } from '../../views/Screen'
12
+
13
+ export interface StackScreenProps extends PropsWithChildren {
14
+ name?: string
15
+ options?: NativeStackNavigationOptions
16
+ }
17
+
18
+ /**
19
+ * Stack screen component with support for compositional header configuration.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <Stack.Screen name="home" options={{ title: 'Home' }}>
24
+ * <Stack.Header>
25
+ * <Stack.Header.Title large>Welcome</Stack.Header.Title>
26
+ * <Stack.Header.SearchBar placeholder="Search..." />
27
+ * </Stack.Header>
28
+ * </Stack.Screen>
29
+ * ```
30
+ */
31
+ export function StackScreen({ children, options, ...rest }: StackScreenProps) {
32
+ const updatedOptions = useMemo(
33
+ () =>
34
+ appendScreenStackPropsToOptions(options ?? {}, {
35
+ children,
36
+ }),
37
+ [options, children]
38
+ )
39
+ return <Screen {...rest} options={updatedOptions} />
40
+ }
41
+
42
+ export function appendScreenStackPropsToOptions(
43
+ options: NativeStackNavigationOptions,
44
+ props: StackScreenProps
45
+ ): NativeStackNavigationOptions {
46
+ let updatedOptions = { ...options, ...props.options }
47
+
48
+ function appendChildOptions(child: React.ReactElement, options: NativeStackNavigationOptions) {
49
+ if (child.type === StackHeaderComponent) {
50
+ return appendStackHeaderPropsToOptions(options, child.props as StackHeaderProps)
51
+ } else {
52
+ console.warn(
53
+ `Warning: Unknown child element passed to Stack.Screen: ${(child.type as { name: string }).name ?? child.type}`
54
+ )
55
+ }
56
+ return options
57
+ }
58
+
59
+ Children.forEach(props.children, (child) => {
60
+ if (isValidElement(child)) {
61
+ updatedOptions = appendChildOptions(child, updatedOptions)
62
+ }
63
+ })
64
+
65
+ return updatedOptions
66
+ }