first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
import React from 'react';
import type { InternalNativeTabsProps, NativeTabsProps } from './types';
export declare const NativeTabsContext: React.Context<boolean>;
export declare function NativeTabsNavigator({ children, backBehavior, labelStyle, iconColor, blurEffect, backgroundColor, badgeBackgroundColor, indicatorColor, badgeTextColor, shadowColor, screenListeners, ...rest }: InternalNativeTabsProps): React.JSX.Element;
export declare function NativeTabsNavigatorWrapper(props: NativeTabsProps): React.JSX.Element;
//# sourceMappingURL=NativeBottomTabsNavigator.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeBottomTabsNavigator.d.ts","sourceRoot":"","sources":["../../src/native-tabs/NativeBottomTabsNavigator.tsx"],"names":[],"mappings":"AASA,OAAO,KAAoC,MAAM,OAAO,CAAC;AAKzD,OAAO,KAAK,EACV,uBAAuB,EAGvB,eAAe,EAEhB,MAAM,SAAS,CAAC;AAQjB,eAAO,MAAM,iBAAiB,wBAAsC,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,YAAkC,EAClC,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,WAAW,EACX,eAAe,EACf,GAAG,IAAI,EACR,EAAE,uBAAuB,qBAmHzB;AAWD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,eAAe,qBAiBhE"}

View File

@@ -0,0 +1,134 @@
"use strict";
'use client';
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabsContext = void 0;
exports.NativeTabsNavigator = NativeTabsNavigator;
exports.NativeTabsNavigatorWrapper = NativeTabsNavigatorWrapper;
const native_1 = require("@react-navigation/native");
const react_1 = __importStar(require("react"));
const NativeBottomTabsRouter_1 = require("./NativeBottomTabsRouter");
const NativeTabTrigger_1 = require("./NativeTabTrigger");
const NativeTabsView_1 = require("./NativeTabsView");
const utils_1 = require("./utils");
const withLayoutContext_1 = require("../layouts/withLayoutContext");
const linking_1 = require("../link/linking");
const children_1 = require("../utils/children");
// In Jetpack Compose, the default back behavior is to go back to the initial route.
const defaultBackBehavior = 'initialRoute';
exports.NativeTabsContext = react_1.default.createContext(false);
function NativeTabsNavigator({ children, backBehavior = defaultBackBehavior, labelStyle, iconColor, blurEffect, backgroundColor, badgeBackgroundColor, indicatorColor, badgeTextColor, shadowColor, screenListeners, ...rest }) {
if ((0, react_1.use)(exports.NativeTabsContext)) {
throw new Error('Nesting Native Tabs inside each other is not supported natively. Use JS tabs for nesting instead.');
}
const processedLabelStyle = (0, utils_1.convertLabelStylePropToObject)(labelStyle);
const processedIconColor = (0, utils_1.convertIconColorPropToObject)(iconColor);
const selectedLabelStyle = processedLabelStyle.selected
? {
...processedLabelStyle.selected,
color: processedLabelStyle.selected.color ?? rest.tintColor,
}
: rest.tintColor
? { color: rest.tintColor }
: undefined;
const { state, descriptors, navigation, NavigationContent } = (0, native_1.useNavigationBuilder)(NativeBottomTabsRouter_1.NativeBottomTabsRouter, {
children,
backBehavior,
screenListeners,
screenOptions: {
disableTransparentOnScrollEdge: rest.disableTransparentOnScrollEdge,
labelStyle: processedLabelStyle.default,
selectedLabelStyle,
iconColor: processedIconColor.default,
selectedIconColor: processedIconColor.selected ?? rest.tintColor,
blurEffect,
backgroundColor,
badgeBackgroundColor,
indicatorColor,
badgeTextColor,
shadowColor,
},
});
const { routes } = state;
const visibleTabs = (0, react_1.useMemo)(() => routes
// The <NativeTab.Trigger> always sets `hidden` to defined boolean value.
// If it is not defined, then it was not specified, and we should hide the tab.
.filter((route) => descriptors[route.key].options?.hidden !== true)
.map((route) => ({
options: descriptors[route.key].options,
routeKey: route.key,
name: route.name,
contentRenderer: () => descriptors[route.key].render(),
})), [routes, descriptors]);
const visibleFocusedTabIndex = (0, react_1.useMemo)(() => visibleTabs.findIndex((tab) => tab.routeKey === routes[state.index].key), [visibleTabs, routes, state.index]);
const visibleTabsKeys = (0, react_1.useMemo)(() => visibleTabs.map((tab) => tab.routeKey).join(';'), [visibleTabs]);
if (visibleFocusedTabIndex < 0) {
if (process.env.NODE_ENV !== 'production') {
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)}"`);
}
}
const focusedIndex = visibleFocusedTabIndex >= 0 ? visibleFocusedTabIndex : 0;
const onTabChange = (0, react_1.useCallback)((tabKey) => {
const descriptor = descriptors[tabKey];
const route = descriptor.route;
navigation.emit({
type: 'tabPress',
target: tabKey,
data: {
__internalTabsType: 'native',
},
});
navigation.dispatch({
type: 'JUMP_TO',
target: state.key,
payload: {
name: route.name,
},
});
}, [descriptors, navigation, state.key]);
return (<NavigationContent>
<exports.NativeTabsContext value>
<NativeTabsView_1.NativeTabsView {...rest} key={visibleTabsKeys} focusedIndex={focusedIndex} tabs={visibleTabs} onTabChange={onTabChange}/>
</exports.NativeTabsContext>
</NavigationContent>);
}
const createNativeTabNavigator = (0, native_1.createNavigatorFactory)(NativeTabsNavigator);
const NativeTabsNavigatorWithContext = (0, withLayoutContext_1.withLayoutContext)(createNativeTabNavigator().Navigator, undefined, true);
function NativeTabsNavigatorWrapper(props) {
const triggerChildren = (0, react_1.useMemo)(() => (0, children_1.getAllChildrenOfType)(props.children, NativeTabTrigger_1.NativeTabTrigger), [props.children]);
const nonTriggerChildren = (0, react_1.useMemo)(() => (0, children_1.getAllChildrenNotOfType)(props.children, NativeTabTrigger_1.NativeTabTrigger), [props.children]);
return (<NativeTabsNavigatorWithContext {...props} children={triggerChildren} nonTriggerChildren={nonTriggerChildren}/>);
}
//# sourceMappingURL=NativeBottomTabsNavigator.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
import { ParamListBase, Router, TabActionType, TabNavigationState, type TabRouterOptions } from '@react-navigation/native';
export declare function NativeBottomTabsRouter(options: TabRouterOptions): Router<TabNavigationState<ParamListBase>, import("@react-navigation/routers/lib/typescript/src/CommonActions").Action | TabActionType>;
//# sourceMappingURL=NativeBottomTabsRouter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeBottomTabsRouter.d.ts","sourceRoot":"","sources":["../../src/native-tabs/NativeBottomTabsRouter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EACb,MAAM,EACN,aAAa,EACb,kBAAkB,EAElB,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAYlC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,0IAkE/D"}

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeBottomTabsRouter = NativeBottomTabsRouter;
const native_1 = require("@react-navigation/native");
const navigationParams_1 = require("../navigationParams");
function NativeBottomTabsRouter(options) {
const tabRouter = (0, native_1.TabRouter)({ ...options });
const nativeTabRouter = {
...tabRouter,
// @ts-expect-error TODO: For some reason this is not typed correctly
getStateForAction: (state, action, options) => {
switch (action.type) {
case 'NAVIGATE': {
const newStateFromNavigation = tabRouter.getStateForAction(state, action, options);
const index = state.routes.findIndex((route) => route.name === action.payload.name);
if (index === -1 || !newStateFromNavigation) {
return newStateFromNavigation;
}
const newState = {
...newStateFromNavigation,
routes: newStateFromNavigation.routes.map((route) => {
if (route.name !== action.payload.name) {
return route;
}
const expoParams = (0, navigationParams_1.getInternalExpoRouterParams)(action.payload.params);
if (route.params && 'screen' in route.params) {
expoParams[navigationParams_1.INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME] = true;
}
if (process.env.NODE_ENV !== 'production') {
if (expoParams[navigationParams_1.INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SOURCE_ID_PARAM_NAME]) {
console.warn('Zoom transition is not supported when navigating between tabs. Falling back to standard navigation transition.');
}
}
// Zoom transition needs to be disabled for navigation inside tabs
// Otherwise user can end up in a situation where a view is missing on one tab
// because it was used to perform zoom transition on another tab
const params = (0, navigationParams_1.removeParams)((0, navigationParams_1.appendInternalExpoRouterParams)(route.params, expoParams), [
navigationParams_1.INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SCREEN_ID_PARAM_NAME,
navigationParams_1.INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SOURCE_ID_PARAM_NAME,
]);
return {
...route,
params,
};
}),
};
return newState;
}
}
return tabRouter.getStateForAction(state, action, options);
},
};
return nativeTabRouter;
}
//# sourceMappingURL=NativeBottomTabsRouter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeBottomTabsRouter.js","sourceRoot":"","sources":["../../src/native-tabs/NativeBottomTabsRouter.tsx"],"names":[],"mappings":";;AAoBA,wDAkEC;AAtFD,qDAQkC;AAElC,0DAQ6B;AAE7B,SAAgB,sBAAsB,CAAC,OAAyB;IAC9D,MAAM,SAAS,GAAG,IAAA,kBAAS,EAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAE5C,MAAM,eAAe,GAGjB;QACF,GAAG,SAAS;QACZ,qEAAqE;QACrE,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAA8C,EAAE,OAAO,EAAE,EAAE;YACpF,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;gBACpB,KAAK,UAAU,CAAC,CAAC,CAAC;oBAChB,MAAM,sBAAsB,GAAG,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;oBACnF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAEpF,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;wBAC5C,OAAO,sBAAsB,CAAC;oBAChC,CAAC;oBAED,MAAM,QAAQ,GAAG;wBACf,GAAG,sBAAsB;wBACzB,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;4BAClD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gCACvC,OAAO,KAAK,CAAC;4BACf,CAAC;4BAED,MAAM,UAAU,GAA6B,IAAA,8CAA2B,EACtE,MAAM,CAAC,OAAO,CAAC,MAAM,CACtB,CAAC;4BAEF,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gCAC7C,UAAU,CAAC,+DAA4C,CAAC,GAAG,IAAI,CAAC;4BAClE,CAAC;4BAED,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;gCAC1C,IAAI,UAAU,CAAC,4EAAyD,CAAC,EAAE,CAAC;oCAC1E,OAAO,CAAC,IAAI,CACV,gHAAgH,CACjH,CAAC;gCACJ,CAAC;4BACH,CAAC;4BAED,kEAAkE;4BAClE,8EAA8E;4BAC9E,gEAAgE;4BAChE,MAAM,MAAM,GAAG,IAAA,+BAAY,EACzB,IAAA,iDAA8B,EAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,EACxD;gCACE,4EAAyD;gCACzD,4EAAyD;6BAC1D,CACF,CAAC;4BACF,OAAO;gCACL,GAAG,KAAK;gCACR,MAAM;6BACP,CAAC;wBACJ,CAAC,CAAC;qBACH,CAAC;oBACF,OAAO,QAAQ,CAAC;gBAClB,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC","sourcesContent":["import {\n CommonNavigationAction,\n ParamListBase,\n Router,\n TabActionType,\n TabNavigationState,\n TabRouter,\n type TabRouterOptions,\n} from '@react-navigation/native';\n\nimport {\n appendInternalExpoRouterParams,\n getInternalExpoRouterParams,\n INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME,\n INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SCREEN_ID_PARAM_NAME,\n INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SOURCE_ID_PARAM_NAME,\n removeParams,\n type InternalExpoRouterParams,\n} from '../navigationParams';\n\nexport function NativeBottomTabsRouter(options: TabRouterOptions) {\n const tabRouter = TabRouter({ ...options });\n\n const nativeTabRouter: Router<\n TabNavigationState<ParamListBase>,\n TabActionType | CommonNavigationAction\n > = {\n ...tabRouter,\n // @ts-expect-error TODO: For some reason this is not typed correctly\n getStateForAction: (state, action: TabActionType | CommonNavigationAction, options) => {\n switch (action.type) {\n case 'NAVIGATE': {\n const newStateFromNavigation = tabRouter.getStateForAction(state, action, options);\n const index = state.routes.findIndex((route) => route.name === action.payload.name);\n\n if (index === -1 || !newStateFromNavigation) {\n return newStateFromNavigation;\n }\n\n const newState = {\n ...newStateFromNavigation,\n routes: newStateFromNavigation.routes.map((route) => {\n if (route.name !== action.payload.name) {\n return route;\n }\n\n const expoParams: InternalExpoRouterParams = getInternalExpoRouterParams(\n action.payload.params\n );\n\n if (route.params && 'screen' in route.params) {\n expoParams[INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME] = true;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (expoParams[INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SOURCE_ID_PARAM_NAME]) {\n console.warn(\n 'Zoom transition is not supported when navigating between tabs. Falling back to standard navigation transition.'\n );\n }\n }\n\n // Zoom transition needs to be disabled for navigation inside tabs\n // Otherwise user can end up in a situation where a view is missing on one tab\n // because it was used to perform zoom transition on another tab\n const params = removeParams(\n appendInternalExpoRouterParams(route.params, expoParams),\n [\n INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SCREEN_ID_PARAM_NAME,\n INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SOURCE_ID_PARAM_NAME,\n ]\n );\n return {\n ...route,\n params,\n };\n }),\n };\n return newState;\n }\n }\n return tabRouter.getStateForAction(state, action, options);\n },\n };\n\n return nativeTabRouter;\n}\n"]}

View File

@@ -0,0 +1,53 @@
import { type ReactElement, type ReactNode } from 'react';
import { type NativeTabsTriggerBadgeProps, type NativeTabsTriggerLabelProps, type NativeTabsTriggerIconProps } from './common/elements';
import type { NativeTabOptions, NativeTabTriggerProps } from './types';
/**
* The component used to customize the native tab options both in the _layout file and from the tab screen.
*
* When used in the _layout file, you need to provide a `name` prop.
* When used in the tab screen, the `name` prop takes no effect.
*
* @example
* ```tsx app/_layout.tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default function Layout() {
* return (
* <NativeTabs>
* <NativeTabs.Trigger name="home" />
* <NativeTabs.Trigger name="settings" />
* </NativeTabs>
* );
* }
* ```
*
* @example
* ```tsx app/home.tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default function HomeScreen() {
* return (
* <View>
* <NativeTabs.Trigger>
* <NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
* </NativeTabs.Trigger>
* <Text>This is home screen!</Text>
* </View>
* );
* }
* ```
*/
declare function NativeTabTriggerImpl(props: NativeTabTriggerProps): null;
export declare const NativeTabTrigger: typeof NativeTabTriggerImpl & {
Label: import("react").FC<NativeTabsTriggerLabelProps>;
Icon: import("react").FC<NativeTabsTriggerIconProps>;
Badge: import("react").FC<NativeTabsTriggerBadgeProps>;
VectorIcon: typeof import("..").VectorIcon;
};
export declare function convertTabPropsToOptions({ hidden, children, role, disablePopToTop, disableScrollToTop, unstable_nativeProps, disableAutomaticContentInsets, contentStyle, disableTransparentOnScrollEdge, }: NativeTabTriggerProps, isDynamic?: boolean): NativeTabOptions;
export declare function appendIconOptions(options: NativeTabOptions, props: NativeTabsTriggerIconProps): void;
export declare function isNativeTabTrigger(child: ReactNode, contextKey?: string): child is ReactElement<NativeTabTriggerProps & {
name: string;
}>;
export {};
//# sourceMappingURL=NativeTabTrigger.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeTabTrigger.d.ts","sourceRoot":"","sources":["../../src/native-tabs/NativeTabTrigger.tsx"],"names":[],"mappings":"AAGA,OAAO,EAA+B,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvF,OAAO,EAKL,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAEhC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAOvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,iBAAS,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,QAuBzD;AAED,eAAO,MAAM,gBAAgB;;;;;CAK3B,CAAC;AAEH,wBAAgB,wBAAwB,CACtC,EACE,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,YAAY,EACZ,8BAA8B,GAC/B,EAAE,qBAAqB,EACxB,SAAS,GAAE,OAAe,oBAuC3B;AAyBD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,0BAA0B,QAwD7F;AAsCD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,KAAK,IAAI,YAAY,CAAC,qBAAqB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBjE"}

View File

@@ -0,0 +1,236 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabTrigger = void 0;
exports.convertTabPropsToOptions = convertTabPropsToOptions;
exports.appendIconOptions = appendIconOptions;
exports.isNativeTabTrigger = isNativeTabTrigger;
const native_1 = require("@react-navigation/native");
const react_1 = require("react");
const react_native_1 = require("react-native");
const elements_1 = require("./common/elements");
const icon_1 = require("./utils/icon");
const PreviewRouteContext_1 = require("../link/preview/PreviewRouteContext");
const useFocusEffect_1 = require("../useFocusEffect");
const children_1 = require("../utils/children");
const materialIconConverter_1 = require("./utils/materialIconConverter");
/**
* The component used to customize the native tab options both in the _layout file and from the tab screen.
*
* When used in the _layout file, you need to provide a `name` prop.
* When used in the tab screen, the `name` prop takes no effect.
*
* @example
* ```tsx app/_layout.tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default function Layout() {
* return (
* <NativeTabs>
* <NativeTabs.Trigger name="home" />
* <NativeTabs.Trigger name="settings" />
* </NativeTabs>
* );
* }
* ```
*
* @example
* ```tsx app/home.tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default function HomeScreen() {
* return (
* <View>
* <NativeTabs.Trigger>
* <NativeTabs.Trigger.Label>Home</NativeTabs.Trigger.Label>
* </NativeTabs.Trigger>
* <Text>This is home screen!</Text>
* </View>
* );
* }
* ```
*/
function NativeTabTriggerImpl(props) {
const route = (0, native_1.useRoute)();
const navigation = (0, native_1.useNavigation)();
const isInPreview = (0, PreviewRouteContext_1.useIsPreview)();
(0, useFocusEffect_1.useFocusEffect)((0, react_1.useCallback)(() => {
// This will cause the tab to update only when it is focused.
// As long as all tabs are loaded at the start, we don't need this check.
// It is here to ensure similar behavior to stack
if (!isInPreview) {
if (navigation.getState()?.type !== 'tab') {
throw new Error(`Trigger component can only be used in the tab screen. Current route: ${route.name}`);
}
const options = convertTabPropsToOptions(props, true);
navigation.setOptions(options);
}
}, [props, isInPreview]));
return null;
}
exports.NativeTabTrigger = Object.assign(NativeTabTriggerImpl, {
Label: elements_1.NativeTabsTriggerLabel,
Icon: elements_1.NativeTabsTriggerIcon,
Badge: elements_1.NativeTabsTriggerBadge,
VectorIcon: elements_1.NativeTabsTriggerVectorIcon,
});
function convertTabPropsToOptions({ hidden, children, role, disablePopToTop, disableScrollToTop, unstable_nativeProps, disableAutomaticContentInsets, contentStyle, disableTransparentOnScrollEdge, }, isDynamic = false) {
const initialOptions = isDynamic
? {
...(unstable_nativeProps ? { nativeProps: unstable_nativeProps } : {}),
...(disableTransparentOnScrollEdge !== undefined ? { disableTransparentOnScrollEdge } : {}),
}
: {
hidden: !!hidden,
specialEffects: {
repeatedTabSelection: {
popToRoot: !disablePopToTop,
scrollToTop: !disableScrollToTop,
},
},
contentStyle,
role,
nativeProps: unstable_nativeProps,
disableAutomaticContentInsets,
...(disableTransparentOnScrollEdge !== undefined ? { disableTransparentOnScrollEdge } : {}),
};
const allowedChildren = (0, children_1.filterAllowedChildrenElements)(children, [
elements_1.NativeTabsTriggerBadge,
elements_1.NativeTabsTriggerLabel,
elements_1.NativeTabsTriggerIcon,
]);
return allowedChildren.reduce((acc, child) => {
if ((0, children_1.isChildOfType)(child, elements_1.NativeTabsTriggerBadge)) {
appendBadgeOptions(acc, child.props);
}
else if ((0, children_1.isChildOfType)(child, elements_1.NativeTabsTriggerLabel)) {
appendLabelOptions(acc, child.props);
}
else if ((0, children_1.isChildOfType)(child, elements_1.NativeTabsTriggerIcon)) {
appendIconOptions(acc, child.props);
}
return acc;
}, { ...initialOptions });
}
function appendBadgeOptions(options, props) {
if (props.children) {
options.badgeValue = String(props.children);
options.selectedBadgeBackgroundColor = props.selectedBackgroundColor;
}
else if (!props.hidden) {
// If no value is provided, we set it to a space to show the badge
// Otherwise, the `react-native-screens` will interpret it as a hidden badge
// https://github.com/software-mansion/react-native-screens/blob/b4358fd95dd0736fc54df6bb97f210dc89edf24c/ios/bottom-tabs/RNSBottomTabsScreenComponentView.mm#L172
options.badgeValue = ' ';
}
}
function appendLabelOptions(options, props) {
if (props.hidden) {
options.title = '';
}
else {
options.title = props.children;
if (props.selectedStyle) {
options.selectedLabelStyle = react_native_1.StyleSheet.flatten(props.selectedStyle);
}
}
}
function appendIconOptions(options, props) {
if ('sf' in props && props.sf && process.env.EXPO_OS === 'ios') {
if (typeof props.sf === 'string') {
options.icon = props.sf
? {
sf: props.sf,
}
: undefined;
options.selectedIcon = undefined;
}
else if (props.sf) {
options.icon = props.sf.default
? {
sf: props.sf.default,
}
: undefined;
options.selectedIcon = props.sf.selected
? {
sf: props.sf.selected,
}
: undefined;
}
}
else if ('xcasset' in props && props.xcasset && process.env.EXPO_OS === 'ios') {
if (typeof props.xcasset === 'string') {
options.icon = { xcasset: props.xcasset };
options.selectedIcon = undefined;
}
else {
options.icon = props.xcasset.default ? { xcasset: props.xcasset.default } : undefined;
options.selectedIcon = props.xcasset.selected
? { xcasset: props.xcasset.selected }
: undefined;
}
}
else if ('drawable' in props && props.drawable && process.env.EXPO_OS === 'android') {
if ('md' in props) {
console.warn('Both `md` and `drawable` props are provided to NativeTabs.Trigger.Icon. `drawable` will take precedence on Android platform.');
}
options.icon = { drawable: props.drawable };
options.selectedIcon = undefined;
}
else if ('md' in props && props.md && process.env.EXPO_OS === 'android') {
if (process.env.NODE_ENV !== 'production') {
if ('drawable' in props) {
console.warn('Both `md` and `drawable` props are provided to NativeTabs.Trigger.Icon. `drawable` will take precedence on Android platform.');
}
}
options.icon = (0, materialIconConverter_1.convertMaterialIconNameToImageSource)(props.md);
}
else if ('src' in props && props.src) {
const icon = convertIconSrcToIconOption(props);
options.icon = icon?.icon;
options.selectedIcon = icon?.selectedIcon;
}
if (props.selectedColor) {
options.selectedIconColor = props.selectedColor;
}
}
function convertIconSrcToIconOption(icon) {
if (icon && icon.src) {
const { defaultIcon, selected } = typeof icon.src === 'object' && 'selected' in icon.src
? { defaultIcon: icon.src.default, selected: icon.src.selected }
: { defaultIcon: icon.src };
const options = {};
options.icon = convertSrcOrComponentToSrc(defaultIcon, { renderingMode: icon.renderingMode });
options.selectedIcon = convertSrcOrComponentToSrc(selected, {
renderingMode: icon.renderingMode,
});
return options;
}
return undefined;
}
function convertSrcOrComponentToSrc(src, options) {
if (src) {
if ((0, react_1.isValidElement)(src)) {
return (0, icon_1.convertComponentSrcToImageSource)(src);
}
else {
return { src, renderingMode: options.renderingMode };
}
}
return undefined;
}
function isNativeTabTrigger(child, contextKey) {
if ((0, children_1.isChildOfType)(child, exports.NativeTabTrigger)) {
if ('name' in child.props && !child.props.name) {
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.`);
}
if (process.env.NODE_ENV !== 'production') {
if (['component', 'getComponent'].some((key) => key in child.props)) {
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`);
}
}
return true;
}
return false;
}
//# sourceMappingURL=NativeTabTrigger.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
import type { NativeTabsProps } from './types';
/**
* The component used to create native tabs layout.
*
* @example
* ```tsx app/_layout.tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default function Layout() {
* return (
* <NativeTabs>
* <NativeTabs.Trigger name="home" />
* <NativeTabs.Trigger name="settings" />
* </NativeTabs>
* );
* }
* ```
*/
export declare const NativeTabs: ((props: NativeTabsProps) => import("react").JSX.Element) & {
Trigger: ((props: import("./types").NativeTabTriggerProps) => null) & {
Label: import("react").FC<import("./common/elements").NativeTabsTriggerLabelProps>;
Icon: import("react").FC<import("./common/elements").NativeTabsTriggerIconProps>;
Badge: import("react").FC<import("./common/elements").NativeTabsTriggerBadgeProps>;
VectorIcon: typeof import("..").VectorIcon;
};
BottomAccessory: import("react").FC<import("./common/elements").NativeTabsBottomAccessoryProps> & {
usePlacement: () => "regular" | "inline";
};
};
//# sourceMappingURL=NativeTabs.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeTabs.d.ts","sourceRoot":"","sources":["../../src/native-tabs/NativeTabs.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAM/C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,UAAU,WACb,eAAe;;;;;;;;;;CAIxB,CAAC"}

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabs = void 0;
// We need this file to re-export the navigator
// Otherwise rsc would fail
const NativeBottomTabsNavigator_1 = require("./NativeBottomTabsNavigator");
const NativeTabTrigger_1 = require("./NativeTabTrigger");
const elements_1 = require("./common/elements");
const hooks_1 = require("./hooks");
const BottomAccessory = Object.assign(elements_1.NativeTabsBottomAccessory, {
usePlacement: hooks_1.usePlacement,
});
/**
* The component used to create native tabs layout.
*
* @example
* ```tsx app/_layout.tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default function Layout() {
* return (
* <NativeTabs>
* <NativeTabs.Trigger name="home" />
* <NativeTabs.Trigger name="settings" />
* </NativeTabs>
* );
* }
* ```
*/
exports.NativeTabs = Object.assign((props) => {
return <NativeBottomTabsNavigator_1.NativeTabsNavigatorWrapper {...props}/>;
}, { Trigger: NativeTabTrigger_1.NativeTabTrigger, BottomAccessory });
//# sourceMappingURL=NativeTabs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeTabs.js","sourceRoot":"","sources":["../../src/native-tabs/NativeTabs.tsx"],"names":[],"mappings":";;;AAAA,+CAA+C;AAC/C,2BAA2B;AAC3B,2EAAyE;AACzE,yDAAsD;AACtD,gDAA8D;AAC9D,mCAAuC;AAGvC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,oCAAyB,EAAE;IAC/D,YAAY,EAAZ,oBAAY;CACb,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;GAgBG;AACU,QAAA,UAAU,GAAG,MAAM,CAAC,MAAM,CACrC,CAAC,KAAsB,EAAE,EAAE;IACzB,OAAO,CAAC,sDAA0B,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACnD,CAAC,EACD,EAAE,OAAO,EAAE,mCAAgB,EAAE,eAAe,EAAE,CAC/C,CAAC","sourcesContent":["// We need this file to re-export the navigator\n// Otherwise rsc would fail\nimport { NativeTabsNavigatorWrapper } from './NativeBottomTabsNavigator';\nimport { NativeTabTrigger } from './NativeTabTrigger';\nimport { NativeTabsBottomAccessory } from './common/elements';\nimport { usePlacement } from './hooks';\nimport type { NativeTabsProps } from './types';\n\nconst BottomAccessory = Object.assign(NativeTabsBottomAccessory, {\n usePlacement,\n});\n\n/**\n * The component used to create native tabs layout.\n *\n * @example\n * ```tsx app/_layout.tsx\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 <NativeTabsNavigatorWrapper {...props} />;\n },\n { Trigger: NativeTabTrigger, BottomAccessory }\n);\n"]}

View File

@@ -0,0 +1,4 @@
import React from 'react';
import { type NativeTabsViewProps } from './types';
export declare function NativeTabsView(props: NativeTabsViewProps): React.JSX.Element;
//# sourceMappingURL=NativeTabsView.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeTabsView.d.ts","sourceRoot":"","sources":["../../src/native-tabs/NativeTabsView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoC,MAAM,OAAO,CAAC;AAYzD,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,SAAS,CAAC;AASjB,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,qBAyHxD"}

View File

@@ -0,0 +1,158 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabsView = NativeTabsView;
const native_1 = require("@react-navigation/native");
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const react_native_safe_area_context_1 = require("react-native-safe-area-context");
const react_native_screens_1 = require("react-native-screens");
const experimental_1 = require("react-native-screens/experimental");
const appearance_1 = require("./appearance");
const color_1 = require("../color");
const elements_1 = require("./common/elements");
const types_1 = require("./types");
const icon_1 = require("./utils/icon");
const children_1 = require("../utils/children");
const bottomAccessory_1 = require("./utils/bottomAccessory");
function NativeTabsView(props) {
const { minimizeBehavior, disableIndicator, focusedIndex, tabs, sidebarAdaptable, nonTriggerChildren, } = props;
const deferredFocusedIndex = (0, react_1.useDeferredValue)(focusedIndex);
// We need to check if the deferred index is not out of bounds
// This can happen when the focused index is the last tab, and user removes that tab
// In that case the deferred index will still point to the last tab, but after re-render
// it will be out of bounds
const inBoundsDeferredFocusedIndex = deferredFocusedIndex < tabs.length ? deferredFocusedIndex : focusedIndex;
const appearances = tabs.map((tab) => ({
standardAppearance: (0, appearance_1.createStandardAppearanceFromOptions)(tab.options),
scrollEdgeAppearance: (0, appearance_1.createScrollEdgeAppearanceFromOptions)(tab.options),
}));
const options = tabs.map((tab) => tab.options);
const bottomAccessory = (0, react_1.useMemo)(() => (0, children_1.getFirstChildOfType)(nonTriggerChildren, elements_1.NativeTabsBottomAccessory), [nonTriggerChildren]);
const bottomAccessoryFn = (0, bottomAccessory_1.useBottomAccessoryFunctionFromBottomAccessories)(bottomAccessory);
const children = tabs.map((tab, index) => {
const isFocused = index === inBoundsDeferredFocusedIndex;
return (<Screen key={tab.routeKey} routeKey={tab.routeKey} name={tab.name} options={tab.options} isFocused={isFocused} standardAppearance={appearances[index].standardAppearance} scrollEdgeAppearance={appearances[index].scrollEdgeAppearance} badgeTextColor={tab.options.badgeTextColor} contentRenderer={tab.contentRenderer}/>);
});
const currentTabAppearance = appearances[inBoundsDeferredFocusedIndex]?.standardAppearance;
const tabBarControllerMode = sidebarAdaptable
? 'tabSidebar'
: sidebarAdaptable === false
? 'tabBar'
: 'automatic';
// Material Design 3 dynamic color defaults for Android
const androidMaterialDefaults = process.env.EXPO_OS === 'android'
? {
inactiveColor: color_1.Color.android.dynamic.onSurfaceVariant,
activeIconColor: color_1.Color.android.dynamic.onSecondaryContainer,
activeLabelColor: color_1.Color.android.dynamic.onSurface,
backgroundColor: color_1.Color.android.dynamic.surfaceContainer,
rippleColor: color_1.Color.android.dynamic.primary,
indicatorColor: color_1.Color.android.dynamic.secondaryContainer,
}
: undefined;
return (<TabsHostWrapper
// #region android props
tabBarItemTitleFontColor={currentTabAppearance?.stacked?.normal?.tabBarItemTitleFontColor ??
androidMaterialDefaults?.inactiveColor} tabBarItemTitleFontFamily={currentTabAppearance?.stacked?.normal?.tabBarItemTitleFontFamily} tabBarItemTitleFontSize={currentTabAppearance?.stacked?.normal?.tabBarItemTitleFontSize} tabBarItemTitleFontSizeActive={currentTabAppearance?.stacked?.normal?.tabBarItemTitleFontSize} tabBarItemTitleFontWeight={currentTabAppearance?.stacked?.normal?.tabBarItemTitleFontWeight} tabBarItemTitleFontStyle={currentTabAppearance?.stacked?.normal?.tabBarItemTitleFontStyle} tabBarItemIconColor={currentTabAppearance?.stacked?.normal?.tabBarItemIconColor ??
androidMaterialDefaults?.inactiveColor} tabBarBackgroundColor={currentTabAppearance?.tabBarBackgroundColor ?? androidMaterialDefaults?.backgroundColor} tabBarItemRippleColor={props.rippleColor ?? androidMaterialDefaults?.rippleColor} tabBarItemLabelVisibilityMode={props.labelVisibilityMode} tabBarItemIconColorActive={currentTabAppearance?.stacked?.selected?.tabBarItemIconColor ??
props?.tintColor ??
androidMaterialDefaults?.activeIconColor} tabBarItemTitleFontColorActive={currentTabAppearance?.stacked?.selected?.tabBarItemTitleFontColor ??
props?.tintColor ??
androidMaterialDefaults?.activeLabelColor}
// tabBarItemTitleFontSizeActive={activeStyle?.fontSize}
tabBarItemActiveIndicatorColor={options[inBoundsDeferredFocusedIndex]?.indicatorColor ??
androidMaterialDefaults?.indicatorColor} tabBarItemActiveIndicatorEnabled={!disableIndicator}
// #endregion
// #region iOS props
tabBarTintColor={props?.tintColor} tabBarMinimizeBehavior={minimizeBehavior} tabBarControllerMode={tabBarControllerMode} bottomAccessory={bottomAccessoryFn} tabBarHidden={props.hidden}
// #endregion
onNativeFocusChange={({ nativeEvent: { tabKey } }) => {
props.onTabChange(tabKey);
}}>
{children}
</TabsHostWrapper>);
}
function Screen(props) {
const { routeKey, name, options, isFocused, standardAppearance, scrollEdgeAppearance, badgeTextColor, contentRenderer, } = props;
const title = options.title ?? name;
// We need to await the icon, as VectorIcon will load asynchronously
const icon = (0, icon_1.useAwaitedScreensIcon)(options.icon);
const selectedIcon = (0, icon_1.useAwaitedScreensIcon)(options.selectedIcon);
const { colors } = (0, native_1.useTheme)();
const content = (<react_native_1.View
// https://github.com/software-mansion/react-native-screens/issues/2662#issuecomment-2757735088
collapsable={false} style={[
{ backgroundColor: colors.background },
options.contentStyle,
{ flex: 1, position: 'relative', overflow: 'hidden' },
]}>
{contentRenderer()}
</react_native_1.View>);
const wrappedContent = (0, react_1.useMemo)(() => {
if (process.env.EXPO_OS === 'android' && !options.disableAutomaticContentInsets) {
return (<experimental_1.SafeAreaView
// https://github.com/software-mansion/react-native-screens/issues/2662#issuecomment-2757735088
collapsable={false} style={{ flex: 1 }} edges={{ bottom: true }}>
{content}
</experimental_1.SafeAreaView>);
}
else if (process.env.EXPO_OS === 'ios') {
return <react_native_safe_area_context_1.SafeAreaProvider>{content}</react_native_safe_area_context_1.SafeAreaProvider>;
}
else {
return content;
}
}, [content, options.disableAutomaticContentInsets]);
return (<react_native_screens_1.Tabs.Screen {...options} overrideScrollViewContentInsetAdjustmentBehavior={!options.disableAutomaticContentInsets} tabBarItemBadgeBackgroundColor={standardAppearance.stacked?.normal?.tabBarItemBadgeBackgroundColor} tabBarItemBadgeTextColor={badgeTextColor} standardAppearance={standardAppearance} scrollEdgeAppearance={scrollEdgeAppearance} icon={(0, icon_1.convertOptionsIconToRNScreensPropsIcon)(icon, standardAppearance?.stacked?.normal?.tabBarItemIconColor)} selectedIcon={(0, icon_1.convertOptionsIconToIOSPropsIcon)(selectedIcon, standardAppearance?.stacked?.selected?.tabBarItemIconColor)} title={title} freezeContents={false} systemItem={options.role} {...options.nativeProps} tabKey={routeKey} isFocused={isFocused}>
{wrappedContent}
</react_native_screens_1.Tabs.Screen>);
}
const supportedTabBarMinimizeBehaviorsSet = new Set(types_1.SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS);
const supportedTabBarItemLabelVisibilityModesSet = new Set(types_1.SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES);
function TabsHostWrapper(props) {
let { tabBarMinimizeBehavior, tabBarItemLabelVisibilityMode, ...rest } = props;
if (tabBarMinimizeBehavior && !supportedTabBarMinimizeBehaviorsSet.has(tabBarMinimizeBehavior)) {
console.warn(`Unsupported minimizeBehavior: ${tabBarMinimizeBehavior}. Supported values are: ${types_1.SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS.map((behavior) => `"${behavior}"`).join(', ')}`);
tabBarMinimizeBehavior = undefined;
}
if (tabBarItemLabelVisibilityMode &&
!supportedTabBarItemLabelVisibilityModesSet.has(tabBarItemLabelVisibilityMode)) {
console.warn(`Unsupported labelVisibilityMode: ${tabBarItemLabelVisibilityMode}. Supported values are: ${types_1.SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES.map((mode) => `"${mode}"`).join(', ')}`);
tabBarItemLabelVisibilityMode = undefined;
}
return (<react_native_screens_1.Tabs.Host tabBarItemLabelVisibilityMode={tabBarItemLabelVisibilityMode} tabBarMinimizeBehavior={tabBarMinimizeBehavior} {...rest}/>);
}
//# sourceMappingURL=NativeTabsView.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
import React from 'react';
import type { NativeTabsViewProps } from './types';
export declare function NativeTabsView(props: NativeTabsViewProps): React.JSX.Element;
//# sourceMappingURL=NativeTabsView.web.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeTabsView.web.d.ts","sourceRoot":"","sources":["../../src/native-tabs/NativeTabsView.web.tsx"],"names":[],"mappings":"AACA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAoB,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGrE,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,qBA6CxD"}

View File

@@ -0,0 +1,119 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabsView = NativeTabsView;
const react_tabs_1 = require("@radix-ui/react-tabs");
const react_1 = __importStar(require("react"));
const native_tabs_module_css_1 = __importDefault(require("../../assets/native-tabs.module.css"));
function NativeTabsView(props) {
const { tabs, focusedIndex } = props;
const currentTab = tabs[focusedIndex];
const defaultTab = (0, react_1.useMemo)(() => currentTab,
// We don't specify currentTab here, as we don't want to change the default tab when focusedIndex changes
[]);
const value = currentTab.routeKey;
const items = tabs.map((tab) => (<TabItem key={tab.routeKey} routeKey={tab.routeKey} title={tab.options.title ?? tab.name} badgeValue={tab.options.badgeValue}/>));
const children = tabs.map((tab) => {
return (<react_tabs_1.TabsContent key={tab.routeKey} value={tab.routeKey} className={native_tabs_module_css_1.default.tabContent} forceMount>
{tab.contentRenderer()}
</react_tabs_1.TabsContent>);
});
return (<react_tabs_1.Tabs className={native_tabs_module_css_1.default.nativeTabsContainer} defaultValue={defaultTab.routeKey} value={value} onValueChange={(value) => {
props.onTabChange(value);
}} style={convertNativeTabsPropsToStyleVars(props, currentTab.options)}>
<react_tabs_1.TabsList aria-label="Main" className={native_tabs_module_css_1.default.navigationMenuRoot}>
{items}
</react_tabs_1.TabsList>
{children}
</react_tabs_1.Tabs>);
}
function TabItem(props) {
const { title, badgeValue, routeKey } = props;
const isBadgeEmpty = badgeValue === ' ';
return (<react_tabs_1.TabsTrigger value={routeKey} className={native_tabs_module_css_1.default.navigationMenuTrigger}>
<span className={native_tabs_module_css_1.default.tabText}>{title}</span>
{badgeValue && (<div className={`${native_tabs_module_css_1.default.tabBadge} ${isBadgeEmpty ? native_tabs_module_css_1.default.emptyTabBadge : ''}`}>
{badgeValue}
</div>)}
</react_tabs_1.TabsTrigger>);
}
function convertNativeTabsPropsToStyleVars(props, currentTabOptions) {
const vars = {};
if (!props) {
return vars;
}
const optionsLabelStyle = currentTabOptions?.labelStyle;
if (optionsLabelStyle?.fontFamily) {
vars['--expo-router-tabs-font-family'] = String(optionsLabelStyle.fontFamily);
}
if (optionsLabelStyle?.fontSize) {
vars['--expo-router-tabs-font-size'] = String(optionsLabelStyle.fontSize);
}
if (optionsLabelStyle?.fontWeight) {
vars['--expo-router-tabs-font-weight'] = String(optionsLabelStyle.fontWeight);
}
if (optionsLabelStyle?.fontStyle) {
vars['--expo-router-tabs-font-style'] = String(optionsLabelStyle.fontStyle);
}
if (optionsLabelStyle?.color) {
vars['--expo-router-tabs-text-color'] = String(optionsLabelStyle.color);
}
if (currentTabOptions?.selectedLabelStyle?.color) {
vars['--expo-router-tabs-active-text-color'] = String(currentTabOptions?.selectedLabelStyle?.color);
}
else if (props.tintColor) {
vars['--expo-router-tabs-active-text-color'] = String(props.tintColor);
}
if (currentTabOptions?.selectedLabelStyle?.fontSize) {
vars['--expo-router-tabs-active-font-size'] = String(currentTabOptions?.selectedLabelStyle?.fontSize);
}
if (currentTabOptions?.indicatorColor) {
vars['--expo-router-tabs-active-background-color'] = String(currentTabOptions.indicatorColor);
}
if (currentTabOptions?.backgroundColor) {
vars['--expo-router-tabs-background-color'] = String(currentTabOptions.backgroundColor);
}
if (currentTabOptions?.badgeBackgroundColor) {
vars['--expo-router-tabs-badge-background-color'] = String(currentTabOptions.badgeBackgroundColor);
}
if (currentTabOptions?.badgeTextColor) {
vars['--expo-router-tabs-badge-text-color'] = String(currentTabOptions.badgeTextColor);
}
return vars;
}
//# sourceMappingURL=NativeTabsView.web.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import type { ColorValue } from 'react-native';
import type { TabsScreenAppearance, TabsScreenItemStateAppearance } from 'react-native-screens';
import { type NativeTabOptions, type NativeTabsBlurEffect, type NativeTabsLabelStyle } from './types';
export declare function createStandardAppearanceFromOptions(options: NativeTabOptions): TabsScreenAppearance;
export declare function createScrollEdgeAppearanceFromOptions(options: NativeTabOptions): TabsScreenAppearance;
export interface AppearanceStyle extends NativeTabsLabelStyle {
iconColor?: ColorValue;
backgroundColor?: ColorValue | null;
blurEffect?: NativeTabsBlurEffect;
badgeBackgroundColor?: ColorValue;
shadowColor?: ColorValue;
titlePositionAdjustment?: {
horizontal?: number;
vertical?: number;
};
}
export declare function appendSelectedStyleToAppearance(selectedStyle: AppearanceStyle, appearance: TabsScreenAppearance): TabsScreenAppearance;
export declare function appendStyleToAppearance(style: AppearanceStyle, appearance: TabsScreenAppearance, states: ('selected' | 'focused' | 'disabled' | 'normal')[]): TabsScreenAppearance;
export declare function convertStyleToAppearance(style: AppearanceStyle | undefined): TabsScreenAppearance;
export declare function convertStyleToItemStateAppearance(style: AppearanceStyle | undefined): TabsScreenItemStateAppearance;
//# sourceMappingURL=appearance.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/native-tabs/appearance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EACV,oBAAoB,EAEpB,6BAA6B,EAC9B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAC;AAKjB,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,gBAAgB,GACxB,oBAAoB,CAgCtB;AAED,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,gBAAgB,GACxB,oBAAoB,CAgCtB;AAED,MAAM,WAAW,eAAgB,SAAQ,oBAAoB;IAC3D,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,eAAe,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,oBAAoB,CAAC,EAAE,UAAU,CAAC;IAClC,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,uBAAuB,CAAC,EAAE;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,eAAe,EAC9B,UAAU,EAAE,oBAAoB,GAC/B,oBAAoB,CAEtB;AASD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,CAAC,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC,EAAE,GACzD,oBAAoB,CA8BtB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,oBAAoB,CAmBjG;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,eAAe,GAAG,SAAS,GACjC,6BAA6B,CAsB/B"}

View File

@@ -0,0 +1,133 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createStandardAppearanceFromOptions = createStandardAppearanceFromOptions;
exports.createScrollEdgeAppearanceFromOptions = createScrollEdgeAppearanceFromOptions;
exports.appendSelectedStyleToAppearance = appendSelectedStyleToAppearance;
exports.appendStyleToAppearance = appendStyleToAppearance;
exports.convertStyleToAppearance = convertStyleToAppearance;
exports.convertStyleToItemStateAppearance = convertStyleToItemStateAppearance;
const types_1 = require("./types");
const style_1 = require("../utils/style");
const supportedBlurEffectsSet = new Set(types_1.SUPPORTED_BLUR_EFFECTS);
function createStandardAppearanceFromOptions(options) {
let blurEffect = options.blurEffect;
if (blurEffect && !supportedBlurEffectsSet.has(blurEffect)) {
console.warn(`Unsupported blurEffect: ${blurEffect}. Supported values are: ${types_1.SUPPORTED_BLUR_EFFECTS.map((effect) => `"${effect}"`).join(', ')}`);
blurEffect = undefined;
}
const appearance = appendStyleToAppearance({
...options.labelStyle,
iconColor: options.iconColor,
backgroundColor: options.backgroundColor,
blurEffect,
badgeBackgroundColor: options.badgeBackgroundColor,
titlePositionAdjustment: options.titlePositionAdjustment,
shadowColor: options.shadowColor,
}, {}, ['normal', 'focused', 'selected']);
return appendSelectedStyleToAppearance({
...(options.selectedLabelStyle ?? {}),
iconColor: options.selectedIconColor,
badgeBackgroundColor: options.selectedBadgeBackgroundColor,
titlePositionAdjustment: options.selectedTitlePositionAdjustment,
}, appearance);
}
function createScrollEdgeAppearanceFromOptions(options) {
let blurEffect = options.disableTransparentOnScrollEdge ? options.blurEffect : 'none';
if (blurEffect && !supportedBlurEffectsSet.has(blurEffect)) {
console.warn(`Unsupported blurEffect: ${blurEffect}. Supported values are: ${types_1.SUPPORTED_BLUR_EFFECTS.map((effect) => `"${effect}"`).join(', ')}`);
blurEffect = undefined;
}
const appearance = appendStyleToAppearance({
...options.labelStyle,
iconColor: options.iconColor,
blurEffect,
backgroundColor: options.disableTransparentOnScrollEdge ? options.backgroundColor : null,
shadowColor: options.disableTransparentOnScrollEdge ? options.shadowColor : 'transparent',
badgeBackgroundColor: options.badgeBackgroundColor,
titlePositionAdjustment: options.titlePositionAdjustment,
}, {}, ['normal', 'focused', 'selected']);
return appendSelectedStyleToAppearance({
...(options.selectedLabelStyle ?? {}),
iconColor: options.selectedIconColor,
badgeBackgroundColor: options.selectedBadgeBackgroundColor,
titlePositionAdjustment: options.selectedTitlePositionAdjustment,
}, appearance);
}
function appendSelectedStyleToAppearance(selectedStyle, appearance) {
return appendStyleToAppearance(selectedStyle, appearance, ['selected', 'focused']);
}
const EMPTY_APPEARANCE_ITEM = {
normal: {},
selected: {},
focused: {},
disabled: {},
};
function appendStyleToAppearance(style, appearance, states) {
const baseItemAppearance = appearance.stacked || appearance.inline || appearance.compactInline || {};
const styleAppearance = convertStyleToAppearance(style);
const newAppearances = states.map((state) => ({
key: state,
appearance: {
...baseItemAppearance.normal,
...baseItemAppearance[state],
...styleAppearance.stacked?.normal,
},
}));
const itemAppearance = {
...EMPTY_APPEARANCE_ITEM,
...baseItemAppearance,
...Object.fromEntries(newAppearances.map(({ key, appearance }) => [key, appearance])),
};
return {
stacked: itemAppearance,
inline: itemAppearance,
compactInline: itemAppearance,
tabBarBackgroundColor: style.backgroundColor === null
? undefined
: (style.backgroundColor ?? appearance.tabBarBackgroundColor),
tabBarBlurEffect: styleAppearance.tabBarBlurEffect ?? appearance.tabBarBlurEffect,
tabBarShadowColor: styleAppearance.tabBarShadowColor ?? appearance.tabBarShadowColor,
};
}
function convertStyleToAppearance(style) {
if (!style) {
return {};
}
const stateAppearance = convertStyleToItemStateAppearance(style);
const itemAppearance = {
normal: stateAppearance,
selected: stateAppearance,
focused: stateAppearance,
disabled: {},
};
return {
inline: itemAppearance,
stacked: itemAppearance,
compactInline: itemAppearance,
tabBarBackgroundColor: style?.backgroundColor ?? undefined,
tabBarBlurEffect: style?.blurEffect,
tabBarShadowColor: style?.shadowColor,
};
}
function convertStyleToItemStateAppearance(style) {
if (!style) {
return {};
}
const stateAppearance = {
tabBarItemBadgeBackgroundColor: style.badgeBackgroundColor,
tabBarItemTitlePositionAdjustment: style.titlePositionAdjustment,
tabBarItemIconColor: style.iconColor,
tabBarItemTitleFontFamily: style.fontFamily,
tabBarItemTitleFontSize: style.fontSize,
tabBarItemTitleFontWeight: (0, style_1.convertFontWeightToStringFontWeight)(style.fontWeight),
tabBarItemTitleFontStyle: style.fontStyle,
tabBarItemTitleFontColor: style.color,
};
Object.keys(stateAppearance).forEach((key) => {
if (stateAppearance[key] === undefined) {
delete stateAppearance[key];
}
});
return stateAppearance;
}
//# sourceMappingURL=appearance.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,226 @@
import type { AndroidSymbol } from 'expo-symbols';
import type { ColorValue, ImageSourcePropType, StyleProp } from 'react-native';
import type { SFSymbol } from 'sf-symbols-typescript';
import { VectorIcon } from '../../primitives';
import type { NativeTabsLabelStyle } from '../types';
export interface NativeTabsTriggerLabelProps {
/**
* The text to display as the label for the tab.
*/
children?: string;
selectedStyle?: StyleProp<NativeTabsLabelStyle>;
/**
* If true, the label will be hidden.
* @default false
*/
hidden?: boolean;
}
export declare const NativeTabsTriggerLabel: React.FC<NativeTabsTriggerLabelProps>;
export interface SrcIcon {
/**
* The image source to use as an icon.
*
* When `sf` prop is used it will override this prop on iOS.
*
* When `drawable` or `material` prop is used it will override this prop on Android.
*
* The value can be provided in two ways:
* - As an image source
* - As an object specifying the default and selected states
*
* @example
* ```tsx
* <Icon src={require('./path/to/icon.png')} />
* ```
*
* @example
* ```tsx
* <Icon src={{ default: require('./path/to/icon.png'), selected: require('./path/to/icon-selected.png') }} />
* ```
*
* @platform Android
* @platform iOS
*/
src?: ImageSourcePropType | React.ReactElement | {
default?: ImageSourcePropType | React.ReactElement;
selected: ImageSourcePropType | React.ReactElement;
};
/**
* Controls how the image icon is rendered on iOS.
*
* - `'template'`: iOS applies tint color to the icon (selected/unselected states)
* - `'original'`: Preserves original icon colors
*
* **Default behavior:**
* - If tab bar icon color is configured, defaults to `'template'`
* - If no icon color is set, defaults to `'original'`
*
* @see [Apple documentation](https://developer.apple.com/documentation/uikit/uiimage/renderingmode-swift.enum) for more information.
*
* @platform ios
*/
renderingMode?: 'template' | 'original';
}
export interface SFSymbolIcon {
/**
* The name of the SF Symbol to use as an icon.
*
* The value can be provided in two ways:
* - As a string with the SF Symbol name
* - As an object specifying the default and selected states
*
* @example
* ```tsx
* <Icon sf="magnifyingglass" />
* ```
*
* @example
* ```tsx
* <Icon sf={{ default: "house", selected: "house.fill" }} />
* ```
*
* @platform iOS
*/
sf?: SFSymbol | {
default?: SFSymbol;
selected: SFSymbol;
};
}
export interface XcassetIcon {
/**
* The name of the iOS asset catalog image to use as an icon.
*
* Xcassets provide automatic multi-resolution (@1x/@2x/@3x), dark mode variants,
* and device-specific images via `[UIImage imageNamed:]`.
*
* The rendering mode (template vs original) can be controlled via the `renderingMode` prop
* on the `Icon` component. By default, icons are tinted when `iconColor` is set, and
* rendered as original otherwise.
*
* The value can be provided in two ways:
* - As a string with the asset catalog image name
* - As an object specifying the default and selected states
*
* @example
* ```tsx
* <Icon xcasset="custom-icon" />
* ```
*
* @example
* ```tsx
* <Icon xcasset={{ default: "home-outline", selected: "home-filled" }} />
* ```
*
* @platform iOS
*/
xcasset?: string | {
default?: string;
selected: string;
};
}
export interface DrawableIcon {
/**
* The name of the drawable resource to use as an icon.
* @platform android
*/
drawable?: string;
}
/**
* Material icon name for Android native tabs.
*
* @platform android
*/
export interface MaterialIcon {
/**
* Material icon glyph name. See the [Material icons for the complete catalog](https://fonts.google.com/icons).
*/
md: AndroidSymbol;
}
export type BaseNativeTabsTriggerIconProps = {
selectedColor?: ColorValue;
};
export type NativeTabsTriggerIconProps = BaseNativeTabsTriggerIconProps & ((SFSymbolIcon & DrawableIcon) | (SFSymbolIcon & MaterialIcon) | (SFSymbolIcon & SrcIcon) | (XcassetIcon & DrawableIcon) | (XcassetIcon & MaterialIcon) | (XcassetIcon & SrcIcon) | (MaterialIcon & SrcIcon) | (DrawableIcon & SrcIcon) | SrcIcon);
/**
* Renders an icon for the tab.
*
* Accepts various icon sources such as SF Symbols, xcasset images, drawable resources, material icons, or image sources.
*
* Acceptable props combinations:
* - `sf` and `drawable` - `sf` will be used for iOS icon, `drawable` for Android icon
* - `sf` and `src` - `sf` will be used for iOS icon, `src` for Android icon
* - `xcasset` and `drawable` - `xcasset` will be used for iOS icon, `drawable` for Android icon
* - `xcasset` and `md` - `xcasset` will be used for iOS icon, `md` for Android icon
* - `xcasset` and `src` - `xcasset` will be used for iOS icon, `src` for Android icon
* - `src` and `drawable` - `src` will be used for iOS icon, `drawable` for Android icon
* - `src` only - `src` will be used for both iOS and Android icons
*
* Priority on iOS: `sf` > `xcasset` > `src`. Priority on Android: `drawable` > `md` > `src`.
*
* @platform ios
* @platform android
*/
export declare const NativeTabsTriggerIcon: React.FC<NativeTabsTriggerIconProps>;
/**
* Helper component which can be used to load vector icons for `NativeTabs`.
*
* @example
* ```tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
* import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
*
* export default Layout(){
* return (
* <NativeTabs>
* <NativeTabs.Trigger name="index">
* <NativeTabs.Trigger.Icon src={<NativeTabs.Trigger.VectorIcon family={MaterialCommunityIcons} name="home" />} />
* </NativeTabs.Trigger>
* </NativeTabs>
* );
* }
* ```
*/
export declare const NativeTabsTriggerVectorIcon: typeof VectorIcon;
export interface NativeTabsTriggerPromiseIconProps {
loader: () => Promise<ImageSourcePropType | null>;
}
export declare const NativeTabsTriggerPromiseIcon: (props: NativeTabsTriggerPromiseIconProps) => null;
export interface NativeTabsTriggerBadgeProps {
/**
* The text to display as the badge for the tab.
* If not provided, the badge will not be displayed.
*/
children?: string;
/**
* If true, the badge will be hidden.
* @default false
*/
hidden?: boolean;
selectedBackgroundColor?: ColorValue;
}
export declare const NativeTabsTriggerBadge: React.FC<NativeTabsTriggerBadgeProps>;
export interface NativeTabsBottomAccessoryProps {
children?: React.ReactNode;
}
/**
* A [bottom accessory](https://developer.apple.com/documentation/uikit/uitabbarcontroller/bottomaccessory) for `NativeTabs` on iOS 26 and above.
*
* @example
* ```tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default Layout(){
* return (
* <NativeTabs>
* <NativeTabs.BottomAccessory>
* <YourAccessoryComponent />
* </NativeTabs.BottomAccessory>
* <NativeTabs.Trigger name="index" />
* </NativeTabs>
* );
* }
* ```
*
* @platform iOS 26+
*/
export declare const NativeTabsBottomAccessory: React.FC<NativeTabsBottomAccessoryProps>;
//# sourceMappingURL=elements.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/common/elements.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAsB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAC;IAChD;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAAS,CAAC;AAEnF,MAAM,WAAW,OAAO;IACtB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,GAAG,CAAC,EACA,mBAAmB,GACnB,KAAK,CAAC,YAAY,GAClB;QACE,OAAO,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAAC;QACnD,QAAQ,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAAC;KACpD,CAAC;IACN;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;;;;;;OAkBG;IACH,EAAE,CAAC,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAA;KAAE,CAAC;CAC5D;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,EAAE,EAAE,aAAa,CAAC;CACnB;AAED,MAAM,MAAM,8BAA8B,GAAG;IAAE,aAAa,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC;AAE5E,MAAM,MAAM,0BAA0B,GAAG,8BAA8B,GACrE,CACI,CAAC,YAAY,GAAG,YAAY,CAAC,GAC7B,CAAC,YAAY,GAAG,YAAY,CAAC,GAC7B,CAAC,YAAY,GAAG,OAAO,CAAC,GACxB,CAAC,WAAW,GAAG,YAAY,CAAC,GAC5B,CAAC,WAAW,GAAG,YAAY,CAAC,GAC5B,CAAC,WAAW,GAAG,OAAO,CAAC,GACvB,CAAC,YAAY,GAAG,OAAO,CAAC,GACxB,CAAC,YAAY,GAAG,OAAO,CAAC,GACxB,OAAO,CACV,CAAC;AAEJ;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAAQ,CAAC;AAEhF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,2BAA2B,mBAAa,CAAC;AAEtD,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,MAAM,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;CACnD;AAED,eAAO,MAAM,4BAA4B,GACvC,OAAO,iCAAiC,SAGzC,CAAC;AAEF,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uBAAuB,CAAC,EAAE,UAAU,CAAC;CACtC;AAED,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAAS,CAAC;AAEnF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,8BAA8B,CAE9E,CAAC"}

View File

@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabsBottomAccessory = exports.NativeTabsTriggerBadge = exports.NativeTabsTriggerPromiseIcon = exports.NativeTabsTriggerVectorIcon = exports.NativeTabsTriggerIcon = exports.NativeTabsTriggerLabel = void 0;
const primitives_1 = require("../../primitives");
exports.NativeTabsTriggerLabel = primitives_1.Label;
/**
* Renders an icon for the tab.
*
* Accepts various icon sources such as SF Symbols, xcasset images, drawable resources, material icons, or image sources.
*
* Acceptable props combinations:
* - `sf` and `drawable` - `sf` will be used for iOS icon, `drawable` for Android icon
* - `sf` and `src` - `sf` will be used for iOS icon, `src` for Android icon
* - `xcasset` and `drawable` - `xcasset` will be used for iOS icon, `drawable` for Android icon
* - `xcasset` and `md` - `xcasset` will be used for iOS icon, `md` for Android icon
* - `xcasset` and `src` - `xcasset` will be used for iOS icon, `src` for Android icon
* - `src` and `drawable` - `src` will be used for iOS icon, `drawable` for Android icon
* - `src` only - `src` will be used for both iOS and Android icons
*
* Priority on iOS: `sf` > `xcasset` > `src`. Priority on Android: `drawable` > `md` > `src`.
*
* @platform ios
* @platform android
*/
exports.NativeTabsTriggerIcon = primitives_1.Icon;
/**
* Helper component which can be used to load vector icons for `NativeTabs`.
*
* @example
* ```tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
* import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
*
* export default Layout(){
* return (
* <NativeTabs>
* <NativeTabs.Trigger name="index">
* <NativeTabs.Trigger.Icon src={<NativeTabs.Trigger.VectorIcon family={MaterialCommunityIcons} name="home" />} />
* </NativeTabs.Trigger>
* </NativeTabs>
* );
* }
* ```
*/
exports.NativeTabsTriggerVectorIcon = primitives_1.VectorIcon;
const NativeTabsTriggerPromiseIcon = function NativeTabsTriggerPromiseIcon(props) {
return null;
};
exports.NativeTabsTriggerPromiseIcon = NativeTabsTriggerPromiseIcon;
exports.NativeTabsTriggerBadge = primitives_1.Badge;
/**
* A [bottom accessory](https://developer.apple.com/documentation/uikit/uitabbarcontroller/bottomaccessory) for `NativeTabs` on iOS 26 and above.
*
* @example
* ```tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* export default Layout(){
* return (
* <NativeTabs>
* <NativeTabs.BottomAccessory>
* <YourAccessoryComponent />
* </NativeTabs.BottomAccessory>
* <NativeTabs.Trigger name="index" />
* </NativeTabs>
* );
* }
* ```
*
* @platform iOS 26+
*/
const NativeTabsBottomAccessory = () => {
return null;
};
exports.NativeTabsBottomAccessory = NativeTabsBottomAccessory;
//# sourceMappingURL=elements.js.map

File diff suppressed because one or more lines are too long

45
node_modules/expo-router/build/native-tabs/hooks.d.ts generated vendored Normal file
View File

@@ -0,0 +1,45 @@
export declare const BottomAccessoryPlacementContext: import("react").Context<"regular" | "inline" | undefined>;
/**
* A hook which returns the bottom accessory environment for given component.
*
* Note, that there can be two copies of the same component rendered for different environments.
* The hook will ensure that component with correct environment is displayed.
*
* Because two instances of the component will exist simultaneously, **any state kept
* inside the component will not be shared between the regular and inline versions**.
* If your accessory needs synchronized or persistent state you must store that state
* outside of bottom accessory component (e.g. passing via props or using context).
*
* Don't pass the environment obtained using this hook up the tree.
*
* @example
*
* ```tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* // This component will have two copies rendered, one for `inline` and one for `regular` environment
* function AccessoryContent(props) {
* const placement = NativeTabs.BottomAccessory.usePlacement();
* if (placement === 'inline') {
* return <InlineAccessoryComponent {...props} />;
* }
* return <RegularAccessoryComponent {...props} />;
* }
*
* export default function Layout(){
* const [isPlaying, setIsPlaying] = useState(false);
* return (
* <NativeTabs>
* <NativeTabs.BottomAccessory>
* <AccessoryContent isPlaying={isPlaying} setIsPlaying={setIsPlaying} />
* </NativeTabs.BottomAccessory>
* <NativeTabs.Trigger name="index" />
* </NativeTabs>
* );
* }
* ```
*
* @platform iOS 26+
*/
export declare const usePlacement: () => "regular" | "inline";
//# sourceMappingURL=hooks.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/native-tabs/hooks.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,+BAA+B,2DAE3C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAM,YAAY,QAAO,SAAS,GAAG,QAQ3C,CAAC"}

57
node_modules/expo-router/build/native-tabs/hooks.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePlacement = exports.BottomAccessoryPlacementContext = void 0;
const react_1 = require("react");
exports.BottomAccessoryPlacementContext = (0, react_1.createContext)(undefined);
/**
* A hook which returns the bottom accessory environment for given component.
*
* Note, that there can be two copies of the same component rendered for different environments.
* The hook will ensure that component with correct environment is displayed.
*
* Because two instances of the component will exist simultaneously, **any state kept
* inside the component will not be shared between the regular and inline versions**.
* If your accessory needs synchronized or persistent state you must store that state
* outside of bottom accessory component (e.g. passing via props or using context).
*
* Don't pass the environment obtained using this hook up the tree.
*
* @example
*
* ```tsx
* import { NativeTabs } from 'expo-router/unstable-native-tabs';
*
* // This component will have two copies rendered, one for `inline` and one for `regular` environment
* function AccessoryContent(props) {
* const placement = NativeTabs.BottomAccessory.usePlacement();
* if (placement === 'inline') {
* return <InlineAccessoryComponent {...props} />;
* }
* return <RegularAccessoryComponent {...props} />;
* }
*
* export default function Layout(){
* const [isPlaying, setIsPlaying] = useState(false);
* return (
* <NativeTabs>
* <NativeTabs.BottomAccessory>
* <AccessoryContent isPlaying={isPlaying} setIsPlaying={setIsPlaying} />
* </NativeTabs.BottomAccessory>
* <NativeTabs.Trigger name="index" />
* </NativeTabs>
* );
* }
* ```
*
* @platform iOS 26+
*/
const usePlacement = () => {
const value = (0, react_1.use)(exports.BottomAccessoryPlacementContext);
if (!value) {
throw new Error('usePlacement can only be used within a <NativeTabs.BottomAccessory> component.');
}
return value;
};
exports.usePlacement = usePlacement;
//# sourceMappingURL=hooks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/native-tabs/hooks.ts"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;AAEb,iCAA2C;AAE9B,QAAA,+BAA+B,GAAG,IAAA,qBAAa,EAC1D,SAAS,CACV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACI,MAAM,YAAY,GAAG,GAAyB,EAAE;IACrD,MAAM,KAAK,GAAG,IAAA,WAAG,EAAC,uCAA+B,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,gFAAgF,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AARW,QAAA,YAAY,gBAQvB","sourcesContent":["'use client';\n\nimport { createContext, use } from 'react';\n\nexport const BottomAccessoryPlacementContext = createContext<'regular' | 'inline' | undefined>(\n undefined\n);\n\n/**\n * A hook which returns the bottom accessory environment for given component.\n *\n * Note, that there can be two copies of the same component rendered for different environments.\n * The hook will ensure that component with correct environment is displayed.\n *\n * Because two instances of the component will exist simultaneously, **any state kept\n * inside the component will not be shared between the regular and inline versions**.\n * If your accessory needs synchronized or persistent state you must store that state\n * outside of bottom accessory component (e.g. passing via props or using context).\n *\n * Don't pass the environment obtained using this hook up the tree.\n *\n * @example\n *\n * ```tsx\n * import { NativeTabs } from 'expo-router/unstable-native-tabs';\n *\n * // This component will have two copies rendered, one for `inline` and one for `regular` environment\n * function AccessoryContent(props) {\n * const placement = NativeTabs.BottomAccessory.usePlacement();\n * if (placement === 'inline') {\n * return <InlineAccessoryComponent {...props} />;\n * }\n * return <RegularAccessoryComponent {...props} />;\n * }\n *\n * export default function Layout(){\n * const [isPlaying, setIsPlaying] = useState(false);\n * return (\n * <NativeTabs>\n * <NativeTabs.BottomAccessory>\n * <AccessoryContent isPlaying={isPlaying} setIsPlaying={setIsPlaying} />\n * </NativeTabs.BottomAccessory>\n * <NativeTabs.Trigger name=\"index\" />\n * </NativeTabs>\n * );\n * }\n * ```\n *\n * @platform iOS 26+\n */\nexport const usePlacement = (): 'regular' | 'inline' => {\n const value = use(BottomAccessoryPlacementContext);\n if (!value) {\n throw new Error(\n 'usePlacement can only be used within a <NativeTabs.BottomAccessory> component.'\n );\n }\n return value;\n};\n"]}

View File

@@ -0,0 +1,5 @@
export type { NativeTabsTriggerLabelProps, SrcIcon, SFSymbolIcon, XcassetIcon, DrawableIcon, MaterialIcon, BaseNativeTabsTriggerIconProps, NativeTabsTriggerIconProps, NativeTabsTriggerBadgeProps, NativeTabsBottomAccessoryProps, } from './common/elements';
export type { NativeTabsProps, NativeTabTriggerProps, NativeTabsLabelStyle, SymbolOrImageSource, NativeTabsTabBarItemLabelVisibilityMode, NativeTabsBlurEffect, NativeTabsTabBarMinimizeBehavior, NativeTabsTabBarItemRole, } from './types';
export { NativeTabTrigger } from './NativeTabTrigger';
export { NativeTabs } from './NativeTabs';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native-tabs/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,2BAA2B,EAC3B,OAAO,EACP,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,8BAA8B,EAC9B,0BAA0B,EAC1B,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uCAAuC,EACvC,oBAAoB,EACpB,gCAAgC,EAChC,wBAAwB,GACzB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}

8
node_modules/expo-router/build/native-tabs/index.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeTabs = exports.NativeTabTrigger = void 0;
var NativeTabTrigger_1 = require("./NativeTabTrigger");
Object.defineProperty(exports, "NativeTabTrigger", { enumerable: true, get: function () { return NativeTabTrigger_1.NativeTabTrigger; } });
var NativeTabs_1 = require("./NativeTabs");
Object.defineProperty(exports, "NativeTabs", { enumerable: true, get: function () { return NativeTabs_1.NativeTabs; } });
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/native-tabs/index.ts"],"names":[],"mappings":";;;AAsBA,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,2CAA0C;AAAjC,wGAAA,UAAU,OAAA","sourcesContent":["export type {\n NativeTabsTriggerLabelProps,\n SrcIcon,\n SFSymbolIcon,\n XcassetIcon,\n DrawableIcon,\n MaterialIcon,\n BaseNativeTabsTriggerIconProps,\n NativeTabsTriggerIconProps,\n NativeTabsTriggerBadgeProps,\n NativeTabsBottomAccessoryProps,\n} from './common/elements';\nexport type {\n NativeTabsProps,\n NativeTabTriggerProps,\n NativeTabsLabelStyle,\n SymbolOrImageSource,\n NativeTabsTabBarItemLabelVisibilityMode,\n NativeTabsBlurEffect,\n NativeTabsTabBarMinimizeBehavior,\n NativeTabsTabBarItemRole,\n} from './types';\nexport { NativeTabTrigger } from './NativeTabTrigger';\nexport { NativeTabs } from './NativeTabs';\n"]}

388
node_modules/expo-router/build/native-tabs/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,388 @@
import type { DefaultRouterOptions, EventMapBase, NavigationState, ParamListBase, RouteProp, ScreenListeners, TabNavigationState } from '@react-navigation/native';
import type { PropsWithChildren } from 'react';
import type { ColorValue, ImageSourcePropType, StyleProp, TextStyle, ViewStyle } from 'react-native';
import type { TabsScreenProps } from 'react-native-screens';
import type { SFSymbol } from 'sf-symbols-typescript';
/**
* Event map for `NativeTabs` navigation events.
* Only `tabPress` is currently supported.
*/
export type NativeTabNavigationEventMap = {
tabPress: {
data: {
__internalTabsType: 'native';
};
canPreventDefault: false;
};
};
export type NativeScreenProps = Partial<Omit<TabsScreenProps, 'tabKey' | 'isFocused'>>;
export interface NativeTabOptions extends DefaultRouterOptions {
icon?: SymbolOrImageSource;
selectedIcon?: SymbolOrImageSource;
title?: string;
badgeValue?: string;
selectedLabelStyle?: NativeTabsLabelStyle;
labelStyle?: NativeTabsLabelStyle;
role?: NativeTabsTabBarItemRole;
selectedIconColor?: ColorValue;
selectedBadgeBackgroundColor?: ColorValue;
badgeBackgroundColor?: ColorValue;
badgeTextColor?: ColorValue;
backgroundColor?: ColorValue;
blurEffect?: NativeTabsBlurEffect;
shadowColor?: ColorValue;
iconColor?: ColorValue;
disableTransparentOnScrollEdge?: boolean;
titlePositionAdjustment?: {
horizontal?: number;
vertical?: number;
};
selectedTitlePositionAdjustment?: {
horizontal?: number;
vertical?: number;
};
indicatorColor?: ColorValue;
hidden?: boolean;
specialEffects?: TabsScreenProps['specialEffects'];
nativeProps?: NativeScreenProps;
disableAutomaticContentInsets?: boolean;
contentStyle?: Pick<ViewStyle, 'backgroundColor' | 'experimental_backgroundImage' | 'padding' | 'paddingTop' | 'paddingBottom' | 'paddingLeft' | 'paddingRight' | 'paddingBlock' | 'paddingBlockEnd' | 'paddingBlockStart' | 'paddingInline' | 'paddingInlineEnd' | 'paddingInlineStart' | 'paddingEnd' | 'paddingHorizontal' | 'paddingVertical' | 'paddingStart' | 'alignContent' | 'alignItems' | 'justifyContent' | 'flexDirection' | 'gap'>;
}
export type SymbolOrImageSource = {
/**
* The name of the SF Symbol to use as an icon.
* @platform iOS
*/
sf?: SFSymbol;
/**
* The name of the iOS asset catalog image to use as an icon.
* @platform iOS
*/
xcasset?: string;
/**
* The name of the drawable resource to use as an icon.
* @platform android
*/
drawable?: string;
} | {
/**
* The image source to use as an icon.
*/
src?: ImageSourcePropType | Promise<ImageSourcePropType | null>;
/**
* Controls how the icon is rendered on iOS.
* @platform ios
* @default 'template'
*/
renderingMode?: 'template' | 'original';
};
export type NativeTabsLabelStyle = Pick<TextStyle, 'fontFamily' | 'fontSize' | 'fontStyle' | 'fontWeight' | 'color'>;
export declare const SUPPORTED_BLUR_EFFECTS: readonly ["none", "systemDefault", "extraLight", "light", "dark", "regular", "prominent", "systemUltraThinMaterial", "systemThinMaterial", "systemMaterial", "systemThickMaterial", "systemChromeMaterial", "systemUltraThinMaterialLight", "systemThinMaterialLight", "systemMaterialLight", "systemThickMaterialLight", "systemChromeMaterialLight", "systemUltraThinMaterialDark", "systemThinMaterialDark", "systemMaterialDark", "systemThickMaterialDark", "systemChromeMaterialDark"];
/**
* @see [Apple documentation](https://developer.apple.com/documentation/uikit/uiblureffect/style)
*/
export type NativeTabsBlurEffect = (typeof SUPPORTED_BLUR_EFFECTS)[number];
export interface NativeTabsProps extends PropsWithChildren {
/**
* The style of the every tab label in the tab bar.
*/
labelStyle?: StyleProp<NativeTabsLabelStyle> | {
default?: StyleProp<NativeTabsLabelStyle>;
selected?: StyleProp<NativeTabsLabelStyle>;
};
/**
* The color of every tab icon in the tab bar.
*/
iconColor?: ColorValue | {
default?: ColorValue;
selected?: ColorValue;
};
/**
* The tint color of the tab icon.
*
* Can be overridden by icon color and label color for each tab individually.
*/
tintColor?: ColorValue;
/**
* The background color of the tab bar.
*/
backgroundColor?: ColorValue;
/**
* The background color of every badge in the tab bar.
*/
badgeBackgroundColor?: ColorValue;
/**
* When set to `true`, hides the tab bar.
*
* @default false
*/
hidden?: boolean;
/**
* Specifies the minimize behavior for the tab bar.
*
* Available starting from iOS 26.
*
* The following values are currently supported:
*
* - `automatic` - resolves to the system default minimize behavior
* - `never` - the tab bar does not minimize
* - `onScrollDown` - the tab bar minimizes when scrolling down and
* expands when scrolling back up
* - `onScrollUp` - the tab bar minimizes when scrolling up and expands
* when scrolling back down
*
* @see The supported values correspond to the official [Apple documentation](https://developer.apple.com/documentation/uikit/uitabbarcontroller/minimizebehavior).
*
* @default automatic
*
* @platform iOS 26+
*/
minimizeBehavior?: NativeTabsTabBarMinimizeBehavior;
/**
* The blur effect applied to the tab bar.
*
* @platform iOS
*/
blurEffect?: NativeTabsBlurEffect;
/**
* The color of the shadow.
*
* @see [Apple documentation](https://developer.apple.com/documentation/uikit/uibarappearance/shadowcolor)
*
* @platform iOS
*/
shadowColor?: ColorValue;
/**
* @see [Apple documentation](https://developer.apple.com/documentation/uikit/uitabbaritem/titlepositionadjustment)
*
* @platform iOS
*/
titlePositionAdjustment?: {
horizontal?: number;
vertical?: number;
};
/**
* When set to `true`, the tab bar will not become transparent when scrolled to the edge.
*
* @platform iOS
*/
disableTransparentOnScrollEdge?: boolean;
/**
* When set to `true`, enables the sidebarAdaptable tab bar style on iPadOS and macOS. This prop has no effect on iPhone.
*
* @platform iOS 18+
*/
sidebarAdaptable?: boolean;
/**
* Disables the active indicator for the tab bar.
*
* @platform android
*/
disableIndicator?: boolean;
/**
* The behavior when navigating back with the back button.
*
* @platform android
*/
backBehavior?: 'none' | 'initialRoute' | 'history';
/**
* The visibility mode of the tab item label.
*
* @see [Material Components documentation](https://github.com/material-components/material-components-android/blob/master/docs/components/BottomNavigation.md#making-navigation-bar-accessible)
*
* @platform android
*/
labelVisibilityMode?: NativeTabsTabBarItemLabelVisibilityMode;
/**
* The color of the ripple effect when the tab is pressed.
*
* @platform android
*/
rippleColor?: ColorValue;
/**
* The color of the tab indicator.
*
* @platform android
* @platform web
*/
indicatorColor?: ColorValue;
/**
* The color of the badge text.
*
* @platform android
* @platform web
*/
badgeTextColor?: ColorValue;
/**
* Listeners for navigation events on all tabs.
*
* Supported events:
* - `tabPress` - called when a tab is pressed
* - `focus` - called when the screen comes into focus
* - `blur` - called when the screen loses focus
*
* @example
* ```tsx
* <NativeTabs
* screenListeners={{
* tabPress: (e) => {
* console.log('Any tab pressed');
* },
* }}
* >
* ...
* </NativeTabs>
* ```
*/
screenListeners?: ScreenListeners<TabNavigationState<ParamListBase>, NativeTabNavigationEventMap> | ((prop: {
route: RouteProp<ParamListBase, string>;
}) => ScreenListeners<TabNavigationState<ParamListBase>, NativeTabNavigationEventMap>);
}
export interface InternalNativeTabsProps extends NativeTabsProps {
nonTriggerChildren?: React.ReactNode;
}
export interface NativeTabsViewProps extends Omit<InternalNativeTabsProps, 'labelStyle' | 'iconColor' | 'backgroundColor' | 'badgeBackgroundColor' | 'blurEffect' | 'indicatorColor' | 'badgeTextColor'> {
focusedIndex: number;
tabs: NativeTabsViewTabItem[];
onTabChange: (tabKey: string) => void;
}
export interface NativeTabsViewTabItem {
options: NativeTabOptions;
routeKey: string;
name: string;
contentRenderer: () => React.ReactNode;
}
export declare const SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES: readonly ["auto", "selected", "labeled", "unlabeled"];
/**
* @see [Material Components documentation](https://github.com/material-components/material-components-android/blob/master/docs/components/BottomNavigation.md#making-navigation-bar-accessible)
*
* @platform android
*/
export type NativeTabsTabBarItemLabelVisibilityMode = (typeof SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES)[number];
export declare const SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS: readonly ["automatic", "never", "onScrollDown", "onScrollUp"];
/**
* @see [Apple documentation](https://developer.apple.com/documentation/uikit/uitabbarcontroller/minimizebehavior)
*
* @platform iOS 26
*/
export type NativeTabsTabBarMinimizeBehavior = (typeof SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS)[number];
export interface NativeTabTriggerProps {
/**
* The name of the route.
*
* This is required when used inside a Layout component.
*
* When used in a route it has no effect.
*/
name?: string;
/**
* If true, the tab will be hidden from the tab bar.
*
* > **Note**: Marking a tab as `hidden` means it cannot be navigated to in any way.
*
* > **Note**: Dynamically hiding tabs will remount the navigator and the state will be reset.
*/
hidden?: boolean;
/**
* Props passed to the underlying native tab screen implementation.
* Use this to configure props not directly exposed by Expo Router, but available in `react-native-screens`.
*
* > **Note**: This will override any other props set by Expo Router and may lead to unexpected behavior.
*
* > **Note**: This is an unstable API and may change or be removed in minor versions.
*
* @platform android
* @platform iOS
*/
unstable_nativeProps?: NativeScreenProps;
/**
* If true, the tab will not pop stack to the root when selected again.
*
* @default false
* @platform iOS
*/
disablePopToTop?: boolean;
/**
* If true, the tab will not scroll to the top when selected again.
* @default false
*
* @platform iOS
*/
disableScrollToTop?: boolean;
/**
* The children of the trigger.
*
* Use `Icon`, `Label`, and `Badge` components to customize the tab.
*/
children?: React.ReactNode;
/**
* System-provided tab bar item with predefined icon and title
*
* Uses Apple's built-in tab bar items (e.g., bookmarks, contacts, downloads) with
* standard iOS styling and localized titles. Custom `icon` or `selectedIcon`
* properties will override the system icon, but the system-defined title cannot
* be customized.
*
* @see The supported values correspond to the official [Apple documentation](https://developer.apple.com/documentation/uikit/uitabbaritem/systemitem).
* @platform ios
*/
role?: NativeTabsTabBarItemRole;
/**
* The default behavior differs between iOS and Android.
*
* On **Android**, the content of a native tabs screen is automatically wrapped in a `SafeAreaView`,
* and the **bottom** inset is applied. Other insets must be handled manually.
*
* On **iOS**, the first scroll view nested inside a native tabs screen has
* [automatic content inset adjustment](https://reactnative.dev/docs/scrollview#contentinsetadjustmentbehavior-ios) enabled
*
* When this property is set to `true`, automatic content inset adjustment is disabled for the screen
* and must be managed manually. You can use `SafeAreaView` from `react-native-screens/experimental`
* to handle safe area insets.
*
* @platform android
* @platform ios
*/
disableAutomaticContentInsets?: boolean;
/**
* The style applied to the content of the tab
*
* Note: Only certain style properties are supported.
*/
contentStyle?: NativeTabOptions['contentStyle'];
/**
* When set to `true`, the tab bar will not become transparent when scrolled to the edge.
*
* When set on a trigger, it takes precedence over the value set on `NativeTabs`.
*
* @platform iOS
*/
disableTransparentOnScrollEdge?: boolean;
/**
* Listeners for navigation events on this tab.
*
* Supported events:
* - `tabPress` - called when this tab is pressed
* - `focus` - called when this screen comes into focus
* - `blur` - called when this screen loses focus
*
* @example
* ```tsx
* <NativeTabs.Trigger
* name="home"
* listeners={{
* tabPress: (e) => {
* console.log('Home tab pressed');
* },
* }}
* />
* ```
*/
listeners?: ScreenListeners<NavigationState, EventMapBase> | ((prop: {
route: RouteProp<ParamListBase, string>;
}) => ScreenListeners<NavigationState, EventMapBase>);
}
declare const SUPPORTED_TAB_BAR_ITEM_ROLES: readonly ["bookmarks", "contacts", "downloads", "favorites", "featured", "history", "more", "mostRecent", "mostViewed", "recents", "search", "topRated"];
export type NativeTabsTabBarItemRole = (typeof SUPPORTED_TAB_BAR_ITEM_ROLES)[number];
export {};
//# sourceMappingURL=types.d.ts.map

File diff suppressed because one or more lines are too long

54
node_modules/expo-router/build/native-tabs/types.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS = exports.SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES = exports.SUPPORTED_BLUR_EFFECTS = void 0;
exports.SUPPORTED_BLUR_EFFECTS = [
'none',
'systemDefault',
'extraLight',
'light',
'dark',
'regular',
'prominent',
'systemUltraThinMaterial',
'systemThinMaterial',
'systemMaterial',
'systemThickMaterial',
'systemChromeMaterial',
'systemUltraThinMaterialLight',
'systemThinMaterialLight',
'systemMaterialLight',
'systemThickMaterialLight',
'systemChromeMaterialLight',
'systemUltraThinMaterialDark',
'systemThinMaterialDark',
'systemMaterialDark',
'systemThickMaterialDark',
'systemChromeMaterialDark',
];
exports.SUPPORTED_TAB_BAR_ITEM_LABEL_VISIBILITY_MODES = [
'auto',
'selected',
'labeled',
'unlabeled',
];
exports.SUPPORTED_TAB_BAR_MINIMIZE_BEHAVIORS = [
'automatic',
'never',
'onScrollDown',
'onScrollUp',
];
const SUPPORTED_TAB_BAR_ITEM_ROLES = [
'bookmarks',
'contacts',
'downloads',
'favorites',
'featured',
'history',
'more',
'mostRecent',
'mostViewed',
'recents',
'search',
'topRated',
];
//# sourceMappingURL=types.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
import { type ReactElement } from 'react';
import type { TabAccessoryComponentFactory } from 'react-native-screens';
import type { NativeTabsBottomAccessoryProps } from '../common/elements';
/**
* Converts `<NativeTabs.BottomAccessory>` component into a function,
* which can be used by `react-native-screens` to render the accessory.
*/
export declare function useBottomAccessoryFunctionFromBottomAccessories(bottomAccessory: ReactElement<NativeTabsBottomAccessoryProps, string | React.JSXElementConstructor<any>> | undefined): TabAccessoryComponentFactory | undefined;
//# sourceMappingURL=bottomAccessory.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bottomAccessory.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/utils/bottomAccessory.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAGzE;;;GAGG;AACH,wBAAgB,+CAA+C,CAC7D,eAAe,EACX,YAAY,CAAC,8BAA8B,EAAE,MAAM,GAAG,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,GACvF,SAAS,GACZ,4BAA4B,GAAG,SAAS,CAY1C"}

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useBottomAccessoryFunctionFromBottomAccessories = useBottomAccessoryFunctionFromBottomAccessories;
const react_1 = require("react");
const hooks_1 = require("../hooks");
/**
* Converts `<NativeTabs.BottomAccessory>` component into a function,
* which can be used by `react-native-screens` to render the accessory.
*/
function useBottomAccessoryFunctionFromBottomAccessories(bottomAccessory) {
return (0, react_1.useMemo)(() => bottomAccessory
? (environment) => (<hooks_1.BottomAccessoryPlacementContext value={environment}>
{bottomAccessory.props.children}
</hooks_1.BottomAccessoryPlacementContext>)
: undefined, [bottomAccessory]);
}
//# sourceMappingURL=bottomAccessory.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"bottomAccessory.js","sourceRoot":"","sources":["../../../src/native-tabs/utils/bottomAccessory.tsx"],"names":[],"mappings":";;AAUA,0GAgBC;AA1BD,iCAAmD;AAInD,oCAA2D;AAE3D;;;GAGG;AACH,SAAgB,+CAA+C,CAC7D,eAEa;IAEb,OAAO,IAAA,eAAO,EACZ,GAAG,EAAE,CACH,eAAe;QACb,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CACf,CAAC,uCAA+B,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAClD;cAAA,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,CACjC;YAAA,EAAE,uCAA+B,CAAC,CACnC;QACH,CAAC,CAAC,SAAS,EACf,CAAC,eAAe,CAAC,CAClB,CAAC;AACJ,CAAC","sourcesContent":["import { useMemo, type ReactElement } from 'react';\nimport type { TabAccessoryComponentFactory } from 'react-native-screens';\n\nimport type { NativeTabsBottomAccessoryProps } from '../common/elements';\nimport { BottomAccessoryPlacementContext } from '../hooks';\n\n/**\n * Converts `<NativeTabs.BottomAccessory>` component into a function,\n * which can be used by `react-native-screens` to render the accessory.\n */\nexport function useBottomAccessoryFunctionFromBottomAccessories(\n bottomAccessory:\n | ReactElement<NativeTabsBottomAccessoryProps, string | React.JSXElementConstructor<any>>\n | undefined\n): TabAccessoryComponentFactory | undefined {\n return useMemo<TabAccessoryComponentFactory | undefined>(\n () =>\n bottomAccessory\n ? (environment) => (\n <BottomAccessoryPlacementContext value={environment}>\n {bottomAccessory.props.children}\n </BottomAccessoryPlacementContext>\n )\n : undefined,\n [bottomAccessory]\n );\n}\n"]}

View File

@@ -0,0 +1,32 @@
import type { ColorValue, ImageSourcePropType } from 'react-native';
import type { TabsScreenProps, PlatformIconAndroid, PlatformIconIOS } from 'react-native-screens';
import type { SFSymbol } from 'sf-symbols-typescript';
import type { NativeTabOptions, NativeTabsProps } from '../types';
export declare function convertIconColorPropToObject(iconColor: NativeTabsProps['iconColor']): {
default?: ColorValue;
selected?: ColorValue;
};
type AwaitedIcon = {
sf?: SFSymbol;
xcasset?: string;
drawable?: string;
} | {
src?: ImageSourcePropType;
renderingMode?: 'template' | 'original';
};
export declare function useAwaitedScreensIcon(icon: NativeTabOptions['icon']): {
sf?: SFSymbol;
xcasset?: string;
drawable?: string;
} | {
src?: ImageSourcePropType;
renderingMode?: "template" | "original";
} | undefined;
export declare function convertOptionsIconToRNScreensPropsIcon(icon: AwaitedIcon | undefined, iconColor?: ColorValue): TabsScreenProps['icon'];
export declare function convertOptionsIconToIOSPropsIcon(icon: AwaitedIcon | undefined, iconColor?: ColorValue): PlatformIconIOS | undefined;
export declare function convertOptionsIconToAndroidPropsIcon(icon: AwaitedIcon): PlatformIconAndroid | undefined;
export declare function convertComponentSrcToImageSource(src: React.ReactElement): {
src: Promise<ImageSourcePropType | null>;
} | undefined;
export {};
//# sourceMappingURL=icon.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/utils/icon.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAClG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAElE,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,GAAG;IACrF,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB,CAUA;AAED,KAAK,WAAW,GACZ;IACE,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACD;IACE,GAAG,CAAC,EAAE,mBAAmB,CAAC;IAC1B,aAAa,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CACzC,CAAC;AAEN,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC;;;;;UAJxD,mBAAmB;oBACT,UAAU,GAAG,UAAU;cAyB5C;AAMD,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,SAAS,CAAC,EAAE,UAAU,GACrB,eAAe,CAAC,MAAM,CAAC,CAQzB;AAED,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,SAAS,CAAC,EAAE,UAAU,GACrB,eAAe,GAAG,SAAS,CAqB7B;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,WAAW,GAChB,mBAAmB,GAAG,SAAS,CAWjC;AAED,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,KAAK,CAAC,YAAY;;cAUvE"}

View File

@@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertIconColorPropToObject = convertIconColorPropToObject;
exports.useAwaitedScreensIcon = useAwaitedScreensIcon;
exports.convertOptionsIconToRNScreensPropsIcon = convertOptionsIconToRNScreensPropsIcon;
exports.convertOptionsIconToIOSPropsIcon = convertOptionsIconToIOSPropsIcon;
exports.convertOptionsIconToAndroidPropsIcon = convertOptionsIconToAndroidPropsIcon;
exports.convertComponentSrcToImageSource = convertComponentSrcToImageSource;
const react_1 = require("react");
const children_1 = require("../../utils/children");
const elements_1 = require("../common/elements");
function convertIconColorPropToObject(iconColor) {
if (iconColor) {
if (typeof iconColor === 'object' && ('default' in iconColor || 'selected' in iconColor)) {
return iconColor;
}
return {
default: iconColor,
};
}
return {};
}
function useAwaitedScreensIcon(icon) {
const src = icon && typeof icon === 'object' && 'src' in icon ? icon.src : undefined;
const [awaitedIcon, setAwaitedIcon] = (0, react_1.useState)(undefined);
(0, react_1.useEffect)(() => {
const loadIcon = async () => {
if (src && src instanceof Promise) {
const awaitedSrc = await src;
if (awaitedSrc) {
const currentAwaitedIcon = { src: awaitedSrc };
setAwaitedIcon(currentAwaitedIcon);
}
}
};
loadIcon();
// Checking `src` rather then icon here, to avoid unnecessary re-renders
// The icon object can be recreated, while src should stay the same
// In this case as we control `VectorIcon`, it will only change if `family` or `name` props change
// So we should be safe with promise resolving
}, [src]);
return (0, react_1.useMemo)(() => (isAwaitedIcon(icon) ? icon : awaitedIcon), [awaitedIcon, icon]);
}
function isAwaitedIcon(icon) {
return !icon || !('src' in icon && icon.src instanceof Promise);
}
function convertOptionsIconToRNScreensPropsIcon(icon, iconColor) {
if (!icon) {
return undefined;
}
return {
ios: convertOptionsIconToIOSPropsIcon(icon, iconColor),
android: convertOptionsIconToAndroidPropsIcon(icon),
};
}
function convertOptionsIconToIOSPropsIcon(icon, iconColor) {
if (icon && 'sf' in icon && icon.sf) {
return {
type: 'sfSymbol',
name: icon.sf,
};
}
if (icon && (('xcasset' in icon && icon.xcasset) || ('src' in icon && icon.src))) {
const imageSource = 'xcasset' in icon && icon.xcasset
? { uri: icon.xcasset }
: icon.src;
const renderingMode = 'renderingMode' in icon ? icon.renderingMode : undefined;
const effectiveRenderingMode = renderingMode ?? (iconColor !== undefined ? 'template' : 'original');
if (effectiveRenderingMode === 'original') {
return { type: 'imageSource', imageSource };
}
return { type: 'templateSource', templateSource: imageSource };
}
return undefined;
}
function convertOptionsIconToAndroidPropsIcon(icon) {
if (icon && 'drawable' in icon && icon.drawable) {
return {
type: 'drawableResource',
name: icon.drawable,
};
}
if (icon && 'src' in icon && icon.src) {
return { type: 'imageSource', imageSource: icon.src };
}
return undefined;
}
function convertComponentSrcToImageSource(src) {
if ((0, children_1.isChildOfType)(src, elements_1.NativeTabsTriggerVectorIcon)) {
const props = src.props;
return { src: props.family.getImageSource(props.name, 24, 'white') };
}
else if ((0, children_1.isChildOfType)(src, elements_1.NativeTabsTriggerPromiseIcon)) {
return { src: src.props.loader() };
}
else {
console.warn('Only VectorIcon is supported as a React element in Icon.src');
}
return undefined;
}
//# sourceMappingURL=icon.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
export { convertLabelStylePropToObject } from './label';
export { convertIconColorPropToObject } from './icon';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,QAAQ,CAAC"}

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertIconColorPropToObject = exports.convertLabelStylePropToObject = void 0;
var label_1 = require("./label");
Object.defineProperty(exports, "convertLabelStylePropToObject", { enumerable: true, get: function () { return label_1.convertLabelStylePropToObject; } });
var icon_1 = require("./icon");
Object.defineProperty(exports, "convertIconColorPropToObject", { enumerable: true, get: function () { return icon_1.convertIconColorPropToObject; } });
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/native-tabs/utils/index.ts"],"names":[],"mappings":";;;AAAA,iCAAwD;AAA/C,sHAAA,6BAA6B,OAAA;AACtC,+BAAsD;AAA7C,oHAAA,4BAA4B,OAAA","sourcesContent":["export { convertLabelStylePropToObject } from './label';\nexport { convertIconColorPropToObject } from './icon';\n"]}

View File

@@ -0,0 +1,6 @@
import type { NativeTabsLabelStyle, NativeTabsProps } from '../types';
export declare function convertLabelStylePropToObject(labelStyle: NativeTabsProps['labelStyle']): {
default?: NativeTabsLabelStyle;
selected?: NativeTabsLabelStyle;
};
//# sourceMappingURL=label.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/utils/label.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEtE,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,eAAe,CAAC,YAAY,CAAC,GAAG;IACxF,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC,CAaA"}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertLabelStylePropToObject = convertLabelStylePropToObject;
const react_native_1 = require("react-native");
function convertLabelStylePropToObject(labelStyle) {
if (labelStyle) {
if (typeof labelStyle === 'object' && ('default' in labelStyle || 'selected' in labelStyle)) {
return {
default: labelStyle.default ? react_native_1.StyleSheet.flatten(labelStyle.default) : undefined,
selected: labelStyle.selected ? react_native_1.StyleSheet.flatten(labelStyle.selected) : undefined,
};
}
return {
default: react_native_1.StyleSheet.flatten(labelStyle),
};
}
return {};
}
//# sourceMappingURL=label.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"label.js","sourceRoot":"","sources":["../../../src/native-tabs/utils/label.ts"],"names":[],"mappings":";;AAIA,sEAgBC;AApBD,+CAA0D;AAI1D,SAAgB,6BAA6B,CAAC,UAAyC;IAIrF,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,SAAS,IAAI,UAAU,IAAI,UAAU,IAAI,UAAU,CAAC,EAAE,CAAC;YAC5F,OAAO;gBACL,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAU,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;gBAChF,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,yBAAU,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;aACpF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,yBAAU,CAAC,OAAO,CAAC,UAA6C,CAAC;SAC3E,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC","sourcesContent":["import { StyleSheet, type StyleProp } from 'react-native';\n\nimport type { NativeTabsLabelStyle, NativeTabsProps } from '../types';\n\nexport function convertLabelStylePropToObject(labelStyle: NativeTabsProps['labelStyle']): {\n default?: NativeTabsLabelStyle;\n selected?: NativeTabsLabelStyle;\n} {\n if (labelStyle) {\n if (typeof labelStyle === 'object' && ('default' in labelStyle || 'selected' in labelStyle)) {\n return {\n default: labelStyle.default ? StyleSheet.flatten(labelStyle.default) : undefined,\n selected: labelStyle.selected ? StyleSheet.flatten(labelStyle.selected) : undefined,\n };\n }\n return {\n default: StyleSheet.flatten(labelStyle as StyleProp<NativeTabsLabelStyle>),\n };\n }\n return {};\n}\n"]}

View File

@@ -0,0 +1,4 @@
import { convertComponentSrcToImageSource } from './icon';
import { type MaterialIcon } from '../common/elements';
export declare function convertMaterialIconNameToImageSource(name: MaterialIcon['md']): ReturnType<typeof convertComponentSrcToImageSource>;
//# sourceMappingURL=materialIconConverter.android.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"materialIconConverter.android.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/utils/materialIconConverter.android.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gCAAgC,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErF,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,GACvB,UAAU,CAAC,OAAO,gCAAgC,CAAC,CAMrD"}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertMaterialIconNameToImageSource = convertMaterialIconNameToImageSource;
const expo_symbols_1 = require("expo-symbols");
const icon_1 = require("./icon");
const elements_1 = require("../common/elements");
function convertMaterialIconNameToImageSource(name) {
return (0, icon_1.convertComponentSrcToImageSource)(<elements_1.NativeTabsTriggerPromiseIcon loader={() => (0, expo_symbols_1.unstable_getMaterialSymbolSourceAsync)(name, 24, 'white')}/>);
}
//# sourceMappingURL=materialIconConverter.android.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"materialIconConverter.android.js","sourceRoot":"","sources":["../../../src/native-tabs/utils/materialIconConverter.android.tsx"],"names":[],"mappings":";;AAKA,oFAQC;AAbD,+CAAqE;AAErE,iCAA0D;AAC1D,iDAAqF;AAErF,SAAgB,oCAAoC,CAClD,IAAwB;IAExB,OAAO,IAAA,uCAAgC,EACrC,CAAC,uCAA4B,CAC3B,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,IAAA,oDAAqC,EAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,EACvE,CACH,CAAC;AACJ,CAAC","sourcesContent":["import { unstable_getMaterialSymbolSourceAsync } from 'expo-symbols';\n\nimport { convertComponentSrcToImageSource } from './icon';\nimport { NativeTabsTriggerPromiseIcon, type MaterialIcon } from '../common/elements';\n\nexport function convertMaterialIconNameToImageSource(\n name: MaterialIcon['md']\n): ReturnType<typeof convertComponentSrcToImageSource> {\n return convertComponentSrcToImageSource(\n <NativeTabsTriggerPromiseIcon\n loader={() => unstable_getMaterialSymbolSourceAsync(name, 24, 'white')}\n />\n );\n}\n"]}

View File

@@ -0,0 +1,4 @@
import type { convertComponentSrcToImageSource } from './icon';
import type { MaterialIcon } from '../common/elements';
export declare function convertMaterialIconNameToImageSource(name: MaterialIcon['md']): ReturnType<typeof convertComponentSrcToImageSource>;
//# sourceMappingURL=materialIconConverter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"materialIconConverter.d.ts","sourceRoot":"","sources":["../../../src/native-tabs/utils/materialIconConverter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,QAAQ,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,GACvB,UAAU,CAAC,OAAO,gCAAgC,CAAC,CAKrD"}

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertMaterialIconNameToImageSource = convertMaterialIconNameToImageSource;
function convertMaterialIconNameToImageSource(name) {
console.warn('Using convertMaterialIconNameToImageSource on unsupported platform. This is most likely an internal expo router bug.');
return undefined;
}
//# sourceMappingURL=materialIconConverter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"materialIconConverter.js","sourceRoot":"","sources":["../../../src/native-tabs/utils/materialIconConverter.tsx"],"names":[],"mappings":";;AAGA,oFAOC;AAPD,SAAgB,oCAAoC,CAClD,IAAwB;IAExB,OAAO,CAAC,IAAI,CACV,sHAAsH,CACvH,CAAC;IACF,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import type { convertComponentSrcToImageSource } from './icon';\nimport type { MaterialIcon } from '../common/elements';\n\nexport function convertMaterialIconNameToImageSource(\n name: MaterialIcon['md']\n): ReturnType<typeof convertComponentSrcToImageSource> {\n console.warn(\n 'Using convertMaterialIconNameToImageSource on unsupported platform. This is most likely an internal expo router bug.'\n );\n return undefined;\n}\n"]}