expo-router 5.2.0-canary-20250729-d8899ae → 6.0.0-beta.0

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 (215) hide show
  1. package/_ctx.android.js +1 -1
  2. package/_ctx.ios.js +1 -1
  3. package/_ctx.web.js +1 -1
  4. package/assets/modal.module.css +12 -3
  5. package/build/ExpoRoot.d.ts.map +1 -1
  6. package/build/ExpoRoot.js +12 -2
  7. package/build/ExpoRoot.js.map +1 -1
  8. package/build/Route.d.ts +9 -0
  9. package/build/Route.d.ts.map +1 -1
  10. package/build/Route.js.map +1 -1
  11. package/build/constants.d.ts +2 -0
  12. package/build/constants.d.ts.map +1 -1
  13. package/build/constants.js +3 -1
  14. package/build/constants.js.map +1 -1
  15. package/build/doctor/index.d.ts +1 -1
  16. package/build/doctor/index.d.ts.map +1 -1
  17. package/build/doctor/index.js +4 -1
  18. package/build/doctor/index.js.map +1 -1
  19. package/build/exports.d.ts +2 -2
  20. package/build/exports.d.ts.map +1 -1
  21. package/build/exports.js +6 -6
  22. package/build/exports.js.map +1 -1
  23. package/build/fork/native-stack/createNativeStackNavigator.d.ts +2 -2
  24. package/build/fork/native-stack/createNativeStackNavigator.d.ts.map +1 -1
  25. package/build/fork/native-stack/createNativeStackNavigator.js +82 -2
  26. package/build/fork/native-stack/createNativeStackNavigator.js.map +1 -1
  27. package/build/fork/useLinking.js +2 -2
  28. package/build/fork/useLinking.js.map +1 -1
  29. package/build/getLinkingConfig.d.ts +29 -2
  30. package/build/getLinkingConfig.d.ts.map +1 -1
  31. package/build/getLinkingConfig.js +35 -4
  32. package/build/getLinkingConfig.js.map +1 -1
  33. package/build/getRoutesCore.d.ts +1 -0
  34. package/build/getRoutesCore.d.ts.map +1 -1
  35. package/build/getRoutesCore.js +60 -0
  36. package/build/getRoutesCore.js.map +1 -1
  37. package/build/getServerManifest.d.ts +20 -1
  38. package/build/getServerManifest.d.ts.map +1 -1
  39. package/build/getServerManifest.js +8 -1
  40. package/build/getServerManifest.js.map +1 -1
  41. package/build/global-state/routeInfo.d.ts.map +1 -1
  42. package/build/global-state/routeInfo.js +12 -1
  43. package/build/global-state/routeInfo.js.map +1 -1
  44. package/build/global-state/router-store.d.ts.map +1 -1
  45. package/build/global-state/router-store.js +4 -0
  46. package/build/global-state/router-store.js.map +1 -1
  47. package/build/global-state/routing.d.ts +29 -1
  48. package/build/global-state/routing.d.ts.map +1 -1
  49. package/build/global-state/routing.js +78 -42
  50. package/build/global-state/routing.js.map +1 -1
  51. package/build/global-state/utils.d.ts +4 -0
  52. package/build/global-state/utils.d.ts.map +1 -0
  53. package/build/global-state/utils.js +29 -0
  54. package/build/global-state/utils.js.map +1 -0
  55. package/build/hooks.d.ts +1 -1
  56. package/build/hooks.d.ts.map +1 -1
  57. package/build/hooks.js +9 -4
  58. package/build/hooks.js.map +1 -1
  59. package/build/layouts/DrawerClient.d.ts +2 -2
  60. package/build/layouts/Stack.web.d.ts +1 -1
  61. package/build/layouts/Stack.web.d.ts.map +1 -1
  62. package/build/layouts/Stack.web.js +3 -3
  63. package/build/layouts/Stack.web.js.map +1 -1
  64. package/build/layouts/StackClient.d.ts +2 -2
  65. package/build/layouts/StackClient.d.ts.map +1 -1
  66. package/build/layouts/StackClient.js +18 -14
  67. package/build/layouts/StackClient.js.map +1 -1
  68. package/build/layouts/TabsClient.d.ts +3 -3
  69. package/build/layouts/withLayoutContext.d.ts.map +1 -1
  70. package/build/layouts/withLayoutContext.js +13 -0
  71. package/build/layouts/withLayoutContext.js.map +1 -1
  72. package/build/link/ExpoLink.d.ts.map +1 -1
  73. package/build/link/ExpoLink.js +3 -2
  74. package/build/link/ExpoLink.js.map +1 -1
  75. package/build/link/InternalLinkPreviewContext.d.ts +6 -0
  76. package/build/link/InternalLinkPreviewContext.d.ts.map +1 -0
  77. package/build/link/InternalLinkPreviewContext.js +6 -0
  78. package/build/link/InternalLinkPreviewContext.js.map +1 -0
  79. package/build/link/Link.d.ts +2 -67
  80. package/build/link/Link.d.ts.map +1 -1
  81. package/build/link/Link.js +5 -70
  82. package/build/link/Link.js.map +1 -1
  83. package/build/link/LinkWithPreview.d.ts +1 -46
  84. package/build/link/LinkWithPreview.d.ts.map +1 -1
  85. package/build/link/LinkWithPreview.js +30 -114
  86. package/build/link/LinkWithPreview.js.map +1 -1
  87. package/build/link/elements.d.ts +174 -0
  88. package/build/link/elements.d.ts.map +1 -0
  89. package/build/link/elements.js +172 -0
  90. package/build/link/elements.js.map +1 -0
  91. package/build/link/preview/HrefPreview.d.ts +1 -1
  92. package/build/link/preview/HrefPreview.d.ts.map +1 -1
  93. package/build/link/preview/HrefPreview.js +61 -7
  94. package/build/link/preview/HrefPreview.js.map +1 -1
  95. package/build/link/preview/LinkPreviewContext.d.ts +3 -2
  96. package/build/link/preview/LinkPreviewContext.d.ts.map +1 -1
  97. package/build/link/preview/LinkPreviewContext.js +3 -2
  98. package/build/link/preview/LinkPreviewContext.js.map +1 -1
  99. package/build/link/preview/native.d.ts +14 -6
  100. package/build/link/preview/native.d.ts.map +1 -1
  101. package/build/link/preview/native.js.map +1 -1
  102. package/build/link/preview/useNextScreenId.d.ts +8 -1
  103. package/build/link/preview/useNextScreenId.d.ts.map +1 -1
  104. package/build/link/preview/useNextScreenId.js +36 -32
  105. package/build/link/preview/useNextScreenId.js.map +1 -1
  106. package/build/link/preview/utils.d.ts +12 -0
  107. package/build/link/preview/utils.d.ts.map +1 -0
  108. package/build/link/preview/utils.js +66 -0
  109. package/build/link/preview/utils.js.map +1 -0
  110. package/build/modal/Modal.js +1 -1
  111. package/build/modal/Modal.js.map +1 -1
  112. package/build/modal/ModalsRenderer.js +1 -1
  113. package/build/modal/ModalsRenderer.js.map +1 -1
  114. package/build/modal/ModalsRenderer.web.js +4 -4
  115. package/build/modal/ModalsRenderer.web.js.map +1 -1
  116. package/build/modal/web/{ModalStack.web.d.ts → ModalStack.d.ts} +1 -1
  117. package/build/modal/web/ModalStack.d.ts.map +1 -0
  118. package/build/modal/web/{ModalStack.web.js → ModalStack.js} +5 -5
  119. package/build/modal/web/ModalStack.js.map +1 -0
  120. package/build/modal/web/{ModalStackRouteDrawer.web.d.ts → ModalStackRouteDrawer.d.ts} +1 -1
  121. package/build/modal/web/ModalStackRouteDrawer.d.ts.map +1 -0
  122. package/build/modal/web/{ModalStackRouteDrawer.web.js → ModalStackRouteDrawer.js} +1 -2
  123. package/build/modal/web/ModalStackRouteDrawer.js.map +1 -0
  124. package/build/modal/web/{TransparentModalStackRouteDrawer.web.d.ts → TransparentModalStackRouteDrawer.d.ts} +1 -1
  125. package/build/modal/web/TransparentModalStackRouteDrawer.d.ts.map +1 -0
  126. package/build/modal/web/{TransparentModalStackRouteDrawer.web.js → TransparentModalStackRouteDrawer.js} +1 -1
  127. package/build/modal/web/TransparentModalStackRouteDrawer.js.map +1 -0
  128. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.d.ts +17 -0
  129. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.d.ts.map +1 -0
  130. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.js +27 -0
  131. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.js.map +1 -0
  132. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.d.ts +3 -0
  133. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.d.ts.map +1 -0
  134. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.js +65 -0
  135. package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.js.map +1 -0
  136. package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.d.ts +47 -0
  137. package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.d.ts.map +1 -0
  138. package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js +153 -0
  139. package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js.map +1 -0
  140. package/build/native-tabs/NativeBottomTabs/NativeTabs.d.ts +24 -0
  141. package/build/native-tabs/NativeBottomTabs/NativeTabs.d.ts.map +1 -0
  142. package/build/native-tabs/NativeBottomTabs/NativeTabs.js +27 -0
  143. package/build/native-tabs/NativeBottomTabs/NativeTabs.js.map +1 -0
  144. package/build/native-tabs/NativeBottomTabs/NativeTabsView.d.ts +4 -0
  145. package/build/native-tabs/NativeBottomTabs/NativeTabsView.d.ts.map +1 -0
  146. package/build/native-tabs/NativeBottomTabs/NativeTabsView.js +116 -0
  147. package/build/native-tabs/NativeBottomTabs/NativeTabsView.js.map +1 -0
  148. package/build/native-tabs/NativeBottomTabs/types.d.ts +166 -0
  149. package/build/native-tabs/NativeBottomTabs/types.d.ts.map +1 -0
  150. package/build/native-tabs/NativeBottomTabs/types.js +3 -0
  151. package/build/native-tabs/NativeBottomTabs/types.js.map +1 -0
  152. package/build/native-tabs/NativeBottomTabs/utils.d.ts +7 -0
  153. package/build/native-tabs/NativeBottomTabs/utils.d.ts.map +1 -0
  154. package/build/native-tabs/NativeBottomTabs/utils.js +21 -0
  155. package/build/native-tabs/NativeBottomTabs/utils.js.map +1 -0
  156. package/build/native-tabs/common/elements.d.ts +74 -0
  157. package/build/native-tabs/common/elements.d.ts.map +1 -0
  158. package/build/native-tabs/common/elements.js +21 -0
  159. package/build/native-tabs/common/elements.js.map +1 -0
  160. package/build/native-tabs/index.d.ts +5 -0
  161. package/build/native-tabs/index.d.ts.map +1 -0
  162. package/build/native-tabs/index.js +23 -0
  163. package/build/native-tabs/index.js.map +1 -0
  164. package/build/routes-manifest.d.ts +42 -0
  165. package/build/routes-manifest.d.ts.map +1 -1
  166. package/build/routes-manifest.js.map +1 -1
  167. package/build/rsc/middleware.d.ts +1 -1
  168. package/build/rsc/middleware.d.ts.map +1 -1
  169. package/build/rsc/middleware.js.map +1 -1
  170. package/build/testing-library/mock-config.d.ts +18 -0
  171. package/build/testing-library/mock-config.d.ts.map +1 -1
  172. package/build/testing-library/mock-config.js +4 -1
  173. package/build/testing-library/mock-config.js.map +1 -1
  174. package/build/ui/common.d.ts.map +1 -1
  175. package/build/ui/common.js +7 -6
  176. package/build/ui/common.js.map +1 -1
  177. package/build/useNavigation.d.ts.map +1 -1
  178. package/build/useNavigation.js +8 -5
  179. package/build/useNavigation.js.map +1 -1
  180. package/build/views/NoSSR.d.ts +5 -0
  181. package/build/views/NoSSR.d.ts.map +1 -0
  182. package/build/views/NoSSR.js +22 -0
  183. package/build/views/NoSSR.js.map +1 -0
  184. package/build/views/Screen.d.ts.map +1 -1
  185. package/build/views/Screen.js +4 -1
  186. package/build/views/Screen.js.map +1 -1
  187. package/build/views/Sitemap.d.ts.map +1 -1
  188. package/build/views/Sitemap.js +113 -10
  189. package/build/views/Sitemap.js.map +1 -1
  190. package/build/views/Unmatched.d.ts.map +1 -1
  191. package/build/views/Unmatched.js +14 -4
  192. package/build/views/Unmatched.js.map +1 -1
  193. package/ios/ExpoHead.podspec +10 -1
  194. package/ios/LinkPreview/LinkPreviewNativeActionView.swift +159 -21
  195. package/ios/LinkPreview/LinkPreviewNativeModule.swift +44 -6
  196. package/ios/LinkPreview/LinkPreviewNativeNavigation.h +37 -11
  197. package/ios/LinkPreview/LinkPreviewNativeNavigation.mm +110 -87
  198. package/ios/LinkPreview/LinkPreviewNativeNavigation.swift +136 -0
  199. package/ios/LinkPreview/LinkPreviewNativePreviewView.swift +0 -1
  200. package/ios/LinkPreview/LinkPreviewNativeTriggerView.swift +1 -1
  201. package/ios/LinkPreview/LinkPreviewNativeView.swift +72 -71
  202. package/package.json +42 -10
  203. package/plugin/build/index.d.ts +2 -0
  204. package/plugin/options.json +5 -0
  205. package/plugin/src/index.ts +2 -0
  206. package/plugin/tsconfig.tsbuildinfo +1 -0
  207. package/server.d.ts +2 -1
  208. package/unstable-native-tabs.d.ts +1 -0
  209. package/unstable-native-tabs.js +1 -0
  210. package/build/modal/web/ModalStack.web.d.ts.map +0 -1
  211. package/build/modal/web/ModalStack.web.js.map +0 -1
  212. package/build/modal/web/ModalStackRouteDrawer.web.d.ts.map +0 -1
  213. package/build/modal/web/ModalStackRouteDrawer.web.js.map +0 -1
  214. package/build/modal/web/TransparentModalStackRouteDrawer.web.d.ts.map +0 -1
  215. package/build/modal/web/TransparentModalStackRouteDrawer.web.js.map +0 -1
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.NativeTabTrigger = NativeTabTrigger;
5
+ exports.convertTabPropsToOptions = convertTabPropsToOptions;
6
+ exports.isNativeTabTrigger = isNativeTabTrigger;
7
+ const native_1 = require("@react-navigation/native");
8
+ const react_1 = require("react");
9
+ const utils_1 = require("./utils");
10
+ const useSafeLayoutEffect_1 = require("../../views/useSafeLayoutEffect");
11
+ const elements_1 = require("../common/elements");
12
+ /**
13
+ * The component used to customize the native tab options both in the _layout file and from the tab screen.
14
+ *
15
+ * When used in the _layout file, you need to provide a `name` prop.
16
+ * When used in the tab screen, the `name` prop takes no effect.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // In _layout file
21
+ * import { NativeTabs } from 'expo-router/unstable-native-tabs';
22
+ *
23
+ * export default function Layout() {
24
+ * return (
25
+ * <NativeTabs>
26
+ * <NativeTabs.Trigger name="home" />
27
+ * <NativeTabs.Trigger name="settings" />
28
+ * </NativeTabs>
29
+ * );
30
+ * }
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * // In a tab screen
36
+ * import { NativeTabs } from 'expo-router/unstable-native-tabs';
37
+ *
38
+ * export default function HomeScreen() {
39
+ * return (
40
+ * <View>
41
+ * <NativeTabs.Trigger>
42
+ * <Label>Home</Label>
43
+ * </NativeTabs.Trigger>
44
+ * <Text>This is home screen!</Text>
45
+ * </View>
46
+ * );
47
+ * }
48
+ *
49
+ * **Note:** You can use the alias `NativeTabs.Trigger` for this component.
50
+ */
51
+ function NativeTabTrigger(props) {
52
+ const route = (0, native_1.useRoute)();
53
+ const navigation = (0, native_1.useNavigation)();
54
+ const isFocused = navigation.isFocused();
55
+ (0, useSafeLayoutEffect_1.useSafeLayoutEffect)(() => {
56
+ // This will cause the tab to update only when it is focused.
57
+ // As long as all tabs are loaded at the start, we don't need this check.
58
+ // It is here to ensure similar behavior to stack
59
+ if (isFocused) {
60
+ if (navigation.getState()?.type !== 'tab') {
61
+ throw new Error(`Trigger component can only be used in the tab screen. Current route: ${route.name}`);
62
+ }
63
+ const options = convertTabPropsToOptions(props);
64
+ navigation.setOptions(options);
65
+ }
66
+ }, [isFocused, props]);
67
+ return null;
68
+ }
69
+ function convertTabPropsToOptions({ options, hidden, children, disablePopToTop, disableScrollToTop, }) {
70
+ const initialOptions = {
71
+ ...options,
72
+ hidden: !!hidden,
73
+ specialEffects: {
74
+ repeatedTabSelection: {
75
+ popToRoot: !disablePopToTop,
76
+ scrollToTop: !disableScrollToTop,
77
+ },
78
+ },
79
+ };
80
+ const allowedChildren = (0, utils_1.filterAllowedChildrenElements)(children, [elements_1.Badge, elements_1.Label, elements_1.Icon]);
81
+ return allowedChildren.reduce((acc, child) => {
82
+ if ((0, utils_1.isChildOfType)(child, elements_1.Badge)) {
83
+ if (child.props.children) {
84
+ acc.badgeValue = String(child.props.children);
85
+ }
86
+ else if (!child.props.hidden) {
87
+ // If no value is provided, we set it to a space to show the badge
88
+ // Otherwise, the `react-native-screens` will interpret it as a hidden badge
89
+ // https://github.com/software-mansion/react-native-screens/blob/b4358fd95dd0736fc54df6bb97f210dc89edf24c/ios/bottom-tabs/RNSBottomTabsScreenComponentView.mm#L172
90
+ acc.badgeValue = ' ';
91
+ }
92
+ }
93
+ else if ((0, utils_1.isChildOfType)(child, elements_1.Label)) {
94
+ if (child.props.hidden) {
95
+ acc.title = '';
96
+ }
97
+ else {
98
+ acc.title = child.props.children;
99
+ }
100
+ }
101
+ else if ((0, utils_1.isChildOfType)(child, elements_1.Icon)) {
102
+ if ('src' in child.props || 'selectedSrc' in child.props) {
103
+ acc.icon = child.props.src
104
+ ? {
105
+ src: child.props.src,
106
+ }
107
+ : undefined;
108
+ acc.selectedIcon = child.props.selectedSrc
109
+ ? {
110
+ src: child.props.selectedSrc,
111
+ }
112
+ : undefined;
113
+ }
114
+ else if ('sf' in child.props || 'selectedSf' in child.props) {
115
+ if (process.env.EXPO_OS === 'ios') {
116
+ acc.icon = child.props.sf
117
+ ? {
118
+ sf: child.props.sf,
119
+ }
120
+ : undefined;
121
+ acc.selectedIcon = child.props.selectedSf
122
+ ? {
123
+ sf: child.props.selectedSf,
124
+ }
125
+ : undefined;
126
+ }
127
+ }
128
+ if (process.env.EXPO_OS === 'android') {
129
+ acc.icon = { drawable: child.props.drawable };
130
+ acc.selectedIcon = undefined;
131
+ }
132
+ }
133
+ return acc;
134
+ }, { ...initialOptions });
135
+ }
136
+ function isNativeTabTrigger(child, contextKey) {
137
+ if ((0, react_1.isValidElement)(child) && child && child.type === NativeTabTrigger) {
138
+ if (typeof child.props === 'object' &&
139
+ child.props &&
140
+ 'name' in child.props &&
141
+ !child.props.name) {
142
+ throw new Error(`<Trigger /> component in \`default export\` at \`app${contextKey}/_layout\` must have a \`name\` prop when used as a child of a Layout Route.`);
143
+ }
144
+ if (process.env.NODE_ENV !== 'production') {
145
+ if (['component', 'getComponent'].some((key) => child.props && typeof child.props === 'object' && key in child.props)) {
146
+ throw new Error(`<Trigger /> component in \`default export\` at \`app${contextKey}/_layout\` must not have a \`component\` or \`getComponent\` prop when used as a child of a Layout Route`);
147
+ }
148
+ }
149
+ return true;
150
+ }
151
+ return false;
152
+ }
153
+ //# sourceMappingURL=NativeTabTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeTabTrigger.js","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabTrigger.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useNavigation, useRoute } from '@react-navigation/native';\nimport { isValidElement, type ReactElement, type ReactNode } from 'react';\n\nimport type { ExtendedNativeTabOptions, NativeTabTriggerProps } from './types';\nimport { filterAllowedChildrenElements, isChildOfType } from './utils';\nimport { useSafeLayoutEffect } from '../../views/useSafeLayoutEffect';\nimport { Icon, Badge, Label } from '../common/elements';\n\n/**\n * The component used to customize the native tab options both in the _layout file and from the tab screen.\n *\n * When used in the _layout file, you need to provide a `name` prop.\n * When used in the tab screen, the `name` prop takes no effect.\n *\n * @example\n * ```tsx\n * // In _layout file\n * import { NativeTabs } from 'expo-router/unstable-native-tabs';\n *\n * export default function Layout() {\n * return (\n * <NativeTabs>\n * <NativeTabs.Trigger name=\"home\" />\n * <NativeTabs.Trigger name=\"settings\" />\n * </NativeTabs>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // In a tab screen\n * import { NativeTabs } from 'expo-router/unstable-native-tabs';\n *\n * export default function HomeScreen() {\n * return (\n * <View>\n * <NativeTabs.Trigger>\n * <Label>Home</Label>\n * </NativeTabs.Trigger>\n * <Text>This is home screen!</Text>\n * </View>\n * );\n * }\n *\n * **Note:** You can use the alias `NativeTabs.Trigger` for this component.\n */\nexport function NativeTabTrigger(props: NativeTabTriggerProps) {\n const route = useRoute();\n const navigation = useNavigation();\n const isFocused = navigation.isFocused();\n\n useSafeLayoutEffect(() => {\n // This will cause the tab to update only when it is focused.\n // As long as all tabs are loaded at the start, we don't need this check.\n // It is here to ensure similar behavior to stack\n if (isFocused) {\n if (navigation.getState()?.type !== 'tab') {\n throw new Error(\n `Trigger component can only be used in the tab screen. Current route: ${route.name}`\n );\n }\n const options = convertTabPropsToOptions(props);\n navigation.setOptions(options);\n }\n }, [isFocused, props]);\n\n return null;\n}\n\nexport function convertTabPropsToOptions({\n options,\n hidden,\n children,\n disablePopToTop,\n disableScrollToTop,\n}: NativeTabTriggerProps) {\n const initialOptions: ExtendedNativeTabOptions = {\n ...options,\n hidden: !!hidden,\n specialEffects: {\n repeatedTabSelection: {\n popToRoot: !disablePopToTop,\n scrollToTop: !disableScrollToTop,\n },\n },\n };\n const allowedChildren = filterAllowedChildrenElements(children, [Badge, Label, Icon]);\n return allowedChildren.reduce<ExtendedNativeTabOptions>(\n (acc, child) => {\n if (isChildOfType(child, Badge)) {\n if (child.props.children) {\n acc.badgeValue = String(child.props.children);\n } else if (!child.props.hidden) {\n // If no value is provided, we set it to a space to show the badge\n // Otherwise, the `react-native-screens` will interpret it as a hidden badge\n // https://github.com/software-mansion/react-native-screens/blob/b4358fd95dd0736fc54df6bb97f210dc89edf24c/ios/bottom-tabs/RNSBottomTabsScreenComponentView.mm#L172\n acc.badgeValue = ' ';\n }\n } else if (isChildOfType(child, Label)) {\n if (child.props.hidden) {\n acc.title = '';\n } else {\n acc.title = child.props.children;\n }\n } else if (isChildOfType(child, Icon)) {\n if ('src' in child.props || 'selectedSrc' in child.props) {\n acc.icon = child.props.src\n ? {\n src: child.props.src,\n }\n : undefined;\n acc.selectedIcon = child.props.selectedSrc\n ? {\n src: child.props.selectedSrc,\n }\n : undefined;\n } else if ('sf' in child.props || 'selectedSf' in child.props) {\n if (process.env.EXPO_OS === 'ios') {\n acc.icon = child.props.sf\n ? {\n sf: child.props.sf,\n }\n : undefined;\n acc.selectedIcon = child.props.selectedSf\n ? {\n sf: child.props.selectedSf,\n }\n : undefined;\n }\n }\n if (process.env.EXPO_OS === 'android') {\n acc.icon = { drawable: child.props.drawable };\n acc.selectedIcon = undefined;\n }\n }\n return acc;\n },\n { ...initialOptions }\n );\n}\n\nexport function isNativeTabTrigger(\n child: ReactNode,\n contextKey?: string\n): child is ReactElement<NativeTabTriggerProps & { name: string }> {\n if (isValidElement(child) && child && child.type === NativeTabTrigger) {\n if (\n typeof child.props === 'object' &&\n child.props &&\n 'name' in child.props &&\n !child.props.name\n ) {\n throw new Error(\n `<Trigger /> component in \\`default export\\` at \\`app${contextKey}/_layout\\` must have a \\`name\\` prop when used as a child of a Layout Route.`\n );\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (\n ['component', 'getComponent'].some(\n (key) => child.props && typeof child.props === 'object' && key in child.props\n )\n ) {\n throw new Error(\n `<Trigger /> component in \\`default export\\` at \\`app${contextKey}/_layout\\` must not have a \\`component\\` or \\`getComponent\\` prop when used as a child of a Layout Route`\n );\n }\n }\n\n return true;\n }\n\n return false;\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import { NativeTabTrigger } from './NativeTabTrigger';
2
+ import type { NativeTabsProps } from './types';
3
+ /**
4
+ * The component used to create native tabs layout.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * // In _layout file
9
+ * import { NativeTabs } from 'expo-router/unstable-native-tabs';
10
+ *
11
+ * export default function Layout() {
12
+ * return (
13
+ * <NativeTabs>
14
+ * <NativeTabs.Trigger name="home" />
15
+ * <NativeTabs.Trigger name="settings" />
16
+ * </NativeTabs>
17
+ * );
18
+ * }
19
+ * ```
20
+ */
21
+ export declare const NativeTabs: ((props: NativeTabsProps) => import("react").JSX.Element) & {
22
+ Trigger: typeof NativeTabTrigger;
23
+ };
24
+ //# sourceMappingURL=NativeTabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeTabs.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabs.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,WACb,eAAe;;CAIxB,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NativeTabs = void 0;
4
+ const NativeBottomTabsNavigator_1 = require("./NativeBottomTabsNavigator");
5
+ const NativeTabTrigger_1 = require("./NativeTabTrigger");
6
+ /**
7
+ * The component used to create native tabs layout.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // In _layout file
12
+ * import { NativeTabs } from 'expo-router/unstable-native-tabs';
13
+ *
14
+ * export default function Layout() {
15
+ * return (
16
+ * <NativeTabs>
17
+ * <NativeTabs.Trigger name="home" />
18
+ * <NativeTabs.Trigger name="settings" />
19
+ * </NativeTabs>
20
+ * );
21
+ * }
22
+ * ```
23
+ */
24
+ exports.NativeTabs = Object.assign((props) => {
25
+ return <NativeBottomTabsNavigator_1.NativeTabsNavigatorWithContext {...props}/>;
26
+ }, { Trigger: NativeTabTrigger_1.NativeTabTrigger });
27
+ //# sourceMappingURL=NativeTabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeTabs.js","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabs.tsx"],"names":[],"mappings":";;;AAAA,2EAA6E;AAC7E,yDAAsD;AAGtD;;;;;;;;;;;;;;;;;GAiBG;AACU,QAAA,UAAU,GAAG,MAAM,CAAC,MAAM,CACrC,CAAC,KAAsB,EAAE,EAAE;IACzB,OAAO,CAAC,0DAA8B,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACvD,CAAC,EACD,EAAE,OAAO,EAAE,mCAAgB,EAAE,CAC9B,CAAC","sourcesContent":["import { NativeTabsNavigatorWithContext } from './NativeBottomTabsNavigator';\nimport { NativeTabTrigger } from './NativeTabTrigger';\nimport type { NativeTabsProps } from './types';\n\n/**\n * The component used to create native tabs layout.\n *\n * @example\n * ```tsx\n * // In _layout file\n * import { NativeTabs } from 'expo-router/unstable-native-tabs';\n *\n * export default function Layout() {\n * return (\n * <NativeTabs>\n * <NativeTabs.Trigger name=\"home\" />\n * <NativeTabs.Trigger name=\"settings\" />\n * </NativeTabs>\n * );\n * }\n * ```\n */\nexport const NativeTabs = Object.assign(\n (props: NativeTabsProps) => {\n return <NativeTabsNavigatorWithContext {...props} />;\n },\n { Trigger: NativeTabTrigger }\n);\n"]}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { NativeTabsViewProps } from './types';
3
+ export declare function NativeTabsView(props: NativeTabsViewProps): React.JSX.Element;
4
+ //# sourceMappingURL=NativeTabsView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeTabsView.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabsView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAStC,OAAO,KAAK,EAAoB,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAYrE,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,qBAkGxD"}
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.NativeTabsView = NativeTabsView;
37
+ const react_1 = __importStar(require("react"));
38
+ const react_native_screens_1 = require("react-native-screens");
39
+ const utils_1 = require("./utils");
40
+ const linking_1 = require("../../link/linking");
41
+ // We let native tabs to control the changes. This requires freeze to be disabled for tab bar.
42
+ // Otherwise user may see glitches when switching between tabs.
43
+ react_native_screens_1.featureFlags.experiment.controlledBottomTabs = false;
44
+ // TODO: ENG-16896: Enable freeze globally and disable only for NativeTabsView
45
+ (0, react_native_screens_1.enableFreeze)(false);
46
+ // TODO: Add support for dynamic params inside a route
47
+ function NativeTabsView(props) {
48
+ const { builder, style, minimizeBehavior, disableIndicator } = props;
49
+ const { state, descriptors, navigation } = builder;
50
+ const { routes } = state;
51
+ let focusedIndex = state.index;
52
+ const isAnyRouteFocused = routes[focusedIndex].key &&
53
+ descriptors[routes[focusedIndex].key] &&
54
+ (0, utils_1.shouldTabBeVisible)(descriptors[routes[focusedIndex].key].options);
55
+ if (!isAnyRouteFocused) {
56
+ if (process.env.NODE_ENV !== 'production') {
57
+ throw new Error(`The focused tab in NativeTabsView cannot be displayed. Make sure path is correct and the route is not hidden. Path: "${(0, linking_1.getPathFromState)(state)}"`);
58
+ }
59
+ // Set focusedIndex to the first visible tab
60
+ focusedIndex = routes.findIndex((route) => (0, utils_1.shouldTabBeVisible)(descriptors[route.key].options));
61
+ }
62
+ // This is flag that is set to true, when the transition is executed by native tab change
63
+ // In this case we don't need to change the isFocused of the screens, because the transition will happen on native side
64
+ const isDuringNativeTransition = (0, react_1.useRef)(false);
65
+ // This is the last index that was not part of a native transition, e.g navigation from link
66
+ const lastNotNativeTransitionIndex = (0, react_1.useRef)(focusedIndex);
67
+ // If the flag was set in the onNativeFocusChange handler, it will be still true here
68
+ // It is set to false, later in this function
69
+ // Thus if it is false, we know that the transition was not triggered by a native tab change
70
+ // and we need to reset the lastNotNativeTransitionIndex
71
+ if (!isDuringNativeTransition.current) {
72
+ lastNotNativeTransitionIndex.current = focusedIndex;
73
+ }
74
+ const children = routes
75
+ .map((route, index) => ({ route, index }))
76
+ .filter(({ route: { key } }) => (0, utils_1.shouldTabBeVisible)(descriptors[key].options))
77
+ .map(({ route, index }) => {
78
+ const descriptor = descriptors[route.key];
79
+ // In case of native transition we want to keep the last focused index
80
+ // Otherwise the lastNotNativeTransitionIndex is set to focusedIndex in the if above this statement
81
+ const isFocused = index === lastNotNativeTransitionIndex.current;
82
+ const title = descriptor.options.title ?? route.name;
83
+ return (<react_native_screens_1.BottomTabsScreen key={route.key} {...descriptor.options} iconResourceName={descriptor.options.icon?.drawable} icon={convertOptionsIconToPropsIcon(descriptor.options.icon)} selectedIcon={convertOptionsIconToPropsIcon(descriptor.options.selectedIcon)} title={title} tabKey={route.key} isFocused={isFocused}>
84
+ {descriptor.render()}
85
+ </react_native_screens_1.BottomTabsScreen>);
86
+ });
87
+ // The native render is over, we can reset the flag
88
+ isDuringNativeTransition.current = false;
89
+ return (<react_native_screens_1.BottomTabs tabBarItemTitleFontColor={style?.color} tabBarItemTitleFontFamily={style?.fontFamily} tabBarItemTitleFontSize={style?.fontSize} tabBarItemTitleFontWeight={style?.fontWeight} tabBarItemTitleFontStyle={style?.fontStyle} tabBarBackgroundColor={style?.backgroundColor} tabBarBlurEffect={style?.blurEffect} tabBarTintColor={style?.tintColor} tabBarItemBadgeBackgroundColor={style?.badgeBackgroundColor} tabBarItemRippleColor={style?.rippleColor} tabBarItemLabelVisibilityMode={style?.labelVisibilityMode} tabBarItemIconColor={style?.iconColor} tabBarItemIconColorActive={style?.['&:active']?.iconColor ?? style?.tintColor} tabBarItemTitleFontColorActive={style?.['&:active']?.color ?? style?.tintColor} tabBarItemTitleFontSizeActive={style?.['&:active']?.fontSize} tabBarItemActiveIndicatorColor={style?.['&:active']?.indicatorColor} tabBarItemActiveIndicatorEnabled={!disableIndicator} tabBarMinimizeBehavior={minimizeBehavior} onNativeFocusChange={({ nativeEvent: { tabKey } }) => {
90
+ const descriptor = descriptors[tabKey];
91
+ const route = descriptor.route;
92
+ navigation.dispatch({
93
+ type: 'JUMP_TO',
94
+ target: state.key,
95
+ payload: {
96
+ name: route.name,
97
+ },
98
+ });
99
+ isDuringNativeTransition.current = true;
100
+ }}>
101
+ {children}
102
+ </react_native_screens_1.BottomTabs>);
103
+ }
104
+ function convertOptionsIconToPropsIcon(icon) {
105
+ if (!icon) {
106
+ return undefined;
107
+ }
108
+ if ('sf' in icon && icon.sf) {
109
+ return { sfSymbolName: icon.sf };
110
+ }
111
+ else if ('src' in icon && icon.src) {
112
+ return { templateSource: icon.src };
113
+ }
114
+ return undefined;
115
+ }
116
+ //# sourceMappingURL=NativeTabsView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeTabsView.js","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabsView.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useRef } from 'react';\nimport {\n BottomTabs,\n BottomTabsScreen,\n enableFreeze,\n featureFlags,\n type BottomTabsScreenProps,\n} from 'react-native-screens';\n\nimport type { NativeTabOptions, NativeTabsViewProps } from './types';\nimport { shouldTabBeVisible } from './utils';\nimport { getPathFromState } from '../../link/linking';\n\n// We let native tabs to control the changes. This requires freeze to be disabled for tab bar.\n// Otherwise user may see glitches when switching between tabs.\nfeatureFlags.experiment.controlledBottomTabs = false;\n\n// TODO: ENG-16896: Enable freeze globally and disable only for NativeTabsView\nenableFreeze(false);\n\n// TODO: Add support for dynamic params inside a route\nexport function NativeTabsView(props: NativeTabsViewProps) {\n const { builder, style, minimizeBehavior, disableIndicator } = props;\n const { state, descriptors, navigation } = builder;\n const { routes } = state;\n\n let focusedIndex = state.index;\n const isAnyRouteFocused =\n routes[focusedIndex].key &&\n descriptors[routes[focusedIndex].key] &&\n shouldTabBeVisible(descriptors[routes[focusedIndex].key].options);\n\n if (!isAnyRouteFocused) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The focused tab in NativeTabsView cannot be displayed. Make sure path is correct and the route is not hidden. Path: \"${getPathFromState(state)}\"`\n );\n }\n // Set focusedIndex to the first visible tab\n focusedIndex = routes.findIndex((route) => shouldTabBeVisible(descriptors[route.key].options));\n }\n\n // This is flag that is set to true, when the transition is executed by native tab change\n // In this case we don't need to change the isFocused of the screens, because the transition will happen on native side\n const isDuringNativeTransition = useRef<boolean>(false);\n // This is the last index that was not part of a native transition, e.g navigation from link\n const lastNotNativeTransitionIndex = useRef<number>(focusedIndex);\n\n // If the flag was set in the onNativeFocusChange handler, it will be still true here\n // It is set to false, later in this function\n // Thus if it is false, we know that the transition was not triggered by a native tab change\n // and we need to reset the lastNotNativeTransitionIndex\n if (!isDuringNativeTransition.current) {\n lastNotNativeTransitionIndex.current = focusedIndex;\n }\n\n const children = routes\n .map((route, index) => ({ route, index }))\n .filter(({ route: { key } }) => shouldTabBeVisible(descriptors[key].options))\n .map(({ route, index }) => {\n const descriptor = descriptors[route.key];\n // In case of native transition we want to keep the last focused index\n // Otherwise the lastNotNativeTransitionIndex is set to focusedIndex in the if above this statement\n const isFocused = index === lastNotNativeTransitionIndex.current;\n const title = descriptor.options.title ?? route.name;\n\n return (\n <BottomTabsScreen\n key={route.key}\n {...descriptor.options}\n iconResourceName={descriptor.options.icon?.drawable}\n icon={convertOptionsIconToPropsIcon(descriptor.options.icon)}\n selectedIcon={convertOptionsIconToPropsIcon(descriptor.options.selectedIcon)}\n title={title}\n tabKey={route.key}\n isFocused={isFocused}>\n {descriptor.render()}\n </BottomTabsScreen>\n );\n });\n\n // The native render is over, we can reset the flag\n isDuringNativeTransition.current = false;\n\n return (\n <BottomTabs\n tabBarItemTitleFontColor={style?.color}\n tabBarItemTitleFontFamily={style?.fontFamily}\n tabBarItemTitleFontSize={style?.fontSize}\n tabBarItemTitleFontWeight={style?.fontWeight}\n tabBarItemTitleFontStyle={style?.fontStyle}\n tabBarBackgroundColor={style?.backgroundColor}\n tabBarBlurEffect={style?.blurEffect}\n tabBarTintColor={style?.tintColor}\n tabBarItemBadgeBackgroundColor={style?.badgeBackgroundColor}\n tabBarItemRippleColor={style?.rippleColor}\n tabBarItemLabelVisibilityMode={style?.labelVisibilityMode}\n tabBarItemIconColor={style?.iconColor}\n tabBarItemIconColorActive={style?.['&:active']?.iconColor ?? style?.tintColor}\n tabBarItemTitleFontColorActive={style?.['&:active']?.color ?? style?.tintColor}\n tabBarItemTitleFontSizeActive={style?.['&:active']?.fontSize}\n tabBarItemActiveIndicatorColor={style?.['&:active']?.indicatorColor}\n tabBarItemActiveIndicatorEnabled={!disableIndicator}\n tabBarMinimizeBehavior={minimizeBehavior}\n onNativeFocusChange={({ nativeEvent: { tabKey } }) => {\n const descriptor = descriptors[tabKey];\n const route = descriptor.route;\n navigation.dispatch({\n type: 'JUMP_TO',\n target: state.key,\n payload: {\n name: route.name,\n },\n });\n isDuringNativeTransition.current = true;\n }}>\n {children}\n </BottomTabs>\n );\n}\n\nfunction convertOptionsIconToPropsIcon(\n icon: NativeTabOptions['icon']\n): BottomTabsScreenProps['icon'] {\n if (!icon) {\n return undefined;\n }\n if ('sf' in icon && icon.sf) {\n return { sfSymbolName: icon.sf };\n } else if ('src' in icon && icon.src) {\n return { templateSource: icon.src };\n }\n return undefined;\n}\n"]}
@@ -0,0 +1,166 @@
1
+ import type { DefaultRouterOptions, ParamListBase, TabNavigationState, TabRouterOptions, useNavigationBuilder } from '@react-navigation/native';
2
+ import type { PropsWithChildren } from 'react';
3
+ import type { ColorValue, ImageSourcePropType, TextStyle } from 'react-native';
4
+ import type { BottomTabsProps, BottomTabsScreenProps, TabBarItemLabelVisibilityMode } from 'react-native-screens';
5
+ import type { SFSymbol } from 'sf-symbols-typescript';
6
+ export type NativeTabOptions = Omit<BottomTabsScreenProps, 'children' | 'placeholder' | 'onWillAppear' | 'onDidAppear' | 'onWillDisappear' | 'onDidDisappear' | 'isFocused' | 'tabKey' | 'icon' | 'selectedIcon' | 'iconResourceName' | 'specialEffects'> & DefaultRouterOptions & {
7
+ /**
8
+ * The icon to display in the tab bar.
9
+ * @platform android
10
+ * @platform iOS
11
+ */
12
+ icon?: SfSymbolOrImageSource & {
13
+ /**
14
+ * The name of the drawable resource to use as an icon.
15
+ * @platform android
16
+ */
17
+ drawable?: string;
18
+ };
19
+ /**
20
+ * The icon to display when the tab is selected.
21
+ * @platform iOS
22
+ */
23
+ selectedIcon?: SfSymbolOrImageSource;
24
+ };
25
+ export type SfSymbolOrImageSource = {
26
+ /**
27
+ * The name of the SF Symbol to use as an icon.
28
+ * @platform iOS
29
+ */
30
+ sf?: SFSymbol;
31
+ } | {
32
+ /**
33
+ * The image source to use as an icon.
34
+ * @platform iOS
35
+ */
36
+ src?: ImageSourcePropType;
37
+ };
38
+ export interface ExtendedNativeTabOptions extends NativeTabOptions {
39
+ /**
40
+ * If true, the tab will be hidden from the tab bar.
41
+ */
42
+ hidden?: boolean;
43
+ specialEffects?: BottomTabsScreenProps['specialEffects'];
44
+ }
45
+ export interface NativeTabsStyleType {
46
+ fontFamily?: TextStyle['fontFamily'];
47
+ fontSize?: TextStyle['fontSize'];
48
+ fontWeight?: TextStyle['fontWeight'];
49
+ fontStyle?: TextStyle['fontStyle'];
50
+ color?: TextStyle['color'];
51
+ /**
52
+ * @platform android
53
+ * @platform iOS
54
+ */
55
+ iconColor?: ColorValue;
56
+ backgroundColor?: ColorValue;
57
+ /**
58
+ * @platform iOS
59
+ */
60
+ blurEffect?: BottomTabsScreenProps['tabBarBlurEffect'];
61
+ tintColor?: ColorValue;
62
+ badgeBackgroundColor?: ColorValue;
63
+ /**
64
+ * @platform android
65
+ */
66
+ rippleColor?: ColorValue;
67
+ /**
68
+ * @platform android
69
+ */
70
+ labelVisibilityMode?: TabBarItemLabelVisibilityMode;
71
+ /**
72
+ * @platform android
73
+ */
74
+ '&:active'?: NativeTabsActiveStyleType;
75
+ }
76
+ export interface NativeTabsActiveStyleType {
77
+ /**
78
+ * @platform android
79
+ */
80
+ color?: ColorValue;
81
+ /**
82
+ * @platform android
83
+ */
84
+ fontSize?: TextStyle['fontSize'];
85
+ /**
86
+ * @platform android
87
+ */
88
+ iconColor?: ColorValue;
89
+ /**
90
+ * @platform android
91
+ */
92
+ indicatorColor?: ColorValue;
93
+ }
94
+ export interface NativeTabsProps extends PropsWithChildren {
95
+ style?: NativeTabsStyleType;
96
+ /**
97
+ * https://developer.apple.com/documentation/uikit/uitabbarcontroller/tabbarminimizebehavior
98
+ *
99
+ * Supported values:
100
+ * - `none` - The tab bar does not minimize.
101
+ * - `onScrollUp` - The tab bar minimizes when scrolling up, and expands when scrolling back down. Recommended if the scroll view content is aligned to the bottom.
102
+ * - `onScrollDown` - The tab bar minimizes when scrolling down, and expands when scrolling back up.
103
+ * - `automatic` - Resolves to the system default minimize behavior.
104
+ *
105
+ * @default automatic
106
+ *
107
+ * @platform iOS 26
108
+ */
109
+ minimizeBehavior?: BottomTabsProps['tabBarMinimizeBehavior'];
110
+ /**
111
+ * Disables the active indicator for the tab bar.
112
+ *
113
+ * @platform android
114
+ */
115
+ disableIndicator?: boolean;
116
+ /**
117
+ * The behavior when navigating back with the back button.
118
+ *
119
+ * @platform android
120
+ */
121
+ backBehavior?: 'none' | 'initialRoute' | 'history';
122
+ }
123
+ export interface NativeTabsViewProps extends NativeTabsProps {
124
+ builder: ReturnType<typeof useNavigationBuilder<TabNavigationState<ParamListBase>, TabRouterOptions, Record<string, (...args: any) => void>, NativeTabOptions, Record<string, any>>>;
125
+ }
126
+ export interface NativeTabTriggerProps {
127
+ /**
128
+ * The name of the route.
129
+ *
130
+ * This is required when used inside a Layout component.
131
+ *
132
+ * When used in a route it has no effect.
133
+ */
134
+ name?: string;
135
+ /**
136
+ * If true, the tab will be hidden from the tab bar.
137
+ */
138
+ hidden?: boolean;
139
+ /**
140
+ * The options for the trigger.
141
+ *
142
+ * Use `Icon`, `Label`, and `Badge` components as children to customize the tab, rather then raw options.
143
+ */
144
+ options?: NativeTabOptions;
145
+ /**
146
+ * If true, the tab will not pop stack to the root when selected again.
147
+ * @default false
148
+ *
149
+ * @platform ios
150
+ */
151
+ disablePopToTop?: boolean;
152
+ /**
153
+ * If true, the tab will not scroll to the top when selected again.
154
+ * @default false
155
+ *
156
+ * @platform ios
157
+ */
158
+ disableScrollToTop?: boolean;
159
+ /**
160
+ * The children of the trigger.
161
+ *
162
+ * Use `Icon`, `Label`, and `Badge` components to customize the tab.
163
+ */
164
+ children?: React.ReactNode;
165
+ }
166
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n DefaultRouterOptions,\n ParamListBase,\n TabNavigationState,\n TabRouterOptions,\n useNavigationBuilder,\n} from '@react-navigation/native';\nimport type { PropsWithChildren } from 'react';\nimport type { ColorValue, ImageSourcePropType, TextStyle } from 'react-native';\nimport type {\n BottomTabsProps,\n BottomTabsScreenProps,\n TabBarItemLabelVisibilityMode,\n} from 'react-native-screens';\nimport type { SFSymbol } from 'sf-symbols-typescript';\n\nexport type NativeTabOptions = Omit<\n BottomTabsScreenProps,\n | 'children'\n | 'placeholder'\n | 'onWillAppear'\n | 'onDidAppear'\n | 'onWillDisappear'\n | 'onDidDisappear'\n | 'isFocused'\n | 'tabKey'\n | 'icon'\n | 'selectedIcon'\n | 'iconResourceName'\n | 'specialEffects'\n> &\n DefaultRouterOptions & {\n /**\n * The icon to display in the tab bar.\n * @platform android\n * @platform iOS\n */\n icon?: SfSymbolOrImageSource & {\n /**\n * The name of the drawable resource to use as an icon.\n * @platform android\n */\n drawable?: string;\n };\n /**\n * The icon to display when the tab is selected.\n * @platform iOS\n */\n selectedIcon?: SfSymbolOrImageSource;\n };\n\nexport type SfSymbolOrImageSource =\n | {\n /**\n * The name of the SF Symbol to use as an icon.\n * @platform iOS\n */\n sf?: SFSymbol;\n }\n | {\n /**\n * The image source to use as an icon.\n * @platform iOS\n */\n src?: ImageSourcePropType;\n };\n\nexport interface ExtendedNativeTabOptions extends NativeTabOptions {\n /**\n * If true, the tab will be hidden from the tab bar.\n */\n hidden?: boolean;\n specialEffects?: BottomTabsScreenProps['specialEffects'];\n}\n\nexport interface NativeTabsStyleType {\n fontFamily?: TextStyle['fontFamily'];\n fontSize?: TextStyle['fontSize'];\n fontWeight?: TextStyle['fontWeight'];\n fontStyle?: TextStyle['fontStyle'];\n color?: TextStyle['color'];\n /**\n * @platform android\n * @platform iOS\n */\n iconColor?: ColorValue;\n backgroundColor?: ColorValue;\n /**\n * @platform iOS\n */\n blurEffect?: BottomTabsScreenProps['tabBarBlurEffect'];\n tintColor?: ColorValue;\n badgeBackgroundColor?: ColorValue;\n /**\n * @platform android\n */\n rippleColor?: ColorValue;\n /**\n * @platform android\n */\n labelVisibilityMode?: TabBarItemLabelVisibilityMode;\n /**\n * @platform android\n */\n '&:active'?: NativeTabsActiveStyleType;\n}\n\nexport interface NativeTabsActiveStyleType {\n /**\n * @platform android\n */\n color?: ColorValue;\n /**\n * @platform android\n */\n fontSize?: TextStyle['fontSize'];\n /**\n * @platform android\n */\n iconColor?: ColorValue;\n /**\n * @platform android\n */\n indicatorColor?: ColorValue;\n}\n\nexport interface NativeTabsProps extends PropsWithChildren {\n style?: NativeTabsStyleType;\n /**\n * https://developer.apple.com/documentation/uikit/uitabbarcontroller/tabbarminimizebehavior\n *\n * Supported values:\n * - `none` - The tab bar does not minimize.\n * - `onScrollUp` - The tab bar minimizes when scrolling up, and expands when scrolling back down. Recommended if the scroll view content is aligned to the bottom.\n * - `onScrollDown` - The tab bar minimizes when scrolling down, and expands when scrolling back up.\n * - `automatic` - Resolves to the system default minimize behavior.\n *\n * @default automatic\n *\n * @platform iOS 26\n */\n minimizeBehavior?: BottomTabsProps['tabBarMinimizeBehavior'];\n /**\n * Disables the active indicator for the tab bar.\n *\n * @platform android\n */\n disableIndicator?: boolean;\n /**\n * The behavior when navigating back with the back button.\n *\n * @platform android\n */\n backBehavior?: 'none' | 'initialRoute' | 'history';\n}\n\nexport interface NativeTabsViewProps extends NativeTabsProps {\n builder: ReturnType<\n typeof useNavigationBuilder<\n TabNavigationState<ParamListBase>,\n TabRouterOptions,\n Record<string, (...args: any) => void>,\n NativeTabOptions,\n Record<string, any>\n >\n >;\n}\n\nexport interface NativeTabTriggerProps {\n /**\n * The name of the route.\n *\n * This is required when used inside a Layout component.\n *\n * When used in a route it has no effect.\n */\n name?: string;\n /**\n * If true, the tab will be hidden from the tab bar.\n */\n hidden?: boolean;\n /**\n * The options for the trigger.\n *\n * Use `Icon`, `Label`, and `Badge` components as children to customize the tab, rather then raw options.\n */\n options?: NativeTabOptions;\n /**\n * If true, the tab will not pop stack to the root when selected again.\n * @default false\n *\n * @platform ios\n */\n disablePopToTop?: boolean;\n /**\n * If true, the tab will not scroll to the top when selected again.\n * @default false\n *\n * @platform ios\n */\n disableScrollToTop?: boolean;\n /**\n * The children of the trigger.\n *\n * Use `Icon`, `Label`, and `Badge` components to customize the tab.\n */\n children?: React.ReactNode;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { JSXElementConstructor, ReactNode } from 'react';
2
+ import React from 'react';
3
+ import type { ExtendedNativeTabOptions } from './types';
4
+ export declare function filterAllowedChildrenElements<Components extends JSXElementConstructor<any>[]>(children: ReactNode | ReactNode[], components: Components): React.ReactElement<React.ComponentProps<Components[number]>, Components[number]>[];
5
+ export declare function isChildOfType<T extends JSXElementConstructor<any>>(child: ReactNode, type: T): child is React.ReactElement<React.ComponentProps<T>, T>;
6
+ export declare function shouldTabBeVisible(options: ExtendedNativeTabOptions): boolean;
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAExD,wBAAgB,6BAA6B,CAAC,UAAU,SAAS,qBAAqB,CAAC,GAAG,CAAC,EAAE,EAC3F,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,EACjC,UAAU,EAAE,UAAU,GACrB,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAOpF;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,qBAAqB,CAAC,GAAG,CAAC,EAChE,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,CAAC,GACN,KAAK,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAI7E"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.filterAllowedChildrenElements = filterAllowedChildrenElements;
7
+ exports.isChildOfType = isChildOfType;
8
+ exports.shouldTabBeVisible = shouldTabBeVisible;
9
+ const react_1 = __importDefault(require("react"));
10
+ function filterAllowedChildrenElements(children, components) {
11
+ return react_1.default.Children.toArray(children).filter((child) => react_1.default.isValidElement(child) && components.includes(child.type));
12
+ }
13
+ function isChildOfType(child, type) {
14
+ return react_1.default.isValidElement(child) && child.type === type;
15
+ }
16
+ function shouldTabBeVisible(options) {
17
+ // The <NativeTab.Trigger> always sets `hidden` to defined boolean value.
18
+ // If it is not defined, then it was not specified, and we should hide the tab.
19
+ return options.hidden === false;
20
+ }
21
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/utils.ts"],"names":[],"mappings":";;;;;AAKA,sEAUC;AAED,sCAKC;AAED,gDAIC;AA3BD,kDAA0B;AAI1B,SAAgB,6BAA6B,CAC3C,QAAiC,EACjC,UAAsB;IAEtB,OAAO,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAC5C,CACE,KAAK,EACsF,EAAE,CAC7F,eAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAiC,CAAC,CAC9F,CAAC;AACJ,CAAC;AAED,SAAgB,aAAa,CAC3B,KAAgB,EAChB,IAAO;IAEP,OAAO,eAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AAC5D,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAiC;IAClE,yEAAyE;IACzE,+EAA+E;IAC/E,OAAO,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC;AAClC,CAAC","sourcesContent":["import type { JSXElementConstructor, ReactNode } from 'react';\nimport React from 'react';\n\nimport type { ExtendedNativeTabOptions } from './types';\n\nexport function filterAllowedChildrenElements<Components extends JSXElementConstructor<any>[]>(\n children: ReactNode | ReactNode[],\n components: Components\n): React.ReactElement<React.ComponentProps<Components[number]>, Components[number]>[] {\n return React.Children.toArray(children).filter(\n (\n child\n ): child is React.ReactElement<React.ComponentProps<Components[number]>, Components[number]> =>\n React.isValidElement(child) && components.includes(child.type as (props: any) => ReactNode)\n );\n}\n\nexport function isChildOfType<T extends JSXElementConstructor<any>>(\n child: ReactNode,\n type: T\n): child is React.ReactElement<React.ComponentProps<T>, T> {\n return React.isValidElement(child) && child.type === type;\n}\n\nexport function shouldTabBeVisible(options: ExtendedNativeTabOptions): boolean {\n // The <NativeTab.Trigger> always sets `hidden` to defined boolean value.\n // If it is not defined, then it was not specified, and we should hide the tab.\n return options.hidden === false;\n}\n"]}