UNPKG

expo-router

Version:

Expo Router is a file-based router for React Native and web applications.

266 lines (264 loc) • 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); 0 && (module.exports = { Tabs: null, useTabsWithChildren: null, useTabsWithTriggers: null }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: Object.getOwnPropertyDescriptor(all, name).get }); } _export(exports, { get Tabs () { return Tabs; }, get useTabsWithChildren () { return useTabsWithChildren; }, get useTabsWithTriggers () { return useTabsWithTriggers; } }); 0 && __export(require("./TabContext")) && __export(require("./TabList")) && __export(require("./TabSlot")) && __export(require("./TabTrigger")); function _jsxruntime() { const data = require("react/jsx-runtime"); _jsxruntime = function() { return data; }; return data; } function _react() { const data = require("react"); _react = function() { return data; }; return data; } function _reactnative() { const data = require("react-native"); _reactnative = function() { return data; }; return data; } const _Route = require("../Route"); const _useComponent = require("../fork/useComponent"); const _hooks = require("../hooks"); const _GuardContext = require("../layouts/GuardContext"); const _href = require("../link/href"); const _native = require("../react-navigation/native"); const _routeNode = require("../routeNode"); const _appendMissingPlaceholderTabRoutes = require("../standard-navigation/appendMissingPlaceholderTabRoutes"); const _useNonStackAnchorWarning = require("../standard-navigation/useNonStackAnchorWarning"); const _useReconcileTabHistory = require("../standard-navigation/useReconcileTabHistory"); const _useVisibleTabsWithRedirect = require("../standard-navigation/useVisibleTabsWithRedirect"); const _url = require("../utils/url"); const _Navigator = require("../views/Navigator"); const _TabContext = _export_star(require("./TabContext"), exports); const _TabList = _export_star(require("./TabList"), exports); const _TabRouter = require("./TabRouter"); const _TabSlot = _export_star(require("./TabSlot"), exports); const _TabTrigger = _export_star(require("./TabTrigger"), exports); const _common = require("./common"); function _export_star(from, to) { Object.keys(from).forEach(function(k) { if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) { Object.defineProperty(to, k, { enumerable: true, get: function() { return from[k]; } }); } }); return from; } const emptyGuardedRedirects = new Map(); function Tabs(props) { const { children, asChild, options, activityEnabled, ...rest } = props; const Comp = asChild ? _common.ViewSlot : _reactnative().View; const { NavigationContent } = useTabsWithChildren({ // asChild adds an extra layer, so we need to process the child's children children: asChild && /*#__PURE__*/ (0, _react().isValidElement)(children) && children.props && typeof children.props === 'object' && 'children' in children.props ? children.props.children : children, ...options, activityEnabled: activityEnabled ?? options?.activityEnabled }); return /*#__PURE__*/ (0, _jsxruntime().jsx)(Comp, { style: styles.tabsRoot, ...rest, children: /*#__PURE__*/ (0, _jsxruntime().jsx)(NavigationContent, { children: children }) }); } function useTabsWithChildren(options) { const { children, ...rest } = options; return useTabsWithTriggers({ triggers: parseTriggersFromChildren(children), ...rest }); } function useTabsWithTriggers(options) { const { triggers, ...rest } = options; // Ensure we extend the parent triggers, so we can trigger them as well const parentTriggerMap = (0, _react().use)(_TabContext.TabTriggerMapContext); const parentNavigatorStates = (0, _react().use)(_TabContext.TabNavigatorStatesContext); const routeNode = (0, _Route.useRouteNode)(); const contextKey = (0, _Route.useContextKey)(); const linking = (0, _react().use)(_native.LinkingContext).options; const routeInfo = (0, _hooks.useRouteInfo)(); if (!routeNode || !linking) { throw new Error('No RouteNode. This is likely a bug in expo-router.'); } const initialRouteName = (0, _routeNode.getValidInitialRouteName)(routeNode); const backBehavior = rest.backBehavior ?? (initialRouteName ? 'initialRoute' : undefined); const { children, triggerMap } = (0, _common.useTriggersToScreens)(triggers, routeNode, linking, parentTriggerMap, routeInfo, contextKey); const navigatorContext = (0, _native.useNavigationBuilder)(_TabRouter.ExpoTabRouter, { children, ...rest, triggerMap, id: contextKey, initialRouteName, backBehavior }, { activityDefaultThreshold: 1 }); const { state, describe, descriptors: sparseDescriptors, navigation, NavigationContent: RNNavigationContent } = navigatorContext; (0, _useReconcileTabHistory.useReconcileTabHistory)({ state, navigation }); const descriptors = (0, _react().useMemo)(()=>(0, _appendMissingPlaceholderTabRoutes.appendMissingPlaceholderTabDescriptors)(sparseDescriptors, state, describe), [ describe, sparseDescriptors, state ]); const navigatorStates = (0, _react().useMemo)(()=>({ ...parentNavigatorStates, [contextKey]: state }), [ contextKey, parentNavigatorStates, state ]); const navigatorContextValue = (0, _react().useMemo)(()=>({ ...navigatorContext, descriptors: descriptors, contextKey, router: _TabRouter.ExpoTabRouter }), [ navigatorContext, descriptors, contextKey, _TabRouter.ExpoTabRouter ]); const NavigationContent = (0, _useComponent.useComponent)((children)=>// Headless tabs have no guards, so shadow parent guards whose route names may collide. /*#__PURE__*/ (0, _jsxruntime().jsxs)(_GuardContext.GuardContextProvider, { node: routeNode, guardedRedirects: emptyGuardedRedirects, children: [ /*#__PURE__*/ (0, _jsxruntime().jsx)(TabVisibilityRedirect, { state: state, descriptors: descriptors, backBehavior: backBehavior }), /*#__PURE__*/ (0, _jsxruntime().jsx)(_TabContext.TabTriggerMapContext.Provider, { value: triggerMap, children: /*#__PURE__*/ (0, _jsxruntime().jsx)(_TabContext.TabNavigatorStatesContext.Provider, { value: navigatorStates, children: /*#__PURE__*/ (0, _jsxruntime().jsx)(_Navigator.NavigatorContext.Provider, { value: navigatorContextValue, children: /*#__PURE__*/ (0, _jsxruntime().jsx)(RNNavigationContent, { children: children }) }) }) }) ] })); return { state, describe, descriptors, navigation, NavigationContent }; } function TabVisibilityRedirect({ state, descriptors, backBehavior }) { const stateWithPlaceholders = (0, _react().useMemo)(()=>(0, _appendMissingPlaceholderTabRoutes.appendMissingPlaceholderTabRoutes)(state, descriptors), [ descriptors, state ]); (0, _useNonStackAnchorWarning.useNonStackAnchorWarning)(backBehavior); (0, _useVisibleTabsWithRedirect.useVisibleTabsWithRedirect)({ routes: stateWithPlaceholders.routes, routeNames: stateWithPlaceholders.routeNames, focusedRouteKey: stateWithPlaceholders.routes[stateWithPlaceholders.index]?.key, descriptors }); return null; } function parseTriggersFromChildren(children, screenTriggers = [], isInTabList = false) { _react().Children.forEach(children, (child)=>{ if (!child || !/*#__PURE__*/ (0, _react().isValidElement)(child) || (0, _TabSlot.isTabSlot)(child)) { return; } if (isFragment(child) && typeof child.props.children !== 'function') { return parseTriggersFromChildren(child.props.children, screenTriggers, isInTabList || (0, _TabList.isTabList)(child)); } if ((0, _TabList.isTabList)(child) && typeof child.props.children !== 'function') { let children = child.props.children; // <TabList asChild /> adds an extra layer. We need to parse the child's children if (child.props.asChild && /*#__PURE__*/ (0, _react().isValidElement)(children) && children.props && typeof children.props === 'object' && 'children' in children.props) { children = children.props.children; } return parseTriggersFromChildren(children, screenTriggers, isInTabList || (0, _TabList.isTabList)(child)); } // We should only process TabTriggers within the TabList. All other components will be ignored if (!isInTabList || !(0, _TabTrigger.isTabTrigger)(child)) { return; } const { href, name, activityEnabled } = child.props; if (!href) { if (process.env.NODE_ENV === 'development') { console.warn(`<TabTrigger name={${name}}> does not have a 'href' prop. TabTriggers within a <TabList /> are required to have an href.`); } return; } const resolvedHref = (0, _href.resolveHref)(href); if ((0, _url.shouldLinkExternally)(resolvedHref)) { return screenTriggers.push({ type: 'external', name, href: resolvedHref }); } if (!name) { if (process.env.NODE_ENV === 'development') { console.warn(`<TabTrigger> does not have a 'name' prop. TabTriggers within a <TabList /> are required to have a name.`); } return; } return screenTriggers.push({ type: 'internal', href: resolvedHref, name, activityEnabled }); }); return screenTriggers; } function isFragment(child) { return child.type === _react().Fragment; } const styles = _reactnative().StyleSheet.create({ tabsRoot: { flex: 1 } }); //# sourceMappingURL=Tabs.js.map