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.
- package/_ctx.android.js +1 -1
- package/_ctx.ios.js +1 -1
- package/_ctx.web.js +1 -1
- package/assets/modal.module.css +12 -3
- package/build/ExpoRoot.d.ts.map +1 -1
- package/build/ExpoRoot.js +12 -2
- package/build/ExpoRoot.js.map +1 -1
- package/build/Route.d.ts +9 -0
- package/build/Route.d.ts.map +1 -1
- package/build/Route.js.map +1 -1
- package/build/constants.d.ts +2 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +3 -1
- package/build/constants.js.map +1 -1
- package/build/doctor/index.d.ts +1 -1
- package/build/doctor/index.d.ts.map +1 -1
- package/build/doctor/index.js +4 -1
- package/build/doctor/index.js.map +1 -1
- package/build/exports.d.ts +2 -2
- package/build/exports.d.ts.map +1 -1
- package/build/exports.js +6 -6
- package/build/exports.js.map +1 -1
- package/build/fork/native-stack/createNativeStackNavigator.d.ts +2 -2
- package/build/fork/native-stack/createNativeStackNavigator.d.ts.map +1 -1
- package/build/fork/native-stack/createNativeStackNavigator.js +82 -2
- package/build/fork/native-stack/createNativeStackNavigator.js.map +1 -1
- package/build/fork/useLinking.js +2 -2
- package/build/fork/useLinking.js.map +1 -1
- package/build/getLinkingConfig.d.ts +29 -2
- package/build/getLinkingConfig.d.ts.map +1 -1
- package/build/getLinkingConfig.js +35 -4
- package/build/getLinkingConfig.js.map +1 -1
- package/build/getRoutesCore.d.ts +1 -0
- package/build/getRoutesCore.d.ts.map +1 -1
- package/build/getRoutesCore.js +60 -0
- package/build/getRoutesCore.js.map +1 -1
- package/build/getServerManifest.d.ts +20 -1
- package/build/getServerManifest.d.ts.map +1 -1
- package/build/getServerManifest.js +8 -1
- package/build/getServerManifest.js.map +1 -1
- package/build/global-state/routeInfo.d.ts.map +1 -1
- package/build/global-state/routeInfo.js +12 -1
- package/build/global-state/routeInfo.js.map +1 -1
- package/build/global-state/router-store.d.ts.map +1 -1
- package/build/global-state/router-store.js +4 -0
- package/build/global-state/router-store.js.map +1 -1
- package/build/global-state/routing.d.ts +29 -1
- package/build/global-state/routing.d.ts.map +1 -1
- package/build/global-state/routing.js +78 -42
- package/build/global-state/routing.js.map +1 -1
- package/build/global-state/utils.d.ts +4 -0
- package/build/global-state/utils.d.ts.map +1 -0
- package/build/global-state/utils.js +29 -0
- package/build/global-state/utils.js.map +1 -0
- package/build/hooks.d.ts +1 -1
- package/build/hooks.d.ts.map +1 -1
- package/build/hooks.js +9 -4
- package/build/hooks.js.map +1 -1
- package/build/layouts/DrawerClient.d.ts +2 -2
- package/build/layouts/Stack.web.d.ts +1 -1
- package/build/layouts/Stack.web.d.ts.map +1 -1
- package/build/layouts/Stack.web.js +3 -3
- package/build/layouts/Stack.web.js.map +1 -1
- package/build/layouts/StackClient.d.ts +2 -2
- package/build/layouts/StackClient.d.ts.map +1 -1
- package/build/layouts/StackClient.js +18 -14
- package/build/layouts/StackClient.js.map +1 -1
- package/build/layouts/TabsClient.d.ts +3 -3
- package/build/layouts/withLayoutContext.d.ts.map +1 -1
- package/build/layouts/withLayoutContext.js +13 -0
- package/build/layouts/withLayoutContext.js.map +1 -1
- package/build/link/ExpoLink.d.ts.map +1 -1
- package/build/link/ExpoLink.js +3 -2
- package/build/link/ExpoLink.js.map +1 -1
- package/build/link/InternalLinkPreviewContext.d.ts +6 -0
- package/build/link/InternalLinkPreviewContext.d.ts.map +1 -0
- package/build/link/InternalLinkPreviewContext.js +6 -0
- package/build/link/InternalLinkPreviewContext.js.map +1 -0
- package/build/link/Link.d.ts +2 -67
- package/build/link/Link.d.ts.map +1 -1
- package/build/link/Link.js +5 -70
- package/build/link/Link.js.map +1 -1
- package/build/link/LinkWithPreview.d.ts +1 -46
- package/build/link/LinkWithPreview.d.ts.map +1 -1
- package/build/link/LinkWithPreview.js +30 -114
- package/build/link/LinkWithPreview.js.map +1 -1
- package/build/link/elements.d.ts +174 -0
- package/build/link/elements.d.ts.map +1 -0
- package/build/link/elements.js +172 -0
- package/build/link/elements.js.map +1 -0
- package/build/link/preview/HrefPreview.d.ts +1 -1
- package/build/link/preview/HrefPreview.d.ts.map +1 -1
- package/build/link/preview/HrefPreview.js +61 -7
- package/build/link/preview/HrefPreview.js.map +1 -1
- package/build/link/preview/LinkPreviewContext.d.ts +3 -2
- package/build/link/preview/LinkPreviewContext.d.ts.map +1 -1
- package/build/link/preview/LinkPreviewContext.js +3 -2
- package/build/link/preview/LinkPreviewContext.js.map +1 -1
- package/build/link/preview/native.d.ts +14 -6
- package/build/link/preview/native.d.ts.map +1 -1
- package/build/link/preview/native.js.map +1 -1
- package/build/link/preview/useNextScreenId.d.ts +8 -1
- package/build/link/preview/useNextScreenId.d.ts.map +1 -1
- package/build/link/preview/useNextScreenId.js +36 -32
- package/build/link/preview/useNextScreenId.js.map +1 -1
- package/build/link/preview/utils.d.ts +12 -0
- package/build/link/preview/utils.d.ts.map +1 -0
- package/build/link/preview/utils.js +66 -0
- package/build/link/preview/utils.js.map +1 -0
- package/build/modal/Modal.js +1 -1
- package/build/modal/Modal.js.map +1 -1
- package/build/modal/ModalsRenderer.js +1 -1
- package/build/modal/ModalsRenderer.js.map +1 -1
- package/build/modal/ModalsRenderer.web.js +4 -4
- package/build/modal/ModalsRenderer.web.js.map +1 -1
- package/build/modal/web/{ModalStack.web.d.ts → ModalStack.d.ts} +1 -1
- package/build/modal/web/ModalStack.d.ts.map +1 -0
- package/build/modal/web/{ModalStack.web.js → ModalStack.js} +5 -5
- package/build/modal/web/ModalStack.js.map +1 -0
- package/build/modal/web/{ModalStackRouteDrawer.web.d.ts → ModalStackRouteDrawer.d.ts} +1 -1
- package/build/modal/web/ModalStackRouteDrawer.d.ts.map +1 -0
- package/build/modal/web/{ModalStackRouteDrawer.web.js → ModalStackRouteDrawer.js} +1 -2
- package/build/modal/web/ModalStackRouteDrawer.js.map +1 -0
- package/build/modal/web/{TransparentModalStackRouteDrawer.web.d.ts → TransparentModalStackRouteDrawer.d.ts} +1 -1
- package/build/modal/web/TransparentModalStackRouteDrawer.d.ts.map +1 -0
- package/build/modal/web/{TransparentModalStackRouteDrawer.web.js → TransparentModalStackRouteDrawer.js} +1 -1
- package/build/modal/web/TransparentModalStackRouteDrawer.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.d.ts +17 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.js +27 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.d.ts +3 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.js +65 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.d.ts +47 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js +153 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabs.d.ts +24 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabs.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabs.js +27 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabs.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.d.ts +4 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.js +116 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/types.d.ts +166 -0
- package/build/native-tabs/NativeBottomTabs/types.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/types.js +3 -0
- package/build/native-tabs/NativeBottomTabs/types.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/utils.d.ts +7 -0
- package/build/native-tabs/NativeBottomTabs/utils.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/utils.js +21 -0
- package/build/native-tabs/NativeBottomTabs/utils.js.map +1 -0
- package/build/native-tabs/common/elements.d.ts +74 -0
- package/build/native-tabs/common/elements.d.ts.map +1 -0
- package/build/native-tabs/common/elements.js +21 -0
- package/build/native-tabs/common/elements.js.map +1 -0
- package/build/native-tabs/index.d.ts +5 -0
- package/build/native-tabs/index.d.ts.map +1 -0
- package/build/native-tabs/index.js +23 -0
- package/build/native-tabs/index.js.map +1 -0
- package/build/routes-manifest.d.ts +42 -0
- package/build/routes-manifest.d.ts.map +1 -1
- package/build/routes-manifest.js.map +1 -1
- package/build/rsc/middleware.d.ts +1 -1
- package/build/rsc/middleware.d.ts.map +1 -1
- package/build/rsc/middleware.js.map +1 -1
- package/build/testing-library/mock-config.d.ts +18 -0
- package/build/testing-library/mock-config.d.ts.map +1 -1
- package/build/testing-library/mock-config.js +4 -1
- package/build/testing-library/mock-config.js.map +1 -1
- package/build/ui/common.d.ts.map +1 -1
- package/build/ui/common.js +7 -6
- package/build/ui/common.js.map +1 -1
- package/build/useNavigation.d.ts.map +1 -1
- package/build/useNavigation.js +8 -5
- package/build/useNavigation.js.map +1 -1
- package/build/views/NoSSR.d.ts +5 -0
- package/build/views/NoSSR.d.ts.map +1 -0
- package/build/views/NoSSR.js +22 -0
- package/build/views/NoSSR.js.map +1 -0
- package/build/views/Screen.d.ts.map +1 -1
- package/build/views/Screen.js +4 -1
- package/build/views/Screen.js.map +1 -1
- package/build/views/Sitemap.d.ts.map +1 -1
- package/build/views/Sitemap.js +113 -10
- package/build/views/Sitemap.js.map +1 -1
- package/build/views/Unmatched.d.ts.map +1 -1
- package/build/views/Unmatched.js +14 -4
- package/build/views/Unmatched.js.map +1 -1
- package/ios/ExpoHead.podspec +10 -1
- package/ios/LinkPreview/LinkPreviewNativeActionView.swift +159 -21
- package/ios/LinkPreview/LinkPreviewNativeModule.swift +44 -6
- package/ios/LinkPreview/LinkPreviewNativeNavigation.h +37 -11
- package/ios/LinkPreview/LinkPreviewNativeNavigation.mm +110 -87
- package/ios/LinkPreview/LinkPreviewNativeNavigation.swift +136 -0
- package/ios/LinkPreview/LinkPreviewNativePreviewView.swift +0 -1
- package/ios/LinkPreview/LinkPreviewNativeTriggerView.swift +1 -1
- package/ios/LinkPreview/LinkPreviewNativeView.swift +72 -71
- package/package.json +42 -10
- package/plugin/build/index.d.ts +2 -0
- package/plugin/options.json +5 -0
- package/plugin/src/index.ts +2 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/server.d.ts +2 -1
- package/unstable-native-tabs.d.ts +1 -0
- package/unstable-native-tabs.js +1 -0
- package/build/modal/web/ModalStack.web.d.ts.map +0 -1
- package/build/modal/web/ModalStack.web.js.map +0 -1
- package/build/modal/web/ModalStackRouteDrawer.web.d.ts.map +0 -1
- package/build/modal/web/ModalStackRouteDrawer.web.js.map +0 -1
- package/build/modal/web/TransparentModalStackRouteDrawer.web.d.ts.map +0 -1
- 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 @@
|
|
|
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 @@
|
|
|
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"]}
|