UNPKG

one

Version:

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

184 lines (183 loc) 6.46 kB
import { resolveHref } from "../link/href.mjs"; import { sortRoutesWithInitial } from "../router/sortRoutes.mjs"; import { createGetIdForRoute, getQualifiedRouteComponent, Screen } from "../router/useScreens.mjs"; import { Slot } from "./Slot.mjs"; import { jsx } from "react/jsx-runtime"; const ViewSlot = Slot; function resolveHrefWithSegments(href, routeInfo, segmentsWithoutGroups) { if (href.startsWith("./") || href.startsWith("../")) { const basePath = "/" + segmentsWithoutGroups.join("/"); const baseDir = basePath.replace(/\/[^/]*$/, "") || "/"; const parts = (baseDir + "/" + href).split("/"); const resolved = []; for (const part of parts) { if (part === "." || part === "") continue; if (part === "..") { resolved.pop(); } else { resolved.push(part); } } return "/" + resolved.join("/"); } return href; } function triggersToScreens(triggers, layoutRouteNode, linking, initialRouteName, parentTriggerMap, routeInfo, contextKey) { const configs = []; for (const trigger of triggers) { if (trigger.name in parentTriggerMap) { const parentTrigger = parentTriggerMap[trigger.name]; throw new Error(`Trigger ${JSON.stringify({ name: trigger.name, href: trigger.href })} has the same name as parent trigger ${JSON.stringify({ name: parentTrigger.name, href: parentTrigger.href })}. Triggers must have unique names.`); } if (trigger.type === "external") { configs.push(trigger); continue; } let resolvedHref = resolveHref(trigger.href); if (resolvedHref.startsWith("../")) { throw new Error("Trigger href cannot link to a parent directory"); } const segmentsWithoutGroups = contextKey.split("/").filter(segment => { return !(segment.startsWith("(") && segment.endsWith(")")); }); resolvedHref = resolveHrefWithSegments(resolvedHref, routeInfo, segmentsWithoutGroups); let state = linking.getStateFromPath?.(resolvedHref, linking.config)?.routes[0]; if (!state) { console.warn(`Unable to find screen for trigger ${JSON.stringify(trigger)}. Does this point to a valid screen?`); continue; } let routeState = state; if (routeState.name === "+not-found") { if (process.env.NODE_ENV !== "production") { console.warn(`Tab trigger '${trigger.name}' has the href '${trigger.href}' which points to a +not-found route.`); } continue; } const targetStateName = layoutRouteNode.route || "__root"; while (state?.state) { if (state.name === targetStateName) break; state = state.state.routes[state.state.index ?? state.state.routes.length - 1]; } routeState = state.state?.routes[state.state.index ?? state.state.routes.length - 1] || state; const routeNode = layoutRouteNode.children.find(child => child.route === routeState?.name); if (!routeNode) { console.warn(`Unable to find routeNode for trigger ${JSON.stringify(trigger)}. This might be a bug in One router`); continue; } const duplicateTrigger = trigger.type === "internal" && configs.find(config => { if (config.type === "external") { return false; } return config.routeNode.route === routeNode.route; }); if (duplicateTrigger) { const duplicateTriggerText = `${JSON.stringify({ name: duplicateTrigger.name, href: duplicateTrigger.href })} and ${JSON.stringify({ name: trigger.name, href: trigger.href })}`; throw new Error(`A navigator cannot contain multiple trigger components that map to the same sub-segment. Consider adding a shared group and assigning a group to each trigger. Conflicting triggers: ${duplicateTriggerText}. Both triggers map to route ${routeNode.route}.`); } configs.push({ ...trigger, href: resolvedHref, routeNode, action: stateToAction(state, layoutRouteNode.route) }); } const sortFn = sortRoutesWithInitial(initialRouteName); const sortedConfigs = configs.sort((a, b) => { if (a.type === "external" && b.type === "external") { return 0; } else if (a.type === "external") { return 1; } else if (b.type === "external") { return -1; } return sortFn(a.routeNode, b.routeNode); }); const children = []; const triggerMap = { ...parentTriggerMap }; for (const [index, config] of sortedConfigs.entries()) { triggerMap[config.name] = { ...config, index }; if (config.type === "internal") { const route = config.routeNode; children.push(/* @__PURE__ */jsx(Screen, { getId: createGetIdForRoute(route), name: route.route, options: args => { const staticOptions = route.generated ? route.loadRoute()?.getNavOptions : null; const staticResult = typeof staticOptions === "function" ? staticOptions(args) : staticOptions; const output = { ...staticResult }; if (route.generated) { output.tabBarButton = () => null; output.drawerItemStyle = { height: 0, display: "none" }; } return output; }, getComponent: () => getQualifiedRouteComponent(route) }, route.route)); } } return { children, triggerMap }; } function stateToAction(state, startAtRoute) { const rootPayload = {}; let payload = rootPayload; startAtRoute = startAtRoute === "" ? "__root" : startAtRoute; let foundStartingPoint = startAtRoute === void 0 || !state?.state; while (state) { if (foundStartingPoint) { if (payload === rootPayload) { payload.name = state.name; } else { payload.screen = state.name; } payload.params = state.params ? { ...state.params } : {}; state = state.state?.routes[state.state?.routes.length - 1]; if (state) { payload.params ??= {}; payload = payload.params; } } else { if (state.name === startAtRoute) { foundStartingPoint = true; } const nextState = state.state?.routes[state.state?.routes.length - 1]; if (nextState) { state = nextState; } } } return { type: "JUMP_TO", payload: rootPayload }; } export { ViewSlot, stateToAction, triggersToScreens }; //# sourceMappingURL=common.mjs.map