UNPKG

@react-navigation/core

Version:

Core utilities for building navigators

192 lines (190 loc) 6.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useDescriptors = useDescriptors; var React = _interopRequireWildcard(require("react")); var _NavigationBuilderContext = require("./NavigationBuilderContext.js"); var _NavigationContext = require("./NavigationContext.js"); var _NavigationRouteContext = require("./NavigationRouteContext.js"); var _SceneView = require("./SceneView.js"); var _ThemeContext = require("./theming/ThemeContext.js"); var _useNavigationCache = require("./useNavigationCache.js"); var _useRouteCache = require("./useRouteCache.js"); var _jsxRuntime = require("react/jsx-runtime"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /** * Hook to create descriptor objects for the child routes. * * A descriptor object provides 3 things: * - Helper method to render a screen * - Options specified by the screen for the navigator * - Navigation object intended for the route */ function useDescriptors({ state, screens, navigation, screenOptions, screenLayout, onAction, getState, setState, addListener, addKeyedListener, onRouteFocus, router, emitter }) { const theme = React.useContext(_ThemeContext.ThemeContext); const [options, setOptions] = React.useState({}); const { onDispatchAction, onOptionsChange, scheduleUpdate, flushUpdates, stackRef } = React.useContext(_NavigationBuilderContext.NavigationBuilderContext); const context = React.useMemo(() => ({ navigation, onAction, addListener, addKeyedListener, onRouteFocus, onDispatchAction, onOptionsChange, scheduleUpdate, flushUpdates, stackRef }), [navigation, onAction, addListener, addKeyedListener, onRouteFocus, onDispatchAction, onOptionsChange, scheduleUpdate, flushUpdates, stackRef]); const { base, navigations } = (0, _useNavigationCache.useNavigationCache)({ state, getState, navigation, setOptions, router, emitter }); const routes = (0, _useRouteCache.useRouteCache)(state.routes); const getOptions = (route, navigation, overrides) => { const config = screens[route.name]; const screen = config.props; const optionsList = [ // The default `screenOptions` passed to the navigator screenOptions, // The `screenOptions` props passed to `Group` elements ...(config.options ? config.options.filter(Boolean) : []), // The `options` prop passed to `Screen` elements, screen.options, // The options set via `navigation.setOptions` overrides]; return optionsList.reduce((acc, curr) => Object.assign(acc, // @ts-expect-error: we check for function but TS still complains typeof curr !== 'function' ? curr : curr({ route, navigation, theme })), {}); }; const render = (route, navigation, customOptions, routeState) => { const config = screens[route.name]; const screen = config.props; const clearOptions = () => setOptions(o => { if (route.key in o) { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { [route.key]: _, ...rest } = o; return rest; } return o; }); const layout = // The `layout` prop passed to `Screen` elements, screen.layout ?? // The `screenLayout` props passed to `Group` elements config.layout ?? // The default `screenLayout` passed to the navigator screenLayout; let element = /*#__PURE__*/(0, _jsxRuntime.jsx)(_SceneView.SceneView, { navigation: navigation, route: route, screen: screen, routeState: routeState, getState: getState, setState: setState, options: customOptions, clearOptions: clearOptions }); if (layout != null) { element = layout({ route, navigation, // @ts-expect-error: in practice `theme` will be defined theme, children: element }); } return /*#__PURE__*/(0, _jsxRuntime.jsx)(_NavigationBuilderContext.NavigationBuilderContext.Provider, { value: context, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_NavigationContext.NavigationContext.Provider, { value: navigation, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_NavigationRouteContext.NavigationRouteContext.Provider, { value: route, children: element }) }) }, route.key); }; const descriptors = routes.reduce((acc, route, i) => { const navigation = navigations[route.key]; const customOptions = getOptions(route, navigation, options[route.key]); const element = render(route, navigation, customOptions, state.routes[i].state); acc[route.key] = { route, // @ts-expect-error: it's missing action helpers, fix later navigation, render() { return element; }, options: customOptions }; return acc; }, {}); /** * Create a descriptor object for a route. * * @param route Route object for which the descriptor should be created * @param placeholder Whether the descriptor should be a placeholder, e.g. for a route not yet in the state * @returns Descriptor object */ const describe = (route, placeholder) => { if (!placeholder) { if (!(route.key in descriptors)) { throw new Error(`Couldn't find a route with the key ${route.key}.`); } return descriptors[route.key]; } const navigation = base; const customOptions = getOptions(route, navigation, {}); const element = render(route, navigation, customOptions, undefined); return { route, navigation, render() { return element; }, options: customOptions }; }; return { describe, descriptors }; } //# sourceMappingURL=useDescriptors.js.map