@cedarjs/router 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/dist/ActivePageContext.d.ts +15 -0
  4. package/dist/ActivePageContext.d.ts.map +1 -0
  5. package/dist/ActivePageContext.js +17 -0
  6. package/dist/AuthenticatedRoute.d.ts +11 -0
  7. package/dist/AuthenticatedRoute.d.ts.map +1 -0
  8. package/dist/AuthenticatedRoute.js +49 -0
  9. package/dist/PageLoadingContext.d.ts +14 -0
  10. package/dist/PageLoadingContext.d.ts.map +1 -0
  11. package/dist/PageLoadingContext.js +29 -0
  12. package/dist/Route.d.ts +32 -0
  13. package/dist/Route.d.ts.map +1 -0
  14. package/dist/Route.js +7 -0
  15. package/dist/Set.d.ts +58 -0
  16. package/dist/Set.d.ts.map +1 -0
  17. package/dist/Set.js +28 -0
  18. package/dist/a11yUtils.d.ts +14 -0
  19. package/dist/a11yUtils.d.ts.map +1 -0
  20. package/dist/a11yUtils.js +35 -0
  21. package/dist/active-route-loader.d.ts +12 -0
  22. package/dist/active-route-loader.d.ts.map +1 -0
  23. package/dist/active-route-loader.js +82 -0
  24. package/dist/analyzeRoutes.d.ts +44 -0
  25. package/dist/analyzeRoutes.d.ts.map +1 -0
  26. package/dist/analyzeRoutes.js +128 -0
  27. package/dist/cjs/ActivePageContext.d.ts +15 -0
  28. package/dist/cjs/ActivePageContext.d.ts.map +1 -0
  29. package/dist/cjs/ActivePageContext.js +42 -0
  30. package/dist/cjs/AuthenticatedRoute.d.ts +11 -0
  31. package/dist/cjs/AuthenticatedRoute.d.ts.map +1 -0
  32. package/dist/cjs/AuthenticatedRoute.js +83 -0
  33. package/dist/cjs/PageLoadingContext.d.ts +14 -0
  34. package/dist/cjs/PageLoadingContext.d.ts.map +1 -0
  35. package/dist/cjs/PageLoadingContext.js +64 -0
  36. package/dist/cjs/Route.d.ts +32 -0
  37. package/dist/cjs/Route.d.ts.map +1 -0
  38. package/dist/cjs/Route.js +41 -0
  39. package/dist/cjs/Set.d.ts +58 -0
  40. package/dist/cjs/Set.d.ts.map +1 -0
  41. package/dist/cjs/Set.js +67 -0
  42. package/dist/cjs/a11yUtils.d.ts +14 -0
  43. package/dist/cjs/a11yUtils.d.ts.map +1 -0
  44. package/dist/cjs/a11yUtils.js +61 -0
  45. package/dist/cjs/active-route-loader.d.ts +12 -0
  46. package/dist/cjs/active-route-loader.d.ts.map +1 -0
  47. package/dist/cjs/active-route-loader.js +116 -0
  48. package/dist/cjs/analyzeRoutes.d.ts +44 -0
  49. package/dist/cjs/analyzeRoutes.d.ts.map +1 -0
  50. package/dist/cjs/analyzeRoutes.js +143 -0
  51. package/dist/cjs/createNamedContext.d.ts +3 -0
  52. package/dist/cjs/createNamedContext.d.ts.map +1 -0
  53. package/dist/cjs/createNamedContext.js +33 -0
  54. package/dist/cjs/dummyComponent.d.ts +3 -0
  55. package/dist/cjs/dummyComponent.d.ts.map +1 -0
  56. package/dist/cjs/dummyComponent.js +24 -0
  57. package/dist/cjs/history.d.ts +24 -0
  58. package/dist/cjs/history.d.ts.map +1 -0
  59. package/dist/cjs/history.js +146 -0
  60. package/dist/cjs/index.d.ts +35 -0
  61. package/dist/cjs/index.d.ts.map +1 -0
  62. package/dist/cjs/index.js +110 -0
  63. package/dist/cjs/link.d.ts +9 -0
  64. package/dist/cjs/link.d.ts.map +1 -0
  65. package/dist/cjs/link.js +62 -0
  66. package/dist/cjs/location.d.ts +28 -0
  67. package/dist/cjs/location.d.ts.map +1 -0
  68. package/dist/cjs/location.js +110 -0
  69. package/dist/cjs/namedRoutes.d.ts +3 -0
  70. package/dist/cjs/namedRoutes.d.ts.map +1 -0
  71. package/dist/cjs/namedRoutes.js +28 -0
  72. package/dist/cjs/navLink.d.ts +11 -0
  73. package/dist/cjs/navLink.d.ts.map +1 -0
  74. package/dist/cjs/navLink.js +70 -0
  75. package/dist/cjs/package.json +1 -0
  76. package/dist/cjs/page.d.ts +28 -0
  77. package/dist/cjs/page.d.ts.map +1 -0
  78. package/dist/cjs/page.js +42 -0
  79. package/dist/cjs/params.d.ts +13 -0
  80. package/dist/cjs/params.d.ts.map +1 -0
  81. package/dist/cjs/params.js +64 -0
  82. package/dist/cjs/react-util.d.ts +3 -0
  83. package/dist/cjs/react-util.d.ts.map +1 -0
  84. package/dist/cjs/react-util.js +37 -0
  85. package/dist/cjs/redirect.d.ts +12 -0
  86. package/dist/cjs/redirect.d.ts.map +1 -0
  87. package/dist/cjs/redirect.js +35 -0
  88. package/dist/cjs/route-announcement.d.ts +13 -0
  89. package/dist/cjs/route-announcement.d.ts.map +1 -0
  90. package/dist/cjs/route-announcement.js +61 -0
  91. package/dist/cjs/route-focus.d.ts +12 -0
  92. package/dist/cjs/route-focus.d.ts.map +1 -0
  93. package/dist/cjs/route-focus.js +36 -0
  94. package/dist/cjs/route-validators.d.ts +21 -0
  95. package/dist/cjs/route-validators.d.ts.map +1 -0
  96. package/dist/cjs/route-validators.js +71 -0
  97. package/dist/cjs/routeParamsTypes.d.ts +49 -0
  98. package/dist/cjs/routeParamsTypes.d.ts.map +1 -0
  99. package/dist/cjs/routeParamsTypes.js +16 -0
  100. package/dist/cjs/router-context.d.ts +21 -0
  101. package/dist/cjs/router-context.d.ts.map +1 -0
  102. package/dist/cjs/router-context.js +69 -0
  103. package/dist/cjs/router.d.ts +11 -0
  104. package/dist/cjs/router.d.ts.map +1 -0
  105. package/dist/cjs/router.js +207 -0
  106. package/dist/cjs/rsc/ClientRouter.d.ts +4 -0
  107. package/dist/cjs/rsc/ClientRouter.d.ts.map +1 -0
  108. package/dist/cjs/rsc/ClientRouter.js +90 -0
  109. package/dist/cjs/rsc/RscCache.d.ts +23 -0
  110. package/dist/cjs/rsc/RscCache.d.ts.map +1 -0
  111. package/dist/cjs/rsc/RscCache.js +110 -0
  112. package/dist/cjs/rsc/RscRoutes.d.ts +7 -0
  113. package/dist/cjs/rsc/RscRoutes.d.ts.map +1 -0
  114. package/dist/cjs/rsc/RscRoutes.js +124 -0
  115. package/dist/cjs/rsc/ServerRouteLoader.d.ts +12 -0
  116. package/dist/cjs/rsc/ServerRouteLoader.d.ts.map +1 -0
  117. package/dist/cjs/rsc/ServerRouteLoader.js +65 -0
  118. package/dist/cjs/rsc/ServerRouter.d.ts +11 -0
  119. package/dist/cjs/rsc/ServerRouter.d.ts.map +1 -0
  120. package/dist/cjs/rsc/ServerRouter.js +170 -0
  121. package/dist/cjs/rsc/SsrRouter.d.ts +4 -0
  122. package/dist/cjs/rsc/SsrRouter.d.ts.map +1 -0
  123. package/dist/cjs/rsc/SsrRouter.js +56 -0
  124. package/dist/cjs/rsc/clientSsr.d.ts +2 -0
  125. package/dist/cjs/rsc/clientSsr.d.ts.map +1 -0
  126. package/dist/cjs/rsc/clientSsr.js +114 -0
  127. package/dist/cjs/rsc/rscCss.d.ts +2 -0
  128. package/dist/cjs/rsc/rscCss.d.ts.map +1 -0
  129. package/dist/cjs/rsc/rscCss.js +94 -0
  130. package/dist/cjs/rsc/ssrModuleMap.d.ts +14 -0
  131. package/dist/cjs/rsc/ssrModuleMap.d.ts.map +1 -0
  132. package/dist/cjs/rsc/ssrModuleMap.js +49 -0
  133. package/dist/cjs/rsc/utils.d.ts +20 -0
  134. package/dist/cjs/rsc/utils.d.ts.map +1 -0
  135. package/dist/cjs/rsc/utils.js +68 -0
  136. package/dist/cjs/rsc-link.d.ts +6 -0
  137. package/dist/cjs/rsc-link.d.ts.map +1 -0
  138. package/dist/cjs/rsc-link.js +41 -0
  139. package/dist/cjs/skipNav.d.ts +81 -0
  140. package/dist/cjs/skipNav.d.ts.map +1 -0
  141. package/dist/cjs/skipNav.js +69 -0
  142. package/dist/cjs/splash-page.d.ts +12 -0
  143. package/dist/cjs/splash-page.d.ts.map +1 -0
  144. package/dist/cjs/splash-page.js +515 -0
  145. package/dist/cjs/useBlocker.d.ts +11 -0
  146. package/dist/cjs/useBlocker.d.ts.map +1 -0
  147. package/dist/cjs/useBlocker.js +65 -0
  148. package/dist/cjs/useIsMounted.d.ts +2 -0
  149. package/dist/cjs/useIsMounted.d.ts.map +1 -0
  150. package/dist/cjs/useIsMounted.js +37 -0
  151. package/dist/cjs/useMatch.d.ts +43 -0
  152. package/dist/cjs/useMatch.d.ts.map +1 -0
  153. package/dist/cjs/useMatch.js +72 -0
  154. package/dist/cjs/useRouteName.d.ts +3 -0
  155. package/dist/cjs/useRouteName.d.ts.map +1 -0
  156. package/dist/cjs/useRouteName.js +40 -0
  157. package/dist/cjs/useRoutePaths.d.ts +4 -0
  158. package/dist/cjs/useRoutePaths.d.ts.map +1 -0
  159. package/dist/cjs/useRoutePaths.js +50 -0
  160. package/dist/cjs/util.d.ts +121 -0
  161. package/dist/cjs/util.d.ts.map +1 -0
  162. package/dist/cjs/util.js +214 -0
  163. package/dist/createNamedContext.d.ts +3 -0
  164. package/dist/createNamedContext.d.ts.map +1 -0
  165. package/dist/createNamedContext.js +9 -0
  166. package/dist/dummyComponent.d.ts +3 -0
  167. package/dist/dummyComponent.d.ts.map +1 -0
  168. package/dist/dummyComponent.js +4 -0
  169. package/dist/history.d.ts +24 -0
  170. package/dist/history.d.ts.map +1 -0
  171. package/dist/history.js +118 -0
  172. package/dist/index.d.ts +35 -0
  173. package/dist/index.d.ts.map +1 -0
  174. package/dist/index.js +49 -0
  175. package/dist/link.d.ts +9 -0
  176. package/dist/link.d.ts.map +1 -0
  177. package/dist/link.js +28 -0
  178. package/dist/location.d.ts +28 -0
  179. package/dist/location.d.ts.map +1 -0
  180. package/dist/location.js +74 -0
  181. package/dist/namedRoutes.d.ts +3 -0
  182. package/dist/namedRoutes.d.ts.map +1 -0
  183. package/dist/namedRoutes.js +4 -0
  184. package/dist/navLink.d.ts +11 -0
  185. package/dist/navLink.d.ts.map +1 -0
  186. package/dist/navLink.js +36 -0
  187. package/dist/page.d.ts +28 -0
  188. package/dist/page.d.ts.map +1 -0
  189. package/dist/page.js +17 -0
  190. package/dist/params.d.ts +13 -0
  191. package/dist/params.d.ts.map +1 -0
  192. package/dist/params.js +28 -0
  193. package/dist/react-util.d.ts +3 -0
  194. package/dist/react-util.d.ts.map +1 -0
  195. package/dist/react-util.js +13 -0
  196. package/dist/redirect.d.ts +12 -0
  197. package/dist/redirect.d.ts.map +1 -0
  198. package/dist/redirect.js +11 -0
  199. package/dist/route-announcement.d.ts +13 -0
  200. package/dist/route-announcement.d.ts.map +1 -0
  201. package/dist/route-announcement.js +31 -0
  202. package/dist/route-focus.d.ts +12 -0
  203. package/dist/route-focus.d.ts.map +1 -0
  204. package/dist/route-focus.js +6 -0
  205. package/dist/route-validators.d.ts +21 -0
  206. package/dist/route-validators.d.ts.map +1 -0
  207. package/dist/route-validators.js +44 -0
  208. package/dist/routeParamsTypes.d.ts +49 -0
  209. package/dist/routeParamsTypes.d.ts.map +1 -0
  210. package/dist/routeParamsTypes.js +0 -0
  211. package/dist/router-context.d.ts +21 -0
  212. package/dist/router-context.d.ts.map +1 -0
  213. package/dist/router-context.js +34 -0
  214. package/dist/router.d.ts +11 -0
  215. package/dist/router.d.ts.map +1 -0
  216. package/dist/router.js +173 -0
  217. package/dist/rsc/ClientRouter.d.ts +4 -0
  218. package/dist/rsc/ClientRouter.d.ts.map +1 -0
  219. package/dist/rsc/ClientRouter.js +56 -0
  220. package/dist/rsc/RscCache.d.ts +23 -0
  221. package/dist/rsc/RscCache.d.ts.map +1 -0
  222. package/dist/rsc/RscCache.js +86 -0
  223. package/dist/rsc/RscRoutes.d.ts +7 -0
  224. package/dist/rsc/RscRoutes.d.ts.map +1 -0
  225. package/dist/rsc/RscRoutes.js +100 -0
  226. package/dist/rsc/ServerRouteLoader.d.ts +12 -0
  227. package/dist/rsc/ServerRouteLoader.d.ts.map +1 -0
  228. package/dist/rsc/ServerRouteLoader.js +31 -0
  229. package/dist/rsc/ServerRouter.d.ts +11 -0
  230. package/dist/rsc/ServerRouter.d.ts.map +1 -0
  231. package/dist/rsc/ServerRouter.js +136 -0
  232. package/dist/rsc/SsrRouter.d.ts +4 -0
  233. package/dist/rsc/SsrRouter.d.ts.map +1 -0
  234. package/dist/rsc/SsrRouter.js +22 -0
  235. package/dist/rsc/clientSsr.d.ts +2 -0
  236. package/dist/rsc/clientSsr.d.ts.map +1 -0
  237. package/dist/rsc/clientSsr.js +80 -0
  238. package/dist/rsc/rscCss.d.ts +2 -0
  239. package/dist/rsc/rscCss.d.ts.map +1 -0
  240. package/dist/rsc/rscCss.js +60 -0
  241. package/dist/rsc/ssrModuleMap.d.ts +14 -0
  242. package/dist/rsc/ssrModuleMap.d.ts.map +1 -0
  243. package/dist/rsc/ssrModuleMap.js +25 -0
  244. package/dist/rsc/utils.d.ts +20 -0
  245. package/dist/rsc/utils.d.ts.map +1 -0
  246. package/dist/rsc/utils.js +31 -0
  247. package/dist/rsc-link.d.ts +6 -0
  248. package/dist/rsc-link.d.ts.map +1 -0
  249. package/dist/rsc-link.js +7 -0
  250. package/dist/skipNav.d.ts +81 -0
  251. package/dist/skipNav.d.ts.map +1 -0
  252. package/dist/skipNav.js +34 -0
  253. package/dist/splash-page.d.ts +12 -0
  254. package/dist/splash-page.d.ts.map +1 -0
  255. package/dist/splash-page.js +481 -0
  256. package/dist/useBlocker.d.ts +11 -0
  257. package/dist/useBlocker.d.ts.map +1 -0
  258. package/dist/useBlocker.js +41 -0
  259. package/dist/useIsMounted.d.ts +2 -0
  260. package/dist/useIsMounted.d.ts.map +1 -0
  261. package/dist/useIsMounted.js +13 -0
  262. package/dist/useMatch.d.ts +43 -0
  263. package/dist/useMatch.d.ts.map +1 -0
  264. package/dist/useMatch.js +48 -0
  265. package/dist/useRouteName.d.ts +3 -0
  266. package/dist/useRouteName.d.ts.map +1 -0
  267. package/dist/useRouteName.js +16 -0
  268. package/dist/useRoutePaths.d.ts +4 -0
  269. package/dist/useRoutePaths.d.ts.map +1 -0
  270. package/dist/useRoutePaths.js +25 -0
  271. package/dist/util.d.ts +121 -0
  272. package/dist/util.d.ts.map +1 -0
  273. package/dist/util.js +183 -0
  274. package/package.json +127 -0
  275. package/skip-nav.css +31 -0
@@ -0,0 +1,41 @@
1
+ import { useEffect, useCallback, useState, useId } from "react";
2
+ import { block, unblock } from "./history.js";
3
+ function useBlocker({ when }) {
4
+ const [blockerState, setBlockerState] = useState("IDLE");
5
+ const [pendingNavigation, setPendingNavigation] = useState(null);
6
+ const blockerId = useId();
7
+ const blocker = useCallback(
8
+ ({ retry }) => {
9
+ if (when) {
10
+ setBlockerState("BLOCKED");
11
+ setPendingNavigation(() => retry);
12
+ } else {
13
+ retry();
14
+ }
15
+ },
16
+ [when]
17
+ );
18
+ useEffect(() => {
19
+ if (when) {
20
+ block(blockerId, blocker);
21
+ } else {
22
+ unblock(blockerId);
23
+ }
24
+ return () => unblock(blockerId);
25
+ }, [when, blocker, blockerId]);
26
+ const confirm = useCallback(() => {
27
+ setBlockerState("IDLE");
28
+ if (pendingNavigation) {
29
+ pendingNavigation();
30
+ setPendingNavigation(null);
31
+ }
32
+ }, [pendingNavigation]);
33
+ const abort = useCallback(() => {
34
+ setBlockerState("IDLE");
35
+ setPendingNavigation(null);
36
+ }, []);
37
+ return { state: blockerState, confirm, abort };
38
+ }
39
+ export {
40
+ useBlocker
41
+ };
@@ -0,0 +1,2 @@
1
+ export declare const useIsMounted: () => () => boolean;
2
+ //# sourceMappingURL=useIsMounted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsMounted.d.ts","sourceRoot":"","sources":["../src/useIsMounted.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,qBAUxB,CAAA"}
@@ -0,0 +1,13 @@
1
+ import { useRef, useEffect, useCallback } from "react";
2
+ const useIsMounted = () => {
3
+ const isMounted = useRef(true);
4
+ useEffect(() => {
5
+ return () => {
6
+ isMounted.current = false;
7
+ };
8
+ }, []);
9
+ return useCallback(() => isMounted.current, []);
10
+ };
11
+ export {
12
+ useIsMounted
13
+ };
@@ -0,0 +1,43 @@
1
+ import type { FlattenSearchParams } from './util.js';
2
+ type UseMatchOptions = {
3
+ routeParams?: Record<string, any>;
4
+ searchParams?: FlattenSearchParams;
5
+ matchSubPaths?: boolean;
6
+ };
7
+ /**
8
+ * Returns an object of { match: boolean; params: Record<string, unknown>; }
9
+ * If the path matches the current location `match` will be true.
10
+ * Params will be an object of the matched params, if there are any.
11
+ *
12
+ * Provide routeParams options to match specific route param values
13
+ * Provide searchParams options to match the current location.search
14
+ *
15
+ * This is useful for components that need to know "active" state, e.g.
16
+ * <NavLink>.
17
+ *
18
+ * Examples:
19
+ *
20
+ * Match search params key existence
21
+ * const match = useMatch('/about', { searchParams: ['category', 'page'] })
22
+ *
23
+ * Match search params key and value
24
+ * const match = useMatch('/items', { searchParams: [{page: 2}, {category: 'book'}] })
25
+ *
26
+ * Mix match
27
+ * const match = useMatch('/list', { searchParams: [{page: 2}, 'gtm'] })
28
+ *
29
+ * Match sub paths
30
+ * const match = useMatch('/product', { matchSubPaths: true })
31
+ *
32
+ * Match only specific route param values
33
+ * const match = useMatch('/product/{category}/{id}', { routeParams: { category: 'shirts' } })
34
+ */
35
+ export declare const useMatch: (routePath: string, options?: UseMatchOptions) => {
36
+ match: boolean;
37
+ params?: undefined;
38
+ } | {
39
+ match: boolean;
40
+ params: Record<string, unknown>;
41
+ };
42
+ export {};
43
+ //# sourceMappingURL=useMatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMatch.d.ts","sourceRoot":"","sources":["../src/useMatch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAEpD,KAAK,eAAe,GAAG;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACjC,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAClC,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,QAAQ,cAAe,MAAM,YAAY,eAAe;;;;;;CAiDpE,CAAA"}
@@ -0,0 +1,48 @@
1
+ import { useLocation } from "./location.js";
2
+ import { matchPath } from "./util.js";
3
+ const useMatch = (routePath, options) => {
4
+ const location = useLocation();
5
+ if (!location) {
6
+ return { match: false };
7
+ }
8
+ if (options?.searchParams) {
9
+ const locationParams = new URLSearchParams(location.search);
10
+ const hasUnmatched = options.searchParams.some((param) => {
11
+ if (typeof param === "string") {
12
+ return !locationParams.has(param);
13
+ } else {
14
+ return Object.keys(param).some(
15
+ (key) => param[key] != locationParams.get(key)
16
+ );
17
+ }
18
+ });
19
+ if (hasUnmatched) {
20
+ return { match: false };
21
+ }
22
+ }
23
+ const matchInfo = matchPath(routePath, location.pathname, {
24
+ matchSubPaths: options?.matchSubPaths
25
+ });
26
+ if (!matchInfo.match) {
27
+ return { match: false };
28
+ }
29
+ const routeParams = Object.entries(options?.routeParams || {});
30
+ if (routeParams.length > 0) {
31
+ if (!isMatchWithParams(matchInfo) || !matchInfo.params) {
32
+ return { match: false };
33
+ }
34
+ const isParamMatch = routeParams.every(([key, value]) => {
35
+ return matchInfo.params[key] === value;
36
+ });
37
+ if (!isParamMatch) {
38
+ return { match: false };
39
+ }
40
+ }
41
+ return matchInfo;
42
+ };
43
+ function isMatchWithParams(match) {
44
+ return match !== null && typeof match === "object" && "params" in match;
45
+ }
46
+ export {
47
+ useMatch
48
+ };
@@ -0,0 +1,3 @@
1
+ /** Gets the name of the current route (as defined in your Routes file) */
2
+ export declare function useRouteName(): undefined;
3
+ //# sourceMappingURL=useRouteName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRouteName.d.ts","sourceRoot":"","sources":["../src/useRouteName.ts"],"names":[],"mappings":"AAOA,0EAA0E;AAC1E,wBAAgB,YAAY,cAS3B"}
@@ -0,0 +1,16 @@
1
+ import { useRouterState } from "./router-context.js";
2
+ import { routes } from "./index.js";
3
+ function useRouteName() {
4
+ const routerState = useRouterState();
5
+ const routeName = routerState.activeRouteName;
6
+ if (isAvailableRouteName(routeName)) {
7
+ return routeName;
8
+ }
9
+ return void 0;
10
+ }
11
+ function isAvailableRouteName(name) {
12
+ return typeof name === "string" && Object.keys(routes).includes(name);
13
+ }
14
+ export {
15
+ useRouteName
16
+ };
@@ -0,0 +1,4 @@
1
+ import type { AvailableRoutes } from './index.js';
2
+ export declare function useRoutePaths(): Record<string | number, string>;
3
+ export declare function useRoutePath(routeName?: keyof AvailableRoutes): string | undefined;
4
+ //# sourceMappingURL=useRoutePaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRoutePaths.d.ts","sourceRoot":"","sources":["../src/useRoutePaths.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAGjD,wBAAgB,aAAa,oCAc5B;AAED,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,eAAe,sBAW7D"}
@@ -0,0 +1,25 @@
1
+ import { useRouterState } from "./router-context.js";
2
+ import { useRouteName } from "./useRouteName.js";
3
+ function useRoutePaths() {
4
+ const routerState = useRouterState();
5
+ const routePaths = Object.values(routerState.routes.pathRouteMap).reduce((routePathsAcc, currRoute) => {
6
+ if (currRoute.name) {
7
+ routePathsAcc[currRoute.name] = currRoute.path;
8
+ }
9
+ return routePathsAcc;
10
+ }, {});
11
+ return routePaths;
12
+ }
13
+ function useRoutePath(routeName) {
14
+ const currentRouteName = useRouteName();
15
+ const routePaths = useRoutePaths();
16
+ const name = routeName || currentRouteName;
17
+ if (!name) {
18
+ return void 0;
19
+ }
20
+ return routePaths[name];
21
+ }
22
+ export {
23
+ useRoutePath,
24
+ useRoutePaths
25
+ };
package/dist/util.d.ts ADDED
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Get param name, type, and match for a route.
3
+ *
4
+ * '/blog/{year}/{month}/{day:Int}/{filePath...}'
5
+ * => [
6
+ * ['year', 'String', '{year}'],
7
+ * ['month', 'String', '{month}'],
8
+ * ['day', 'Int', '{day:Int}'],
9
+ * ['filePath', 'Glob', '{filePath...}']
10
+ * ]
11
+ *
12
+ * Only exported to be able to test it
13
+ */
14
+ export declare function paramsForRoute(route: string): string[][];
15
+ export type TrailingSlashesTypes = 'never' | 'always' | 'preserve';
16
+ export interface ParamType {
17
+ match?: RegExp;
18
+ parse?: (value: any) => unknown;
19
+ }
20
+ /**
21
+ * Determine if the given route is a match for the given pathname. If so,
22
+ * extract any named params and return them in an object.
23
+ *
24
+ * route - The route path as specified in the <Route path={...} />
25
+ * pathname - The pathname from the window.location.
26
+ * paramTypes - The object containing all param type definitions.
27
+ * matchSubPaths - Also match sub routes
28
+ *
29
+ * Examples:
30
+ *
31
+ * matchPath('/blog/{year}/{month}/{day}', '/blog/2019/12/07')
32
+ * => { match: true, params: { year: '2019', month: '12', day: '07' }}
33
+ *
34
+ * matchPath('/about', '/')
35
+ * => { match: false }
36
+ *
37
+ * matchPath('/post/{id:Int}', '/post/7')
38
+ * => { match: true, params: { id: 7 }}
39
+ *
40
+ * matchPath('/post/1', '/post/', { matchSubPaths: true })
41
+ * => { match: true, params: {} }
42
+ */
43
+ export declare function matchPath(routeDefinition: string, pathname: string, { userParamTypes, matchSubPaths, }?: {
44
+ userParamTypes?: Record<string, ParamType>;
45
+ matchSubPaths?: boolean;
46
+ }): {
47
+ match: boolean;
48
+ params?: undefined;
49
+ } | {
50
+ match: boolean;
51
+ params: Record<string, unknown>;
52
+ };
53
+ interface GetRouteRegexOptions {
54
+ matchSubPaths?: boolean;
55
+ allParamTypes?: Record<string, ParamType>;
56
+ }
57
+ /**
58
+ * This function will return a regex for each route path i.e. /blog/{year}/{month}/{day}
59
+ * will return a regex like /blog/([^/$1*]+)/([^/$1*]+)/([^/$1*]+)
60
+ *
61
+ * @returns
62
+ */
63
+ export declare function getRouteRegexAndParams(route: string, { matchSubPaths, allParamTypes, }?: GetRouteRegexOptions | undefined): {
64
+ matchRegex: RegExp;
65
+ routeParams: string[][];
66
+ matchRegexString: string;
67
+ };
68
+ /**
69
+ * Parse the given search string into key/value pairs and return them in an
70
+ * object.
71
+ *
72
+ * Examples:
73
+ *
74
+ * parseSearch('?key1=val1&key2=val2')
75
+ * => { key1: 'val1', key2: 'val2' }
76
+ *
77
+ * @fixme
78
+ * This utility ignores keys with multiple values such as `?foo=1&foo=2`.
79
+ */
80
+ export declare function parseSearch(search: string | string[][] | Record<string, string> | URLSearchParams | undefined): {};
81
+ /**
82
+ * Validate a path to make sure it follows the router's rules. If any problems
83
+ * are found, a descriptive Error will be thrown, as problems with routes are
84
+ * critical enough to be considered fatal.
85
+ */
86
+ export declare function validatePath(path: string, routeName: string): void;
87
+ /**
88
+ * Take a given route path and replace any named parameters with those in the
89
+ * given args object. Any extra params not used in the path will be appended
90
+ * as key=value pairs in the search part.
91
+ *
92
+ * Examples:
93
+ *
94
+ * replaceParams('/tags/{tag}', { tag: 'code', extra: 'foo' })
95
+ * => '/tags/code?extra=foo
96
+ */
97
+ export declare function replaceParams(route: string, args?: Record<string, unknown>): string;
98
+ export type FlattenSearchParams = ReturnType<typeof flattenSearchParams>;
99
+ /**
100
+ * Returns a flat array of search params
101
+ *
102
+ * `useMatch` hook options `searchParams` requires a flat array
103
+ *
104
+ * Example:
105
+ * ```
106
+ * parseSearch('?key1=val1&key2=val2')
107
+ * => { key1: 'val1', key2: 'val2' }
108
+ *
109
+ * flattenSearchParams(parseSearch('?key1=val1&key2=val2'))
110
+ * => [ { key1: 'val1' }, { key2: 'val2' } ]
111
+ * ```
112
+ */
113
+ export declare function flattenSearchParams(queryString: string): Record<string, unknown>[];
114
+ /**
115
+ * Detect if we're in an iframe.
116
+ *
117
+ * From https://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
118
+ */
119
+ export declare function inIframe(): boolean;
120
+ export {};
121
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,cAyB3C;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAA;AAElE,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAA;CAChC;AAwBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CACvB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,EACE,cAAc,EACd,aAAa,GACd,GAAE;IACD,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAA;CAIxB;;;;;;EA2CF;AAED,UAAU,oBAAoB;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAC1C;AACD;;;;;GAKG;AAEH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,EACE,aAAqB,EACrB,aAA8B,GAC/B,GAAE,oBAAoB,GAAG,SAAc;;;;EA+BzC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,MAAM,EACF,MAAM,GACN,MAAM,EAAE,EAAE,GACV,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,eAAe,GACf,SAAS,MAWd;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAyC3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,UAgCnC;AAED,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAExE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,6BAQtD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,YAMvB"}
package/dist/util.js ADDED
@@ -0,0 +1,183 @@
1
+ function paramsForRoute(route) {
2
+ const params = [...route.matchAll(/\{([^}]+)\}/g)];
3
+ return params.map((match) => match[1]).map((match) => {
4
+ const parts = match.split(":");
5
+ let name = parts[0];
6
+ if (name.endsWith("...")) {
7
+ name = name.slice(0, -3);
8
+ }
9
+ let type = parts[1];
10
+ if (!type) {
11
+ type = match.endsWith("...") ? "Glob" : "String";
12
+ }
13
+ return [name, type, `{${match}}`];
14
+ });
15
+ }
16
+ const coreParamTypes = {
17
+ String: {
18
+ match: /[^/]+/
19
+ },
20
+ Int: {
21
+ match: /\d+/,
22
+ parse: Number
23
+ },
24
+ Float: {
25
+ match: /[-+]?(?:\d*\.?\d+|\d+\.?\d*)(?:[eE][-+]?\d+)?/,
26
+ parse: Number
27
+ },
28
+ Boolean: {
29
+ match: /true|false/,
30
+ parse: (boolAsString) => boolAsString === "true"
31
+ },
32
+ Glob: {
33
+ match: /.*/
34
+ }
35
+ };
36
+ function matchPath(routeDefinition, pathname, {
37
+ userParamTypes,
38
+ matchSubPaths
39
+ } = {
40
+ userParamTypes: {},
41
+ matchSubPaths: false
42
+ }) {
43
+ const allParamTypes = { ...coreParamTypes, ...userParamTypes };
44
+ const { matchRegex, routeParams: routeParamsDefinition } = getRouteRegexAndParams(routeDefinition, {
45
+ matchSubPaths,
46
+ allParamTypes
47
+ });
48
+ const matches = [...pathname.matchAll(matchRegex)];
49
+ if (matches.length === 0) {
50
+ return { match: false };
51
+ }
52
+ const providedParams = matches[0].slice(1);
53
+ if (routeParamsDefinition.length > 0) {
54
+ const params = providedParams.reduce(
55
+ (acc, value, index) => {
56
+ const [name, transformName] = routeParamsDefinition[index];
57
+ const typeInfo = allParamTypes[transformName];
58
+ let transformedValue = value;
59
+ if (typeof typeInfo?.parse === "function") {
60
+ transformedValue = typeInfo.parse(value);
61
+ }
62
+ return {
63
+ ...acc,
64
+ [name]: transformedValue
65
+ };
66
+ },
67
+ {}
68
+ );
69
+ return { match: true, params };
70
+ }
71
+ return { match: true };
72
+ }
73
+ function getRouteRegexAndParams(route, {
74
+ matchSubPaths = false,
75
+ allParamTypes = coreParamTypes
76
+ } = {}) {
77
+ let typeMatchingRoute = route;
78
+ const routeParams = paramsForRoute(route);
79
+ for (const [_name, type, match] of routeParams) {
80
+ const matcher = allParamTypes[type]?.match;
81
+ const typeRegexp = matcher?.source || "[^/]+";
82
+ typeMatchingRoute = typeMatchingRoute.replace(match, `(${typeRegexp})`);
83
+ }
84
+ const matchRegex = matchSubPaths ? new RegExp(`^${typeMatchingRoute}(?:/.*)?$`, "g") : new RegExp(`^${typeMatchingRoute}$`, "g");
85
+ const matchRegexString = matchSubPaths ? `^${typeMatchingRoute}(?:/.*)?$` : `^${typeMatchingRoute}$`;
86
+ return {
87
+ matchRegex,
88
+ routeParams,
89
+ matchRegexString
90
+ };
91
+ }
92
+ function parseSearch(search) {
93
+ const searchParams = new URLSearchParams(search);
94
+ return [...searchParams.keys()].reduce(
95
+ (params, key) => ({
96
+ ...params,
97
+ [key]: searchParams.get(key)
98
+ }),
99
+ {}
100
+ );
101
+ }
102
+ function validatePath(path, routeName) {
103
+ if (!path.startsWith("/")) {
104
+ throw new Error(
105
+ `Route path for ${routeName} does not begin with a slash: "${path}"`
106
+ );
107
+ }
108
+ if (path.includes(" ")) {
109
+ throw new Error(`Route path for ${routeName} contains spaces: "${path}"`);
110
+ }
111
+ if (/{(?:ref|key)(?::|})/.test(path)) {
112
+ throw new Error(
113
+ [
114
+ `Route for ${routeName} contains ref or key as a path parameter: "${path}"`,
115
+ "`ref` and `key` shouldn't be used as path parameters because they're special React props.",
116
+ "You can fix this by renaming the path parameter."
117
+ ].join("\n")
118
+ );
119
+ }
120
+ if (path.length > 2e3) {
121
+ throw new Error(
122
+ `Route path for ${routeName} is too long to process at ${path.length} characters, limit is 2000 characters.`
123
+ );
124
+ }
125
+ const matches = path.matchAll(/\{([^}]+)\}/g);
126
+ const memo = {};
127
+ for (const match of matches) {
128
+ const param = match[1].split(":")[0];
129
+ if (memo[param]) {
130
+ throw new Error(`Route path contains duplicate parameter: "${path}"`);
131
+ } else {
132
+ memo[param] = true;
133
+ }
134
+ }
135
+ }
136
+ function replaceParams(route, args = {}) {
137
+ const params = paramsForRoute(route);
138
+ let path = route;
139
+ params.forEach((param) => {
140
+ const [name, _type, match] = param;
141
+ const value = args[name];
142
+ if (value !== void 0) {
143
+ path = path.replace(match, value);
144
+ } else {
145
+ throw new Error(
146
+ `Missing parameter '${name}' for route '${route}' when generating a navigation URL.`
147
+ );
148
+ }
149
+ });
150
+ const paramNames = params.map((param) => param[0]);
151
+ const extraArgKeys = Object.keys(args).filter((x) => !paramNames.includes(x)).filter((x) => args[x] !== void 0 && args[x] !== null);
152
+ if (extraArgKeys.length) {
153
+ const extraArgs = Object.fromEntries(
154
+ extraArgKeys.map((key) => [key, `${args[key]}`])
155
+ );
156
+ path += `?${new URLSearchParams(extraArgs).toString()}`;
157
+ }
158
+ return path;
159
+ }
160
+ function flattenSearchParams(queryString) {
161
+ const searchParams = [];
162
+ for (const [key, value] of Object.entries(parseSearch(queryString))) {
163
+ searchParams.push({ [key]: value });
164
+ }
165
+ return searchParams;
166
+ }
167
+ function inIframe() {
168
+ try {
169
+ return global?.self !== global?.top;
170
+ } catch {
171
+ return true;
172
+ }
173
+ }
174
+ export {
175
+ flattenSearchParams,
176
+ getRouteRegexAndParams,
177
+ inIframe,
178
+ matchPath,
179
+ paramsForRoute,
180
+ parseSearch,
181
+ replaceParams,
182
+ validatePath
183
+ };
package/package.json ADDED
@@ -0,0 +1,127 @@
1
+ {
2
+ "name": "@cedarjs/router",
3
+ "version": "0.0.4",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/cedarjs/cedar.git",
7
+ "directory": "packages/router"
8
+ },
9
+ "license": "MIT",
10
+ "type": "module",
11
+ "exports": {
12
+ ".": {
13
+ "import": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "require": {
18
+ "types": "./dist/cjs/index.d.ts",
19
+ "default": "./dist/cjs/index.js"
20
+ }
21
+ },
22
+ "./Route": {
23
+ "import": "./dist/Route.js",
24
+ "require": "./dist/cjs/Route.js"
25
+ },
26
+ "./Set": {
27
+ "import": "./dist/Set.js",
28
+ "require": "./dist/cjs/Set.js"
29
+ },
30
+ "./Link": {
31
+ "import": "./dist/link.js",
32
+ "require": "./dist/cjs/link.js"
33
+ },
34
+ "./NavLink": {
35
+ "import": "./dist/navLink.js",
36
+ "require": "./dist/cjs/navLink.js"
37
+ },
38
+ "./location": {
39
+ "import": "./dist/location.js",
40
+ "require": "./dist/cjs/location.js"
41
+ },
42
+ "./namedRoutes": {
43
+ "import": "./dist/namedRoutes.js",
44
+ "require": "./dist/cjs/namedRoutes.js"
45
+ },
46
+ "./util": {
47
+ "import": "./dist/util.js",
48
+ "require": "./dist/cjs/util.js"
49
+ },
50
+ "./react-util": {
51
+ "import": "./dist/react-util.js",
52
+ "require": "./dist/cjs/react-util.js"
53
+ },
54
+ "./rscCss": {
55
+ "require": "./dist/cjs/rsc/rscCss.js",
56
+ "import": "./dist/rsc/rscCss.js"
57
+ },
58
+ "./serverRouter": {
59
+ "import": "./dist/rsc/ServerRouter.js",
60
+ "require": "./dist/cjs/rsc/ServerRouter.js"
61
+ },
62
+ "./RscRouter": {
63
+ "react-server": "./dist/rsc/ServerRouter.js",
64
+ "require": "./dist/cjs/rsc/ClientRouter.js",
65
+ "import": "./dist/rsc/ClientRouter.js"
66
+ },
67
+ "./SsrRouter": {
68
+ "react-server": "./dist/rsc/ServerRouter.js",
69
+ "require": "./dist/cjs/rsc/SsrRouter.js",
70
+ "import": "./dist/rsc/SsrRouter.js"
71
+ },
72
+ "./dist/*": {
73
+ "require": "./dist/cjs/*.js",
74
+ "import": "./dist/*.js"
75
+ }
76
+ },
77
+ "main": "dist/index.js",
78
+ "types": "dist/index.d.ts",
79
+ "files": [
80
+ "dist",
81
+ "skip-nav.css"
82
+ ],
83
+ "scripts": {
84
+ "build": "tsx ./build.ts",
85
+ "build:pack": "yarn pack -o cedar-router.tgz",
86
+ "build:types": "tsc --build --verbose tsconfig.build.json",
87
+ "build:types-cjs": "tsc --build --verbose tsconfig.cjs.json",
88
+ "build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
89
+ "check:attw": "tsx ./attw.ts",
90
+ "check:package": "concurrently npm:check:attw yarn publint",
91
+ "prepublishOnly": "NODE_ENV=production yarn build",
92
+ "test": "vitest run",
93
+ "test:types": "tstyche",
94
+ "test:watch": "vitest watch"
95
+ },
96
+ "dependencies": {
97
+ "@babel/runtime-corejs3": "7.26.10",
98
+ "@cedarjs/auth": "0.0.4",
99
+ "@cedarjs/server-store": "0.0.4",
100
+ "core-js": "3.42.0",
101
+ "react": "18.3.1",
102
+ "react-dom": "18.3.1"
103
+ },
104
+ "devDependencies": {
105
+ "@arethetypeswrong/cli": "0.16.4",
106
+ "@babel/cli": "7.26.4",
107
+ "@babel/core": "^7.26.10",
108
+ "@cedarjs/framework-tools": "0.0.4",
109
+ "@testing-library/jest-dom": "6.5.0",
110
+ "@types/react": "^18.2.55",
111
+ "@types/react-dom": "^18.2.19",
112
+ "concurrently": "8.2.2",
113
+ "publint": "0.3.11",
114
+ "tstyche": "3.0.0",
115
+ "tsx": "4.19.3",
116
+ "typescript": "5.6.2",
117
+ "vitest": "2.1.9"
118
+ },
119
+ "peerDependencies": {
120
+ "react": "18.3.1",
121
+ "react-dom": "18.3.1"
122
+ },
123
+ "publishConfig": {
124
+ "access": "public"
125
+ },
126
+ "gitHead": "5b4f77f985bd86ee31ee7338312627accf0cb85b"
127
+ }