@react-navigation/core
Version:
Core utilities for building navigators
192 lines (190 loc) • 6.58 kB
JavaScript
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
;