UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

162 lines (161 loc) 5.71 kB
import { StackRouter, useNavigationBuilder } from "@react-navigation/native"; import * as React from "react"; import { SafeAreaView } from "react-native-safe-area-context"; import { useFilterScreenChildren } from "../layouts/withLayoutContext"; import { useContextKey } from "../router/Route"; import { registerProtectedRoutes, unregisterProtectedRoutes } from "../router/router"; import { useSortedScreens, getQualifiedRouteComponent } from "../router/useScreens"; import { Screen } from "./Screen"; import { registerClearSlotStates, registerSetSlotState } from "../router/interceptRoutes"; import { Fragment, jsx } from "react/jsx-runtime"; const SLOT_STATIC_KEY = "one-slot-static-key", globalSlotState = /* @__PURE__ */ new Map(), slotStateListeners = /* @__PURE__ */ new Set(); function getSlotState(slotName) { return globalSlotState.get(slotName); } function setSlotState(slotName, state) { state === null ? globalSlotState.delete(slotName) : globalSlotState.set(slotName, state), slotStateListeners.forEach((listener) => listener()); } function clearAllSlotStates() { globalSlotState.clear(), slotStateListeners.forEach((listener) => listener()); } registerClearSlotStates(clearAllSlotStates); registerSetSlotState(setSlotState); function useSlotStateSubscription() { const [, forceUpdate] = React.useReducer((x) => x + 1, 0); React.useEffect(() => (slotStateListeners.add(forceUpdate), () => { slotStateListeners.delete(forceUpdate); }), []); } const NavigatorContext = React.createContext(null); process.env.NODE_ENV !== "production" && (NavigatorContext.displayName = "NavigatorContext"); function Navigator({ initialRouteName, screenOptions, children, router }) { const contextKey = useContextKey(), { screens, children: otherSlot, protectedScreens } = useFilterScreenChildren(children, { isCustomNavigator: !0, contextKey }); registerProtectedRoutes(contextKey, protectedScreens), React.useEffect(() => (registerProtectedRoutes(contextKey, protectedScreens), () => { unregisterProtectedRoutes(contextKey); }), [contextKey, protectedScreens]); const sorted = useSortedScreens(screens ?? [], { protectedScreens }); return sorted.length ? /* @__PURE__ */ jsx( QualifiedNavigator, { initialRouteName, screenOptions, screens: sorted, contextKey, router, children: otherSlot } ) : (console.warn(`Navigator at "${contextKey}" has no children.`), null); } function QualifiedNavigator({ initialRouteName, screenOptions, children, screens, contextKey, router = StackRouter }) { const { state, navigation, descriptors, NavigationContent } = useNavigationBuilder( router, { // Used for getting the parent with navigation.getParent('/normalized/path') id: contextKey, children: screens, screenOptions, initialRouteName } ), descriptorsRef = React.useRef(descriptors); descriptorsRef.current = descriptors; const value = React.useMemo(() => ({ contextKey, state, navigation, descriptorsRef, router }), [contextKey, state, navigation, router]); return /* @__PURE__ */ jsx(NavigatorContext.Provider, { value, children: /* @__PURE__ */ jsx(NavigationContent, { children }) }); } function useNavigatorContext() { const context = React.useContext(NavigatorContext); if (!context) throw new Error("useNavigatorContext must be used within a <Navigator />"); return context; } function useSlot() { const context = useNavigatorContext(), { state, descriptorsRef } = context, current = state.routes.find((route, i) => state.index === i); if (!current) return null; const renderedElement = descriptorsRef.current[current.key]?.render() ?? null; return renderedElement !== null ? React.cloneElement(renderedElement, { key: SLOT_STATIC_KEY }) : renderedElement; } const Slot = React.memo(function(props) { const contextKey = useContextKey(); return React.useContext(NavigatorContext)?.contextKey !== contextKey ? /* @__PURE__ */ jsx(Navigator, { ...props, children: /* @__PURE__ */ jsx(QualifiedSlot, {}) }) : /* @__PURE__ */ jsx(QualifiedSlot, {}); }); function QualifiedSlot() { return useSlot(); } function DefaultNavigator() { return /* @__PURE__ */ jsx(SafeAreaView, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(Navigator, { children: /* @__PURE__ */ jsx(QualifiedSlot, {}) }) }); } Navigator.Slot = Slot; Navigator.useContext = useNavigatorContext; Navigator.Screen = Screen; function getScopedSlotKey(slotName, layoutContextKey) { return layoutContextKey ? `${layoutContextKey}:${slotName}` : slotName; } function useNamedSlot(slotName, layoutContextKey) { useSlotStateSubscription(); const scopedKey = getScopedSlotKey(slotName, layoutContextKey), slotState = getSlotState(scopedKey); if (!slotState?.activeRouteKey || !slotState.isIntercepted) return null; if (slotState.activeRouteNode) { const Component = getQualifiedRouteComponent(slotState.activeRouteNode); return /* @__PURE__ */ jsx( Component, { route: { params: slotState.params || {} } }, slotState.activeRouteKey ); } return null; } function NamedSlot({ name, layoutContextKey, children }) { const slotContent = useNamedSlot(name, layoutContextKey); return slotContent ? /* @__PURE__ */ jsx(Fragment, { children: slotContent }) : /* @__PURE__ */ jsx(Fragment, { children }); } export { DefaultNavigator, NamedSlot, Navigator, NavigatorContext, QualifiedSlot, Slot, clearAllSlotStates, getScopedSlotKey, getSlotState, setSlotState, useNamedSlot, useNavigatorContext, useSlot }; //# sourceMappingURL=Navigator.js.map