{"version":3,"file":"router.mjs","names":[],"sources":["../../src/router/router.ts","../../src/router/react.tsx"],"sourcesContent":["import type { ClerkHostRouter, RoutingMode } from '../types';\nimport { isAbsoluteUrl, withLeadingSlash, withoutTrailingSlash } from '../url';\n\nexport const PRESERVED_QUERYSTRING_PARAMS = ['after_sign_in_url', 'after_sign_up_url', 'redirect_url'];\n\n/**\n * Internal Clerk router, used by Clerk components to interact with the host's router.\n */\nexport type ClerkRouter = {\n makeDestinationUrlWithPreservedQueryParameters: (path: string) => string;\n /**\n * The basePath the router is currently mounted on.\n */\n basePath: string;\n /**\n * Creates a child router instance scoped to the provided base path.\n */\n child: (childBasePath: string) => ClerkRouter;\n /**\n * Matches the provided path against the router's current path. If index is provided, matches against the root route of the router.\n */\n match: (path?: string, index?: boolean) => boolean;\n\n /**\n * Mode of the router instance, path-based or virtual\n */\n readonly mode: RoutingMode;\n\n /**\n * Name of the router instance\n */\n readonly name: string;\n\n /**\n * Navigates to the provided path via a history push\n */\n push: ClerkHostRouter['push'];\n /**\n * Navigates to the provided path via a history replace\n */\n replace: ClerkHostRouter['replace'];\n /**\n * If supported by the host router, navigates to the provided path without triggering a full navigation\n */\n shallowPush: ClerkHostRouter['shallowPush'];\n /**\n * Returns the current pathname (including the base path)\n */\n pathname: ClerkHostRouter['pathname'];\n /**\n * Returns the current search params\n */\n searchParams: ClerkHostRouter['searchParams'];\n};\n\n/**\n * Ensures the provided path has a leading slash and no trailing slash\n */\nfunction normalizePath(path: string) {\n return withoutTrailingSlash(withLeadingSlash(path));\n}\n\n/**\n * Factory function to create an instance of ClerkRouter with the provided host router.\n *\n * @param router - host router instance to be used by the router\n * @param basePath - base path of the router, navigation and matching will be scoped to this path\n * @returns A ClerkRouter instance\n */\nexport function createClerkRouter(router: ClerkHostRouter, basePath: string = '/'): ClerkRouter {\n const normalizedBasePath = normalizePath(basePath);\n\n /**\n * Certain query parameters need to be preserved when navigating internally. These query parameters are ultimately used by Clerk to dictate behavior, so we keep them around.\n */\n function makeDestinationUrlWithPreservedQueryParameters(path: string) {\n // If the provided path is an absolute URL, return it unmodified.\n if (isAbsoluteUrl(path)) {\n return path;\n }\n\n const destinationUrl = new URL(path, window.location.origin);\n const currentSearchParams = router.searchParams();\n\n PRESERVED_QUERYSTRING_PARAMS.forEach(key => {\n const maybeValue = currentSearchParams.get(key);\n if (maybeValue) {\n destinationUrl.searchParams.set(key, maybeValue);\n }\n });\n\n return `${destinationUrl.pathname}${destinationUrl.search}`;\n }\n\n /**\n *\n */\n function match(path?: string, index?: boolean) {\n const pathToMatch = path ?? (index && '/');\n\n if (!pathToMatch) {\n throw new Error('[clerk] router.match() requires either a path to match, or the index flag must be set to true.');\n }\n\n const normalizedPath = normalizePath(pathToMatch);\n\n return normalizePath(`${normalizedBasePath}${normalizedPath}`) === normalizePath(router.pathname());\n }\n\n /**\n *\n */\n function child(childBasePath: string) {\n return createClerkRouter(router, `${normalizedBasePath}${normalizePath(childBasePath)}`);\n }\n\n /**\n *\n */\n function push(path: string) {\n const destinationUrl = makeDestinationUrlWithPreservedQueryParameters(path);\n return router.push(destinationUrl);\n }\n\n /**\n *\n */\n function replace(path: string) {\n const destinationUrl = makeDestinationUrlWithPreservedQueryParameters(path);\n return router.replace(destinationUrl);\n }\n\n /**\n *\n */\n function shallowPush(path: string) {\n const destinationUrl = makeDestinationUrlWithPreservedQueryParameters(path);\n return router.shallowPush(destinationUrl);\n }\n\n /**\n *\n */\n function pathname() {\n return router.pathname();\n }\n\n /**\n *\n */\n function searchParams() {\n return router.searchParams();\n }\n\n return {\n makeDestinationUrlWithPreservedQueryParameters,\n child,\n match,\n mode: router.mode,\n name: router.name,\n push,\n replace,\n shallowPush,\n pathname,\n searchParams,\n basePath: normalizedBasePath,\n };\n}\n\nexport type { ClerkHostRouter, RoutingMode };\n","/**\n * React-specific binding's for interacting with Clerk's router interface.\n */\nimport React, { createContext, useContext } from 'react';\n\nimport type { ClerkHostRouter, ClerkRouter } from './router';\nimport { createClerkRouter } from './router';\n\nexport const ClerkHostRouterContext = createContext(null);\nexport const ClerkRouterContext = createContext(null);\n\n/**\n *\n */\nexport function useClerkHostRouter() {\n const ctx = useContext(ClerkHostRouterContext);\n\n if (!ctx) {\n throw new Error(\n 'clerk: Unable to locate ClerkHostRouter, make sure this is rendered within ``.',\n );\n }\n\n return ctx;\n}\n\n/**\n *\n */\nexport function useClerkRouter() {\n const ctx = useContext(ClerkRouterContext);\n\n if (!ctx) {\n throw new Error('clerk: Unable to locate ClerkRouter, make sure this is rendered within ``.');\n }\n\n return ctx;\n}\n\n/**\n * Construct a Clerk Router using the provided host router. The router instance is accessible using `useClerkRouter()`.\n */\nexport function Router({\n basePath,\n children,\n router,\n}: {\n children: React.ReactNode;\n basePath?: string;\n router?: ClerkHostRouter;\n}) {\n const hostRouter = useClerkHostRouter();\n const clerkRouter = createClerkRouter(router ?? hostRouter, basePath);\n\n return {children};\n}\n\ntype RouteProps = { path?: string; index?: boolean };\n\n/**\n * Used to conditionally render its children based on whether or not the current path matches the provided path.\n */\nexport function Route({ path, children, index }: RouteProps & { children: React.ReactNode }) {\n const parentRouter = useClerkRouter();\n\n if (!path && !index) {\n return children;\n }\n\n if (!parentRouter?.match(path, index)) {\n return null;\n }\n\n return children;\n}\n"],"mappings":";;;;;;AAGA,MAAa,+BAA+B;CAAC;CAAqB;CAAqB;CAAe;;;;AAuDtG,SAAS,cAAc,MAAc;AACnC,QAAO,qBAAqB,iBAAiB,KAAK,CAAC;;;;;;;;;AAUrD,SAAgB,kBAAkB,QAAyB,WAAmB,KAAkB;CAC9F,MAAM,qBAAqB,cAAc,SAAS;;;;CAKlD,SAAS,+CAA+C,MAAc;AAEpE,MAAI,cAAc,KAAK,CACrB,QAAO;EAGT,MAAM,iBAAiB,IAAI,IAAI,MAAM,OAAO,SAAS,OAAO;EAC5D,MAAM,sBAAsB,OAAO,cAAc;AAEjD,+BAA6B,SAAQ,QAAO;GAC1C,MAAM,aAAa,oBAAoB,IAAI,IAAI;AAC/C,OAAI,WACF,gBAAe,aAAa,IAAI,KAAK,WAAW;IAElD;AAEF,SAAO,GAAG,eAAe,WAAW,eAAe;;;;;CAMrD,SAAS,MAAM,MAAe,OAAiB;EAC7C,MAAM,cAAc,SAAS,SAAS;AAEtC,MAAI,CAAC,YACH,OAAM,IAAI,MAAM,iGAAiG;AAKnH,SAAO,cAAc,GAAG,qBAFD,cAAc,YAAY,GAEa,KAAK,cAAc,OAAO,UAAU,CAAC;;;;;CAMrG,SAAS,MAAM,eAAuB;AACpC,SAAO,kBAAkB,QAAQ,GAAG,qBAAqB,cAAc,cAAc,GAAG;;;;;CAM1F,SAAS,KAAK,MAAc;EAC1B,MAAM,iBAAiB,+CAA+C,KAAK;AAC3E,SAAO,OAAO,KAAK,eAAe;;;;;CAMpC,SAAS,QAAQ,MAAc;EAC7B,MAAM,iBAAiB,+CAA+C,KAAK;AAC3E,SAAO,OAAO,QAAQ,eAAe;;;;;CAMvC,SAAS,YAAY,MAAc;EACjC,MAAM,iBAAiB,+CAA+C,KAAK;AAC3E,SAAO,OAAO,YAAY,eAAe;;;;;CAM3C,SAAS,WAAW;AAClB,SAAO,OAAO,UAAU;;;;;CAM1B,SAAS,eAAe;AACtB,SAAO,OAAO,cAAc;;AAG9B,QAAO;EACL;EACA;EACA;EACA,MAAM,OAAO;EACb,MAAM,OAAO;EACb;EACA;EACA;EACA;EACA;EACA,UAAU;EACX;;;;;;;;AC9JH,MAAa,yBAAyB,cAAsC,KAAK;AACjF,MAAa,qBAAqB,cAAkC,KAAK;;;;AAKzE,SAAgB,qBAAqB;CACnC,MAAM,MAAM,WAAW,uBAAuB;AAE9C,KAAI,CAAC,IACH,OAAM,IAAI,MACR,kHACD;AAGH,QAAO;;;;;AAMT,SAAgB,iBAAiB;CAC/B,MAAM,MAAM,WAAW,mBAAmB;AAE1C,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,qFAAqF;AAGvG,QAAO;;;;;AAMT,SAAgB,OAAO,EACrB,UACA,UACA,UAKC;CACD,MAAM,aAAa,oBAAoB;CACvC,MAAM,cAAc,kBAAkB,UAAU,YAAY,SAAS;AAErE,QAAO,oCAAC,mBAAmB,YAAS,OAAO,eAAc,SAAuC;;;;;AAQlG,SAAgB,MAAM,EAAE,MAAM,UAAU,SAAqD;CAC3F,MAAM,eAAe,gBAAgB;AAErC,KAAI,CAAC,QAAQ,CAAC,MACZ,QAAO;AAGT,KAAI,CAAC,cAAc,MAAM,MAAM,MAAM,CACnC,QAAO;AAGT,QAAO"}