expo-router 6.0.0-beta.0 → 6.0.0-beta.10
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/assets/modal.module.css +15 -14
- package/assets/native-tabs.module.css +109 -0
- package/build/ExpoRoot.d.ts.map +1 -1
- package/build/ExpoRoot.js +0 -2
- package/build/ExpoRoot.js.map +1 -1
- package/build/fork/NavigationContainer.d.ts.map +1 -1
- package/build/fork/NavigationContainer.js +2 -0
- package/build/fork/NavigationContainer.js.map +1 -1
- package/build/fork/extractPathFromURL.d.ts.map +1 -1
- package/build/fork/extractPathFromURL.js +4 -0
- package/build/fork/extractPathFromURL.js.map +1 -1
- package/build/fork/getPathFromState.d.ts.map +1 -1
- package/build/fork/getPathFromState.js +2 -0
- package/build/fork/getPathFromState.js.map +1 -1
- package/build/global-state/routing.d.ts +6 -5
- package/build/global-state/routing.d.ts.map +1 -1
- package/build/global-state/routing.js +20 -14
- package/build/global-state/routing.js.map +1 -1
- package/build/head/ExpoHead.android.d.ts +1 -3
- package/build/imperative-api.d.ts +3 -1
- package/build/imperative-api.d.ts.map +1 -1
- package/build/imperative-api.js +4 -4
- package/build/imperative-api.js.map +1 -1
- package/build/layouts/DrawerClient.d.ts +2 -12
- package/build/layouts/DrawerClient.d.ts.map +1 -1
- package/build/layouts/StackClient.d.ts +14 -19
- package/build/layouts/StackClient.d.ts.map +1 -1
- package/build/layouts/StackClient.js +27 -25
- package/build/layouts/StackClient.js.map +1 -1
- package/build/layouts/TabsClient.d.ts +3 -18
- package/build/layouts/TabsClient.d.ts.map +1 -1
- package/build/layouts/withLayoutContext.d.ts +5 -1
- package/build/layouts/withLayoutContext.d.ts.map +1 -1
- package/build/layouts/withLayoutContext.js +19 -6
- package/build/layouts/withLayoutContext.js.map +1 -1
- package/build/link/ExpoLink.d.ts.map +1 -1
- package/build/link/ExpoLink.js +4 -1
- package/build/link/ExpoLink.js.map +1 -1
- package/build/link/LinkWithPreview.d.ts.map +1 -1
- package/build/link/LinkWithPreview.js +19 -24
- package/build/link/LinkWithPreview.js.map +1 -1
- package/build/link/elements.d.ts +2 -10
- package/build/link/elements.d.ts.map +1 -1
- package/build/link/elements.js +1 -1
- package/build/link/elements.js.map +1 -1
- package/build/link/preview/native.d.ts +0 -2
- package/build/link/preview/native.d.ts.map +1 -1
- package/build/link/preview/native.js +1 -11
- package/build/link/preview/native.js.map +1 -1
- package/build/link/preview/utils.d.ts.map +1 -1
- package/build/link/preview/utils.js +5 -2
- package/build/link/preview/utils.js.map +1 -1
- package/build/modal/web/ModalStackRouteDrawer.js +9 -10
- package/build/modal/web/ModalStackRouteDrawer.js.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.d.ts +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.d.ts.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.js +61 -9
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsNavigator.js.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.d.ts.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.js +6 -27
- package/build/native-tabs/NativeBottomTabs/NativeBottomTabsRouter.js.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.d.ts +11 -3
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.d.ts.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js +154 -62
- package/build/native-tabs/NativeBottomTabs/NativeTabTrigger.js.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabs.d.ts +3 -2
- package/build/native-tabs/NativeBottomTabs/NativeTabs.d.ts.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabsTriggerTabBar.d.ts +24 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsTriggerTabBar.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsTriggerTabBar.js +28 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsTriggerTabBar.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.d.ts +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.d.ts.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.js +114 -38
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.js.map +1 -1
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.web.d.ts +4 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.web.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.web.js +158 -0
- package/build/native-tabs/NativeBottomTabs/NativeTabsView.web.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/appearance.d.ts +20 -0
- package/build/native-tabs/NativeBottomTabs/appearance.d.ts.map +1 -0
- package/build/native-tabs/NativeBottomTabs/appearance.js +119 -0
- package/build/native-tabs/NativeBottomTabs/appearance.js.map +1 -0
- package/build/native-tabs/NativeBottomTabs/types.d.ts +312 -46
- package/build/native-tabs/NativeBottomTabs/types.d.ts.map +1 -1
- package/build/native-tabs/NativeBottomTabs/types.js +51 -0
- package/build/native-tabs/NativeBottomTabs/types.js.map +1 -1
- package/build/native-tabs/common/elements.d.ts +84 -21
- package/build/native-tabs/common/elements.d.ts.map +1 -1
- package/build/native-tabs/common/elements.js +23 -0
- package/build/native-tabs/common/elements.js.map +1 -1
- package/build/native-tabs/index.d.ts +2 -1
- package/build/native-tabs/index.d.ts.map +1 -1
- package/build/native-tabs/index.js +3 -1
- package/build/native-tabs/index.js.map +1 -1
- package/build/navigationParams.d.ts +9 -0
- package/build/navigationParams.d.ts.map +1 -0
- package/build/navigationParams.js +67 -0
- package/build/navigationParams.js.map +1 -0
- package/build/rsc/router/client.d.ts +1 -3
- package/build/rsc/router/client.d.ts.map +1 -1
- package/build/testing-library/index.d.ts +15 -4
- package/build/testing-library/index.d.ts.map +1 -1
- package/build/testing-library/index.js +31 -28
- package/build/testing-library/index.js.map +1 -1
- package/build/testing-library/mocks.js +0 -7
- package/build/testing-library/mocks.js.map +1 -1
- package/build/typed-routes/generate.d.ts +2 -1
- package/build/typed-routes/generate.d.ts.map +1 -1
- package/build/typed-routes/generate.js +3 -1
- package/build/typed-routes/generate.js.map +1 -1
- package/build/ui/Slot.d.ts +5 -1
- package/build/ui/Slot.d.ts.map +1 -1
- package/build/ui/Slot.js.map +1 -1
- package/build/ui/TabContext.d.ts +11 -21
- package/build/ui/TabContext.d.ts.map +1 -1
- package/build/ui/TabRouter.d.ts +7 -0
- package/build/ui/TabRouter.d.ts.map +1 -1
- package/build/ui/Tabs.d.ts +14 -23
- package/build/ui/Tabs.d.ts.map +1 -1
- package/build/ui/Tabs.js +1 -1
- package/build/ui/Tabs.js.map +1 -1
- package/build/ui/common.d.ts +2 -3
- package/build/ui/common.d.ts.map +1 -1
- package/build/ui/common.js +1 -3
- package/build/ui/common.js.map +1 -1
- package/build/useFocusEffect.js +1 -1
- package/build/useFocusEffect.js.map +1 -1
- package/build/useScreens.d.ts +1 -1
- package/build/useScreens.d.ts.map +1 -1
- package/build/useScreens.js +6 -4
- package/build/useScreens.js.map +1 -1
- package/ios/ExpoHead.podspec +2 -0
- package/ios/LinkPreview/LinkPreviewNativeModule.swift +7 -9
- package/ios/LinkPreview/LinkPreviewNativeView.swift +13 -28
- package/package.json +22 -24
- package/plugin/build/index.js +1 -1
- package/plugin/src/index.ts +1 -1
- package/ios/LinkPreview/LinkPreviewNativeTriggerView.swift +0 -9
- package/plugin/tsconfig.tsbuildinfo +0 -1
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
'use client';
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.NativeTabTrigger =
|
|
4
|
+
exports.NativeTabTrigger = void 0;
|
|
5
5
|
exports.convertTabPropsToOptions = convertTabPropsToOptions;
|
|
6
|
+
exports.appendIconOptions = appendIconOptions;
|
|
6
7
|
exports.isNativeTabTrigger = isNativeTabTrigger;
|
|
7
8
|
const native_1 = require("@react-navigation/native");
|
|
8
9
|
const react_1 = require("react");
|
|
10
|
+
const NativeTabsTriggerTabBar_1 = require("./NativeTabsTriggerTabBar");
|
|
9
11
|
const utils_1 = require("./utils");
|
|
12
|
+
const PreviewRouteContext_1 = require("../../link/preview/PreviewRouteContext");
|
|
10
13
|
const useSafeLayoutEffect_1 = require("../../views/useSafeLayoutEffect");
|
|
11
14
|
const elements_1 = require("../common/elements");
|
|
12
15
|
/**
|
|
@@ -45,96 +48,185 @@ const elements_1 = require("../common/elements");
|
|
|
45
48
|
* </View>
|
|
46
49
|
* );
|
|
47
50
|
* }
|
|
51
|
+
* ```
|
|
48
52
|
*
|
|
49
|
-
* **Note:** You can use the alias `NativeTabs.Trigger` for this component.
|
|
53
|
+
* > **Note:** You can use the alias `NativeTabs.Trigger` for this component.
|
|
50
54
|
*/
|
|
51
|
-
function
|
|
55
|
+
function NativeTabTriggerImpl(props) {
|
|
52
56
|
const route = (0, native_1.useRoute)();
|
|
53
57
|
const navigation = (0, native_1.useNavigation)();
|
|
54
58
|
const isFocused = navigation.isFocused();
|
|
59
|
+
const isInPreview = (0, PreviewRouteContext_1.useIsPreview)();
|
|
55
60
|
(0, useSafeLayoutEffect_1.useSafeLayoutEffect)(() => {
|
|
56
61
|
// This will cause the tab to update only when it is focused.
|
|
57
62
|
// As long as all tabs are loaded at the start, we don't need this check.
|
|
58
63
|
// It is here to ensure similar behavior to stack
|
|
59
|
-
if (isFocused) {
|
|
64
|
+
if (isFocused && !isInPreview) {
|
|
60
65
|
if (navigation.getState()?.type !== 'tab') {
|
|
61
66
|
throw new Error(`Trigger component can only be used in the tab screen. Current route: ${route.name}`);
|
|
62
67
|
}
|
|
63
|
-
const options = convertTabPropsToOptions(props);
|
|
68
|
+
const options = convertTabPropsToOptions(props, true);
|
|
64
69
|
navigation.setOptions(options);
|
|
65
70
|
}
|
|
66
|
-
}, [isFocused, props]);
|
|
71
|
+
}, [isFocused, props, isInPreview]);
|
|
67
72
|
return null;
|
|
68
73
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
exports.NativeTabTrigger = Object.assign(NativeTabTriggerImpl, {
|
|
75
|
+
TabBar: NativeTabsTriggerTabBar_1.NativeTabsTriggerTabBar,
|
|
76
|
+
});
|
|
77
|
+
function convertTabPropsToOptions({ options, hidden, children, role, disablePopToTop, disableScrollToTop }, isDynamic = false) {
|
|
78
|
+
const initialOptions = isDynamic
|
|
79
|
+
? { ...options }
|
|
80
|
+
: {
|
|
81
|
+
...options,
|
|
82
|
+
hidden: !!hidden,
|
|
83
|
+
specialEffects: {
|
|
84
|
+
repeatedTabSelection: {
|
|
85
|
+
popToRoot: !disablePopToTop,
|
|
86
|
+
scrollToTop: !disableScrollToTop,
|
|
87
|
+
},
|
|
77
88
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const allowedChildren = (0, utils_1.filterAllowedChildrenElements)(children, [
|
|
89
|
+
role: role ?? options?.role,
|
|
90
|
+
};
|
|
91
|
+
const allowedChildren = (0, utils_1.filterAllowedChildrenElements)(children, [
|
|
92
|
+
elements_1.Badge,
|
|
93
|
+
elements_1.Label,
|
|
94
|
+
elements_1.Icon,
|
|
95
|
+
NativeTabsTriggerTabBar_1.NativeTabsTriggerTabBar,
|
|
96
|
+
]);
|
|
81
97
|
return allowedChildren.reduce((acc, child) => {
|
|
82
98
|
if ((0, utils_1.isChildOfType)(child, elements_1.Badge)) {
|
|
83
|
-
|
|
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
|
-
}
|
|
99
|
+
appendBadgeOptions(acc, child.props);
|
|
92
100
|
}
|
|
93
101
|
else if ((0, utils_1.isChildOfType)(child, elements_1.Label)) {
|
|
94
|
-
|
|
95
|
-
acc.title = '';
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
acc.title = child.props.children;
|
|
99
|
-
}
|
|
102
|
+
appendLabelOptions(acc, child.props);
|
|
100
103
|
}
|
|
101
104
|
else if ((0, utils_1.isChildOfType)(child, elements_1.Icon)) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
105
|
+
appendIconOptions(acc, child.props);
|
|
106
|
+
}
|
|
107
|
+
else if ((0, utils_1.isChildOfType)(child, NativeTabsTriggerTabBar_1.NativeTabsTriggerTabBar)) {
|
|
108
|
+
appendTabBarOptions(acc, child.props);
|
|
109
|
+
}
|
|
110
|
+
return acc;
|
|
111
|
+
}, { ...initialOptions });
|
|
112
|
+
}
|
|
113
|
+
function appendBadgeOptions(options, props) {
|
|
114
|
+
if (props.children) {
|
|
115
|
+
options.badgeValue = String(props.children);
|
|
116
|
+
options.selectedBadgeBackgroundColor = props.selectedBackgroundColor;
|
|
117
|
+
}
|
|
118
|
+
else if (!props.hidden) {
|
|
119
|
+
// If no value is provided, we set it to a space to show the badge
|
|
120
|
+
// Otherwise, the `react-native-screens` will interpret it as a hidden badge
|
|
121
|
+
// https://github.com/software-mansion/react-native-screens/blob/b4358fd95dd0736fc54df6bb97f210dc89edf24c/ios/bottom-tabs/RNSBottomTabsScreenComponentView.mm#L172
|
|
122
|
+
options.badgeValue = ' ';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function appendLabelOptions(options, props) {
|
|
126
|
+
if (props.hidden) {
|
|
127
|
+
options.title = '';
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
options.title = props.children;
|
|
131
|
+
options.selectedLabelStyle = props.selectedStyle;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function appendIconOptions(options, props) {
|
|
135
|
+
if ('src' in props && props.src) {
|
|
136
|
+
const icon = convertIconSrcToIconOption(props);
|
|
137
|
+
options.icon = icon?.icon;
|
|
138
|
+
options.selectedIcon = icon?.selectedIcon;
|
|
139
|
+
}
|
|
140
|
+
else if ('sf' in props && process.env.EXPO_OS === 'ios') {
|
|
141
|
+
if (typeof props.sf === 'string') {
|
|
142
|
+
options.icon = props.sf
|
|
143
|
+
? {
|
|
144
|
+
sf: props.sf,
|
|
145
|
+
}
|
|
146
|
+
: undefined;
|
|
147
|
+
options.selectedIcon = undefined;
|
|
148
|
+
}
|
|
149
|
+
else if (props.sf) {
|
|
150
|
+
options.icon = props.sf.default
|
|
151
|
+
? {
|
|
152
|
+
sf: props.sf.default,
|
|
153
|
+
}
|
|
154
|
+
: undefined;
|
|
155
|
+
options.selectedIcon = props.sf.selected
|
|
156
|
+
? {
|
|
157
|
+
sf: props.sf.selected,
|
|
126
158
|
}
|
|
159
|
+
: undefined;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if ('drawable' in props && process.env.EXPO_OS === 'android') {
|
|
163
|
+
options.icon = { drawable: props.drawable };
|
|
164
|
+
options.selectedIcon = undefined;
|
|
165
|
+
}
|
|
166
|
+
options.selectedIconColor = props.selectedColor;
|
|
167
|
+
}
|
|
168
|
+
function convertIconSrcToIconOption(icon) {
|
|
169
|
+
if (icon && icon.src) {
|
|
170
|
+
const { defaultIcon, selected } = typeof icon.src === 'object' && 'selected' in icon.src
|
|
171
|
+
? { defaultIcon: icon.src.default, selected: icon.src.selected }
|
|
172
|
+
: { defaultIcon: icon.src };
|
|
173
|
+
const options = {};
|
|
174
|
+
options.icon = convertSrcOrComponentToSrc(defaultIcon);
|
|
175
|
+
options.selectedIcon = convertSrcOrComponentToSrc(selected);
|
|
176
|
+
return options;
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
function convertSrcOrComponentToSrc(src) {
|
|
181
|
+
if (src) {
|
|
182
|
+
if ((0, react_1.isValidElement)(src)) {
|
|
183
|
+
if (src.type === elements_1.VectorIcon) {
|
|
184
|
+
const props = src.props;
|
|
185
|
+
return { src: props.family.getImageSource(props.name, 24, 'white') };
|
|
127
186
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
acc.selectedIcon = undefined;
|
|
187
|
+
else {
|
|
188
|
+
console.warn('Only VectorIcon is supported as a React element in Icon.src');
|
|
131
189
|
}
|
|
132
190
|
}
|
|
133
|
-
|
|
134
|
-
|
|
191
|
+
else {
|
|
192
|
+
return { src };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
function appendTabBarOptions(options, props) {
|
|
198
|
+
const { backgroundColor, blurEffect, iconColor, disableTransparentOnScrollEdge, badgeBackgroundColor, badgeTextColor, indicatorColor, labelStyle, } = props;
|
|
199
|
+
if (backgroundColor) {
|
|
200
|
+
options.backgroundColor = backgroundColor;
|
|
201
|
+
}
|
|
202
|
+
// We need better native integration of this on Android
|
|
203
|
+
// Simulating from JS side creates ugly transitions
|
|
204
|
+
if (process.env.EXPO_OS !== 'android') {
|
|
205
|
+
if (blurEffect) {
|
|
206
|
+
options.blurEffect = blurEffect;
|
|
207
|
+
}
|
|
208
|
+
if (iconColor) {
|
|
209
|
+
options.iconColor = iconColor;
|
|
210
|
+
}
|
|
211
|
+
if (disableTransparentOnScrollEdge !== undefined) {
|
|
212
|
+
options.disableTransparentOnScrollEdge = disableTransparentOnScrollEdge;
|
|
213
|
+
}
|
|
214
|
+
if (badgeBackgroundColor) {
|
|
215
|
+
options.badgeBackgroundColor = badgeBackgroundColor;
|
|
216
|
+
}
|
|
217
|
+
if (badgeTextColor) {
|
|
218
|
+
options.badgeTextColor = badgeTextColor;
|
|
219
|
+
}
|
|
220
|
+
if (indicatorColor) {
|
|
221
|
+
options.indicatorColor = indicatorColor;
|
|
222
|
+
}
|
|
223
|
+
if (labelStyle) {
|
|
224
|
+
options.labelStyle = labelStyle;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
135
227
|
}
|
|
136
228
|
function isNativeTabTrigger(child, contextKey) {
|
|
137
|
-
if ((0, react_1.isValidElement)(child) && child && child.type === NativeTabTrigger) {
|
|
229
|
+
if ((0, react_1.isValidElement)(child) && child && child.type === exports.NativeTabTrigger) {
|
|
138
230
|
if (typeof child.props === 'object' &&
|
|
139
231
|
child.props &&
|
|
140
232
|
'name' in child.props &&
|
|
@@ -1 +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"]}
|
|
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';\nimport type { ImageSourcePropType } from 'react-native';\n\nimport { NativeTabsTriggerTabBar } from './NativeTabsTriggerTabBar';\nimport type {\n ExtendedNativeTabOptions,\n NativeTabOptions,\n NativeTabsTriggerTabBarProps,\n NativeTabTriggerProps,\n} from './types';\nimport { filterAllowedChildrenElements, isChildOfType } from './utils';\nimport { useIsPreview } from '../../link/preview/PreviewRouteContext';\nimport { useSafeLayoutEffect } from '../../views/useSafeLayoutEffect';\nimport {\n Icon,\n Badge,\n Label,\n type LabelProps,\n type IconProps,\n type BadgeProps,\n type SourceIconCombination,\n VectorIcon,\n type VectorIconProps,\n} 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 *\n * > **Note:** You can use the alias `NativeTabs.Trigger` for this component.\n */\nfunction NativeTabTriggerImpl(props: NativeTabTriggerProps) {\n const route = useRoute();\n const navigation = useNavigation();\n const isFocused = navigation.isFocused();\n const isInPreview = useIsPreview();\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 && !isInPreview) {\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, true);\n navigation.setOptions(options);\n }\n }, [isFocused, props, isInPreview]);\n\n return null;\n}\n\nexport const NativeTabTrigger = Object.assign(NativeTabTriggerImpl, {\n TabBar: NativeTabsTriggerTabBar,\n});\n\nexport function convertTabPropsToOptions(\n { options, hidden, children, role, disablePopToTop, disableScrollToTop }: NativeTabTriggerProps,\n isDynamic: boolean = false\n) {\n const initialOptions: ExtendedNativeTabOptions = isDynamic\n ? { ...options }\n : {\n ...options,\n hidden: !!hidden,\n specialEffects: {\n repeatedTabSelection: {\n popToRoot: !disablePopToTop,\n scrollToTop: !disableScrollToTop,\n },\n },\n role: role ?? options?.role,\n };\n const allowedChildren = filterAllowedChildrenElements(children, [\n Badge,\n Label,\n Icon,\n NativeTabsTriggerTabBar,\n ]);\n return allowedChildren.reduce<ExtendedNativeTabOptions>(\n (acc, child) => {\n if (isChildOfType(child, Badge)) {\n appendBadgeOptions(acc, child.props);\n } else if (isChildOfType(child, Label)) {\n appendLabelOptions(acc, child.props);\n } else if (isChildOfType(child, Icon)) {\n appendIconOptions(acc, child.props);\n } else if (isChildOfType(child, NativeTabsTriggerTabBar)) {\n appendTabBarOptions(acc, child.props);\n }\n return acc;\n },\n { ...initialOptions }\n );\n}\n\nfunction appendBadgeOptions(options: ExtendedNativeTabOptions, props: BadgeProps) {\n if (props.children) {\n options.badgeValue = String(props.children);\n options.selectedBadgeBackgroundColor = props.selectedBackgroundColor;\n } else if (!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 options.badgeValue = ' ';\n }\n}\n\nfunction appendLabelOptions(options: ExtendedNativeTabOptions, props: LabelProps) {\n if (props.hidden) {\n options.title = '';\n } else {\n options.title = props.children;\n options.selectedLabelStyle = props.selectedStyle;\n }\n}\n\nexport function appendIconOptions(options: ExtendedNativeTabOptions, props: IconProps) {\n if ('src' in props && props.src) {\n const icon = convertIconSrcToIconOption(props);\n options.icon = icon?.icon;\n options.selectedIcon = icon?.selectedIcon;\n } else if ('sf' in props && process.env.EXPO_OS === 'ios') {\n if (typeof props.sf === 'string') {\n options.icon = props.sf\n ? {\n sf: props.sf,\n }\n : undefined;\n options.selectedIcon = undefined;\n } else if (props.sf) {\n options.icon = props.sf.default\n ? {\n sf: props.sf.default,\n }\n : undefined;\n options.selectedIcon = props.sf.selected\n ? {\n sf: props.sf.selected,\n }\n : undefined;\n }\n } else if ('drawable' in props && process.env.EXPO_OS === 'android') {\n options.icon = { drawable: props.drawable };\n options.selectedIcon = undefined;\n }\n options.selectedIconColor = props.selectedColor;\n}\n\nfunction convertIconSrcToIconOption(\n icon: SourceIconCombination | undefined\n): Pick<NativeTabOptions, 'icon' | 'selectedIcon'> | undefined {\n if (icon && icon.src) {\n const { defaultIcon, selected } =\n typeof icon.src === 'object' && 'selected' in icon.src\n ? { defaultIcon: icon.src.default, selected: icon.src.selected }\n : { defaultIcon: icon.src };\n\n const options: Pick<NativeTabOptions, 'icon' | 'selectedIcon'> = {};\n options.icon = convertSrcOrComponentToSrc(defaultIcon);\n options.selectedIcon = convertSrcOrComponentToSrc(selected);\n return options;\n }\n\n return undefined;\n}\n\nfunction convertSrcOrComponentToSrc(src: ImageSourcePropType | ReactElement | undefined) {\n if (src) {\n if (isValidElement(src)) {\n if (src.type === VectorIcon) {\n const props = src.props as VectorIconProps<string>;\n return { src: props.family.getImageSource(props.name, 24, 'white') };\n } else {\n console.warn('Only VectorIcon is supported as a React element in Icon.src');\n }\n } else {\n return { src };\n }\n }\n return undefined;\n}\n\nfunction appendTabBarOptions(\n options: ExtendedNativeTabOptions,\n props: NativeTabsTriggerTabBarProps\n) {\n const {\n backgroundColor,\n blurEffect,\n iconColor,\n disableTransparentOnScrollEdge,\n badgeBackgroundColor,\n badgeTextColor,\n indicatorColor,\n labelStyle,\n } = props;\n\n if (backgroundColor) {\n options.backgroundColor = backgroundColor;\n }\n // We need better native integration of this on Android\n // Simulating from JS side creates ugly transitions\n if (process.env.EXPO_OS !== 'android') {\n if (blurEffect) {\n options.blurEffect = blurEffect;\n }\n if (iconColor) {\n options.iconColor = iconColor;\n }\n if (disableTransparentOnScrollEdge !== undefined) {\n options.disableTransparentOnScrollEdge = disableTransparentOnScrollEdge;\n }\n if (badgeBackgroundColor) {\n options.badgeBackgroundColor = badgeBackgroundColor;\n }\n if (badgeTextColor) {\n options.badgeTextColor = badgeTextColor;\n }\n if (indicatorColor) {\n options.indicatorColor = indicatorColor;\n }\n if (labelStyle) {\n options.labelStyle = labelStyle;\n }\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"]}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { NativeTabTrigger } from './NativeTabTrigger';
|
|
2
1
|
import type { NativeTabsProps } from './types';
|
|
3
2
|
/**
|
|
4
3
|
* The component used to create native tabs layout.
|
|
@@ -19,6 +18,8 @@ import type { NativeTabsProps } from './types';
|
|
|
19
18
|
* ```
|
|
20
19
|
*/
|
|
21
20
|
export declare const NativeTabs: ((props: NativeTabsProps) => import("react").JSX.Element) & {
|
|
22
|
-
Trigger:
|
|
21
|
+
Trigger: ((props: import("./types").NativeTabTriggerProps) => null) & {
|
|
22
|
+
TabBar: typeof import("./NativeTabsTriggerTabBar").NativeTabsTriggerTabBar;
|
|
23
|
+
};
|
|
23
24
|
};
|
|
24
25
|
//# sourceMappingURL=NativeTabs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeTabs.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NativeTabs.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,WACb,eAAe;;;;CAIxB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { NativeTabsTriggerTabBarProps } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The component used to customize the style of the tab bar, when given trigger is selected.
|
|
4
|
+
*
|
|
5
|
+
* Prefer this to global changes of tab bar styles, directly in the page.
|
|
6
|
+
*
|
|
7
|
+
* > **Note:** You can use the alias `NativeTabs.Trigger.TabBar` for this component.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <NativeTabs
|
|
12
|
+
* backgroundColor="black"
|
|
13
|
+
* >
|
|
14
|
+
* <NativeTabs.Trigger name="page">
|
|
15
|
+
* <NativeTabs.Trigger.TabBar
|
|
16
|
+
* backgroundColor="white"
|
|
17
|
+
* />
|
|
18
|
+
* <Label>Page</Label>
|
|
19
|
+
* </NativeTabs.Trigger>
|
|
20
|
+
* </NativeTabs>
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
export declare function NativeTabsTriggerTabBar(props: NativeTabsTriggerTabBarProps): React.ReactNode;
|
|
24
|
+
//# sourceMappingURL=NativeTabsTriggerTabBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTabsTriggerTabBar.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabsTriggerTabBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,GAAG,KAAK,CAAC,SAAS,CAE5F"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NativeTabsTriggerTabBar = NativeTabsTriggerTabBar;
|
|
4
|
+
/**
|
|
5
|
+
* The component used to customize the style of the tab bar, when given trigger is selected.
|
|
6
|
+
*
|
|
7
|
+
* Prefer this to global changes of tab bar styles, directly in the page.
|
|
8
|
+
*
|
|
9
|
+
* > **Note:** You can use the alias `NativeTabs.Trigger.TabBar` for this component.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <NativeTabs
|
|
14
|
+
* backgroundColor="black"
|
|
15
|
+
* >
|
|
16
|
+
* <NativeTabs.Trigger name="page">
|
|
17
|
+
* <NativeTabs.Trigger.TabBar
|
|
18
|
+
* backgroundColor="white"
|
|
19
|
+
* />
|
|
20
|
+
* <Label>Page</Label>
|
|
21
|
+
* </NativeTabs.Trigger>
|
|
22
|
+
* </NativeTabs>
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
function NativeTabsTriggerTabBar(props) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=NativeTabsTriggerTabBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTabsTriggerTabBar.js","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabsTriggerTabBar.tsx"],"names":[],"mappings":";;AAuBA,0DAEC;AAvBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,uBAAuB,CAAC,KAAmC;IACzE,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type { NativeTabsTriggerTabBarProps } from './types';\n\n/**\n * The component used to customize the style of the tab bar, when given trigger is selected.\n *\n * Prefer this to global changes of tab bar styles, directly in the page.\n *\n * > **Note:** You can use the alias `NativeTabs.Trigger.TabBar` for this component.\n *\n * @example\n * ```tsx\n * <NativeTabs\n * backgroundColor=\"black\"\n * >\n * <NativeTabs.Trigger name=\"page\">\n * <NativeTabs.Trigger.TabBar\n * backgroundColor=\"white\"\n * />\n * <Label>Page</Label>\n * </NativeTabs.Trigger>\n * </NativeTabs>\n *\n */\nexport function NativeTabsTriggerTabBar(props: NativeTabsTriggerTabBarProps): React.ReactNode {\n return null;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeTabsView.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabsView.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"NativeTabsView.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/NativeBottomTabs/NativeTabsView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAkB9E,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,SAAS,CAAC;AASjB,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,qBA4IxD"}
|
|
@@ -36,57 +36,73 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.NativeTabsView = NativeTabsView;
|
|
37
37
|
const react_1 = __importStar(require("react"));
|
|
38
38
|
const react_native_screens_1 = require("react-native-screens");
|
|
39
|
+
const appearance_1 = require("./appearance");
|
|
40
|
+
const types_1 = require("./types");
|
|
39
41
|
const utils_1 = require("./utils");
|
|
40
|
-
const linking_1 = require("../../link/linking");
|
|
41
42
|
// We let native tabs to control the changes. This requires freeze to be disabled for tab bar.
|
|
42
43
|
// Otherwise user may see glitches when switching between tabs.
|
|
43
44
|
react_native_screens_1.featureFlags.experiment.controlledBottomTabs = false;
|
|
44
|
-
|
|
45
|
-
(0, react_native_screens_1.enableFreeze)(false);
|
|
46
|
-
// TODO: Add support for dynamic params inside a route
|
|
45
|
+
const supportedBlurEffectsSet = new Set(types_1.SUPPORTED_BLUR_EFFECTS);
|
|
47
46
|
function NativeTabsView(props) {
|
|
48
|
-
const { builder,
|
|
47
|
+
const { builder, minimizeBehavior, disableIndicator, focusedIndex } = props;
|
|
49
48
|
const { state, descriptors, navigation } = builder;
|
|
50
49
|
const { routes } = state;
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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));
|
|
50
|
+
let blurEffect = props.blurEffect;
|
|
51
|
+
if (blurEffect && !supportedBlurEffectsSet.has(blurEffect)) {
|
|
52
|
+
console.warn(`Unsupported blurEffect: ${blurEffect}. Supported values are: ${types_1.SUPPORTED_BLUR_EFFECTS.map((effect) => `"${effect}"`).join(', ')}`);
|
|
53
|
+
blurEffect = undefined;
|
|
61
54
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
lastNotNativeTransitionIndex.current = focusedIndex;
|
|
55
|
+
const deferredFocusedIndex = (0, react_1.useDeferredValue)(focusedIndex);
|
|
56
|
+
let standardAppearance = (0, appearance_1.convertStyleToAppearance)({
|
|
57
|
+
...props.labelStyle,
|
|
58
|
+
iconColor: props.iconColor,
|
|
59
|
+
blurEffect,
|
|
60
|
+
backgroundColor: props.backgroundColor,
|
|
61
|
+
badgeBackgroundColor: props.badgeBackgroundColor,
|
|
62
|
+
});
|
|
63
|
+
if (props.tintColor) {
|
|
64
|
+
standardAppearance = (0, appearance_1.appendSelectedStyleToAppearance)({ iconColor: props.tintColor, color: props.tintColor }, standardAppearance);
|
|
73
65
|
}
|
|
66
|
+
const scrollEdgeAppearance = (0, appearance_1.convertStyleToAppearance)({
|
|
67
|
+
...props.labelStyle,
|
|
68
|
+
iconColor: props.iconColor,
|
|
69
|
+
blurEffect,
|
|
70
|
+
backgroundColor: props.backgroundColor,
|
|
71
|
+
badgeBackgroundColor: props.badgeBackgroundColor,
|
|
72
|
+
});
|
|
73
|
+
const appearances = routes.map((route) => ({
|
|
74
|
+
standardAppearance: (0, appearance_1.createStandardAppearanceFromOptions)(descriptors[route.key].options, standardAppearance),
|
|
75
|
+
scrollEdgeAppearance: (0, appearance_1.createScrollEdgeAppearanceFromOptions)(descriptors[route.key].options, scrollEdgeAppearance),
|
|
76
|
+
}));
|
|
77
|
+
const options = routes.map((route) => descriptors[route.key].options);
|
|
74
78
|
const children = routes
|
|
75
79
|
.map((route, index) => ({ route, index }))
|
|
76
80
|
.filter(({ route: { key } }) => (0, utils_1.shouldTabBeVisible)(descriptors[key].options))
|
|
77
81
|
.map(({ route, index }) => {
|
|
78
82
|
const descriptor = descriptors[route.key];
|
|
79
|
-
|
|
80
|
-
|
|
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>);
|
|
83
|
+
const isFocused = index === deferredFocusedIndex;
|
|
84
|
+
return (<Screen key={route.key} routeKey={route.key} name={route.name} descriptor={descriptor} isFocused={isFocused} standardAppearance={appearances[index].standardAppearance} scrollEdgeAppearance={appearances[index].scrollEdgeAppearance} badgeTextColor={props.badgeTextColor}/>);
|
|
86
85
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
return (<BottomTabsWrapper
|
|
87
|
+
// #region android props
|
|
88
|
+
tabBarItemTitleFontColor={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal
|
|
89
|
+
?.tabBarItemTitleFontColor} tabBarItemTitleFontFamily={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal
|
|
90
|
+
?.tabBarItemTitleFontFamily} tabBarItemTitleFontSize={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal
|
|
91
|
+
?.tabBarItemTitleFontSize} tabBarItemTitleFontSizeActive={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal
|
|
92
|
+
?.tabBarItemTitleFontSize} tabBarItemTitleFontWeight={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal
|
|
93
|
+
?.tabBarItemTitleFontWeight} tabBarItemTitleFontStyle={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal
|
|
94
|
+
?.tabBarItemTitleFontStyle} tabBarItemIconColor={appearances[deferredFocusedIndex].standardAppearance.stacked?.normal?.tabBarItemIconColor} tabBarBackgroundColor={appearances[deferredFocusedIndex].standardAppearance.tabBarBackgroundColor ??
|
|
95
|
+
props.backgroundColor ??
|
|
96
|
+
undefined} tabBarItemRippleColor={props.rippleColor} tabBarItemLabelVisibilityMode={props.labelVisibilityMode} tabBarItemIconColorActive={appearances[deferredFocusedIndex].standardAppearance?.stacked?.selected
|
|
97
|
+
?.tabBarItemIconColor ?? props?.tintColor} tabBarItemTitleFontColorActive={appearances[deferredFocusedIndex].standardAppearance?.stacked?.selected
|
|
98
|
+
?.tabBarItemTitleFontColor ?? props?.tintColor}
|
|
99
|
+
// tabBarItemTitleFontSizeActive={activeStyle?.fontSize}
|
|
100
|
+
tabBarItemActiveIndicatorColor={options[deferredFocusedIndex]?.indicatorColor ?? props?.indicatorColor} tabBarItemActiveIndicatorEnabled={!disableIndicator}
|
|
101
|
+
// #endregion
|
|
102
|
+
// #region iOS props
|
|
103
|
+
tabBarTintColor={props?.tintColor} tabBarMinimizeBehavior={minimizeBehavior}
|
|
104
|
+
// #endregion
|
|
105
|
+
onNativeFocusChange={({ nativeEvent: { tabKey } }) => {
|
|
90
106
|
const descriptor = descriptors[tabKey];
|
|
91
107
|
const route = descriptor.route;
|
|
92
108
|
navigation.dispatch({
|
|
@@ -96,10 +112,43 @@ function NativeTabsView(props) {
|
|
|
96
112
|
name: route.name,
|
|
97
113
|
},
|
|
98
114
|
});
|
|
99
|
-
isDuringNativeTransition.current = true;
|
|
100
115
|
}}>
|
|
101
116
|
{children}
|
|
102
|
-
</
|
|
117
|
+
</BottomTabsWrapper>);
|
|
118
|
+
}
|
|
119
|
+
function Screen(props) {
|
|
120
|
+
const { routeKey, name, descriptor, isFocused, standardAppearance, scrollEdgeAppearance, badgeTextColor, } = props;
|
|
121
|
+
const role = descriptor.options.role;
|
|
122
|
+
// To align with apple documentation and prevent untested cases,
|
|
123
|
+
// title and icon cannot be changed when role is defined
|
|
124
|
+
const shouldResetTitleAndIcon = !!role && process.env.EXPO_OS === 'ios';
|
|
125
|
+
const title = descriptor.options.title ?? name;
|
|
126
|
+
const icon = useAwaitedScreensIcon(descriptor.options.icon);
|
|
127
|
+
const selectedIcon = useAwaitedScreensIcon(descriptor.options.selectedIcon);
|
|
128
|
+
return (<react_native_screens_1.BottomTabsScreen {...descriptor.options} tabBarItemBadgeBackgroundColor={standardAppearance.stacked?.normal?.tabBarItemBadgeBackgroundColor} tabBarItemBadgeTextColor={badgeTextColor} standardAppearance={standardAppearance} scrollEdgeAppearance={scrollEdgeAppearance} iconResourceName={getAndroidIconResourceName(icon)} iconResource={getAndroidIconResource(icon)} icon={shouldResetTitleAndIcon ? undefined : convertOptionsIconToPropsIcon(icon)} selectedIcon={shouldResetTitleAndIcon ? undefined : convertOptionsIconToPropsIcon(selectedIcon)} title={shouldResetTitleAndIcon ? undefined : title} freezeContents={false} tabKey={routeKey} systemItem={descriptor.options.role} isFocused={isFocused}>
|
|
129
|
+
{descriptor.render()}
|
|
130
|
+
</react_native_screens_1.BottomTabsScreen>);
|
|
131
|
+
}
|
|
132
|
+
function useAwaitedScreensIcon(icon) {
|
|
133
|
+
const src = icon && typeof icon === 'object' && 'src' in icon ? icon.src : undefined;
|
|
134
|
+
const [awaitedIcon, setAwaitedIcon] = (0, react_1.useState)(undefined);
|
|
135
|
+
(0, react_1.useEffect)(() => {
|
|
136
|
+
const loadIcon = async () => {
|
|
137
|
+
if (src && src instanceof Promise) {
|
|
138
|
+
const currentAwaitedIcon = { src: await src };
|
|
139
|
+
setAwaitedIcon(currentAwaitedIcon);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
loadIcon();
|
|
143
|
+
// Checking `src` rather then icon here, to avoid unnecessary re-renders
|
|
144
|
+
// The icon object can be recreated, while src should stay the same
|
|
145
|
+
// In this case as we control `VectorIcon`, it will only change if `family` or `name` props change
|
|
146
|
+
// So we should be safe with promise resolving
|
|
147
|
+
}, [src]);
|
|
148
|
+
return (0, react_1.useMemo)(() => (isAwaitedIcon(icon) ? icon : awaitedIcon), [awaitedIcon, icon]);
|
|
149
|
+
}
|
|
150
|
+
function isAwaitedIcon(icon) {
|
|
151
|
+
return !icon || !('src' in icon && icon.src instanceof Promise);
|
|
103
152
|
}
|
|
104
153
|
function convertOptionsIconToPropsIcon(icon) {
|
|
105
154
|
if (!icon) {
|
|
@@ -113,4 +162,31 @@ function convertOptionsIconToPropsIcon(icon) {
|
|
|
113
162
|
}
|
|
114
163
|
return undefined;
|
|
115
164
|
}
|
|
165
|
+
function getAndroidIconResource(icon) {
|
|
166
|
+
if (icon && 'src' in icon && icon.src) {
|
|
167
|
+
return icon.src;
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
function getAndroidIconResourceName(icon) {
|
|
172
|
+
if (icon && 'drawable' in icon && icon.drawable) {
|
|
173
|
+
return icon.drawable;
|
|
174
|
+
}
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const supportedTabBarMinimizeBehaviorsSet = new Set(types_1.SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS);
|
|
178
|
+
const supportedTabBarItemLabelVisibilityModesSet = new Set(types_1.SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES);
|
|
179
|
+
function BottomTabsWrapper(props) {
|
|
180
|
+
let { tabBarMinimizeBehavior, tabBarItemLabelVisibilityMode, ...rest } = props;
|
|
181
|
+
if (tabBarMinimizeBehavior && !supportedTabBarMinimizeBehaviorsSet.has(tabBarMinimizeBehavior)) {
|
|
182
|
+
console.warn(`Unsupported minimizeBehavior: ${tabBarMinimizeBehavior}. Supported values are: ${types_1.SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS.map((behavior) => `"${behavior}"`).join(', ')}`);
|
|
183
|
+
tabBarMinimizeBehavior = undefined;
|
|
184
|
+
}
|
|
185
|
+
if (tabBarItemLabelVisibilityMode &&
|
|
186
|
+
!supportedTabBarItemLabelVisibilityModesSet.has(tabBarItemLabelVisibilityMode)) {
|
|
187
|
+
console.warn(`Unsupported labelVisibilityMode: ${tabBarItemLabelVisibilityMode}. Supported values are: ${types_1.SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES.map((mode) => `"${mode}"`).join(', ')}`);
|
|
188
|
+
tabBarItemLabelVisibilityMode = undefined;
|
|
189
|
+
}
|
|
190
|
+
return (<react_native_screens_1.BottomTabs tabBarItemLabelVisibilityMode={tabBarItemLabelVisibilityMode} tabBarMinimizeBehavior={tabBarMinimizeBehavior} {...rest}/>);
|
|
191
|
+
}
|
|
116
192
|
//# sourceMappingURL=NativeTabsView.js.map
|