router-kit 1.3.4 → 2.0.1

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 (49) hide show
  1. package/README.md +117 -421
  2. package/dist/components/Link.d.ts +23 -6
  3. package/dist/components/Link.js +51 -6
  4. package/dist/components/NavLink.d.ts +44 -7
  5. package/dist/components/NavLink.js +111 -10
  6. package/dist/components/Outlet.d.ts +66 -0
  7. package/dist/components/Outlet.js +69 -0
  8. package/dist/components/Router.d.ts +57 -11
  9. package/dist/components/Router.js +60 -12
  10. package/dist/components/route.d.ts +57 -7
  11. package/dist/components/route.js +35 -5
  12. package/dist/context/OutletContext.d.ts +41 -0
  13. package/dist/context/OutletContext.js +31 -0
  14. package/dist/context/RouterContext.d.ts +9 -0
  15. package/dist/context/RouterContext.js +21 -1
  16. package/dist/context/RouterProvider.d.ts +15 -4
  17. package/dist/context/RouterProvider.js +441 -101
  18. package/dist/core/createRouter.d.ts +65 -0
  19. package/dist/core/createRouter.js +129 -7
  20. package/dist/hooks/useBlocker.d.ts +65 -0
  21. package/dist/hooks/useBlocker.js +152 -0
  22. package/dist/hooks/useDynamicComponents.d.ts +61 -2
  23. package/dist/hooks/useDynamicComponents.js +89 -17
  24. package/dist/hooks/useLoaderData.d.ts +98 -0
  25. package/dist/hooks/useLoaderData.js +107 -0
  26. package/dist/hooks/useLocation.d.ts +37 -0
  27. package/dist/hooks/useLocation.js +130 -2
  28. package/dist/hooks/useMatches.d.ts +99 -0
  29. package/dist/hooks/useMatches.js +114 -0
  30. package/dist/hooks/useNavigate.d.ts +59 -0
  31. package/dist/hooks/useNavigate.js +70 -0
  32. package/dist/hooks/useParams.d.ts +57 -2
  33. package/dist/hooks/useParams.js +60 -14
  34. package/dist/hooks/useQuery.d.ts +53 -3
  35. package/dist/hooks/useQuery.js +107 -8
  36. package/dist/hooks/useRouter.d.ts +34 -0
  37. package/dist/hooks/useRouter.js +35 -1
  38. package/dist/index.d.ts +16 -6
  39. package/dist/index.js +21 -5
  40. package/dist/ssr/StaticRouter.d.ts +65 -0
  41. package/dist/ssr/StaticRouter.js +322 -0
  42. package/dist/ssr/hydrateRouter.d.ts +44 -0
  43. package/dist/ssr/hydrateRouter.js +60 -0
  44. package/dist/ssr/index.d.ts +92 -0
  45. package/dist/ssr/index.js +92 -0
  46. package/dist/ssr/serverUtils.d.ts +107 -0
  47. package/dist/ssr/serverUtils.js +288 -0
  48. package/dist/types/index.d.ts +201 -2
  49. package/package.json +14 -2
@@ -0,0 +1,107 @@
1
+ import type { Route, RouteMatch, RouteMeta } from "../types";
2
+ /**
3
+ * Result from matching routes on the server
4
+ */
5
+ export interface ServerMatchResult {
6
+ /** Matched route path */
7
+ matches: RouteMatch[];
8
+ /** Extracted route params */
9
+ params: Record<string, string>;
10
+ /** Redirect URL if route redirects */
11
+ redirect?: string;
12
+ /** HTTP status code */
13
+ statusCode: number;
14
+ /** Route metadata */
15
+ meta?: RouteMeta;
16
+ }
17
+ /**
18
+ * Result from data loading on the server
19
+ */
20
+ export interface ServerLoaderResult<T = any> {
21
+ /** Loaded data keyed by route path */
22
+ data: Record<string, T>;
23
+ /** Errors encountered during loading */
24
+ errors: Record<string, Error>;
25
+ /** Time taken to load data (ms) */
26
+ loadTime: number;
27
+ }
28
+ /**
29
+ * Match routes for a given URL on the server
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const result = matchServerRoutes(routes, '/users/123');
34
+ * if (result.redirect) {
35
+ * return res.redirect(result.redirect);
36
+ * }
37
+ * console.log(result.params); // { id: '123' }
38
+ * ```
39
+ */
40
+ export declare function matchServerRoutes(routes: Route[], pathname: string, parentPath?: string): ServerMatchResult;
41
+ /**
42
+ * Prefetch loader data for matched routes
43
+ *
44
+ * This function runs all route loaders in parallel and returns
45
+ * the combined data. Use this on the server before rendering.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // server.ts
50
+ * app.get('*', async (req, res) => {
51
+ * const matchResult = matchServerRoutes(routes, req.url);
52
+ *
53
+ * if (matchResult.redirect) {
54
+ * return res.redirect(matchResult.redirect);
55
+ * }
56
+ *
57
+ * const loaderResult = await prefetchLoaderData(
58
+ * matchResult.matches,
59
+ * req.url,
60
+ * { headers: req.headers }
61
+ * );
62
+ *
63
+ * const html = renderToString(
64
+ * <StaticRouter
65
+ * routes={routes}
66
+ * location={req.url}
67
+ * loaderData={loaderResult.data}
68
+ * />
69
+ * );
70
+ *
71
+ * // Inject loader data for hydration
72
+ * const finalHtml = html.replace(
73
+ * '</head>',
74
+ * `<script>window.__LOADER_DATA__ = ${JSON.stringify(loaderResult.data)}</script></head>`
75
+ * );
76
+ *
77
+ * res.send(finalHtml);
78
+ * });
79
+ * ```
80
+ */
81
+ export declare function prefetchLoaderData(matches: RouteMatch[], url: string, requestInit?: RequestInit): Promise<ServerLoaderResult>;
82
+ /**
83
+ * Create a Request object from Node.js IncomingMessage
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { createRequestFromNode } from 'router-kit/ssr';
88
+ *
89
+ * app.get('*', (req, res) => {
90
+ * const request = createRequestFromNode(req);
91
+ * // Use request with loaders
92
+ * });
93
+ * ```
94
+ */
95
+ export declare function createRequestFromNode(nodeRequest: {
96
+ url?: string;
97
+ method?: string;
98
+ headers?: Record<string, string | string[] | undefined>;
99
+ }, baseUrl?: string): Request;
100
+ /**
101
+ * Generate script tag for hydrating loader data on the client
102
+ */
103
+ export declare function getLoaderDataScript(data: Record<string, any>): string;
104
+ /**
105
+ * Get loader data from window on the client side
106
+ */
107
+ export declare function getHydratedLoaderData(): Record<string, any> | null;
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Extract params from a path using a pattern
3
+ */
4
+ const extractParams = (pattern, pathname) => {
5
+ const patternParts = pattern.split("/").filter(Boolean);
6
+ const pathParts = pathname.split("/").filter(Boolean);
7
+ if (patternParts.length !== pathParts.length) {
8
+ const hasCatchAll = patternParts.some((p) => p.startsWith("*"));
9
+ if (!hasCatchAll)
10
+ return null;
11
+ }
12
+ const params = {};
13
+ for (let i = 0; i < patternParts.length; i++) {
14
+ const patternPart = patternParts[i];
15
+ const pathPart = pathParts[i];
16
+ if (patternPart.startsWith("*")) {
17
+ const paramName = patternPart.slice(1) || "splat";
18
+ params[paramName] = pathParts.slice(i).join("/");
19
+ return params;
20
+ }
21
+ if (patternPart.startsWith(":")) {
22
+ const paramName = patternPart.slice(1);
23
+ if (paramName.endsWith("?")) {
24
+ params[paramName.slice(0, -1)] = pathPart !== null && pathPart !== void 0 ? pathPart : "";
25
+ }
26
+ else {
27
+ if (pathPart === undefined)
28
+ return null;
29
+ params[paramName] = pathPart;
30
+ }
31
+ continue;
32
+ }
33
+ if (patternPart !== pathPart)
34
+ return null;
35
+ }
36
+ return params;
37
+ };
38
+ /**
39
+ * Join paths safely
40
+ */
41
+ const joinPaths = (parent, child) => {
42
+ const normalizedParent = parent.endsWith("/") ? parent.slice(0, -1) : parent;
43
+ const normalizedChild = child.startsWith("/") ? child : `/${child}`;
44
+ return `${normalizedParent}${normalizedChild}`;
45
+ };
46
+ /**
47
+ * Normalize path to string (handles array paths)
48
+ */
49
+ const normalizePath = (path) => {
50
+ if (Array.isArray(path)) {
51
+ return path.map((p) => (p.startsWith("/") ? p.slice(1) : p)).join("|");
52
+ }
53
+ return path;
54
+ };
55
+ /**
56
+ * Get the first path from a path (string or array)
57
+ */
58
+ const getFirstPath = (path) => {
59
+ if (Array.isArray(path)) {
60
+ return path[0] || "";
61
+ }
62
+ // Handle pipe-separated paths (already normalized)
63
+ if (path.includes("|")) {
64
+ return path.split("|")[0];
65
+ }
66
+ return path;
67
+ };
68
+ /**
69
+ * Match routes for a given URL on the server
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * const result = matchServerRoutes(routes, '/users/123');
74
+ * if (result.redirect) {
75
+ * return res.redirect(result.redirect);
76
+ * }
77
+ * console.log(result.params); // { id: '123' }
78
+ * ```
79
+ */
80
+ export function matchServerRoutes(routes, pathname, parentPath = "/") {
81
+ const matches = [];
82
+ // Sort routes by priority
83
+ const staticRoutes = [];
84
+ const dynamicRoutes = [];
85
+ const catchAllRoutes = [];
86
+ for (const route of routes) {
87
+ const is404 = route.path === "404" || route.path === "/404";
88
+ if (is404)
89
+ continue;
90
+ const pathArray = Array.isArray(route.path) ? route.path : [route.path];
91
+ const hasCatchAll = pathArray.some((p) => p.includes("*"));
92
+ const hasDynamicParams = pathArray.some((p) => p.includes(":"));
93
+ if (hasCatchAll) {
94
+ catchAllRoutes.push(route);
95
+ }
96
+ else if (hasDynamicParams) {
97
+ dynamicRoutes.push(route);
98
+ }
99
+ else {
100
+ staticRoutes.push(route);
101
+ }
102
+ }
103
+ const orderedRoutes = [...staticRoutes, ...dynamicRoutes, ...catchAllRoutes];
104
+ for (const route of orderedRoutes) {
105
+ const normalizedRoutePath = normalizePath(route.path);
106
+ const firstPath = getFirstPath(route.path);
107
+ const fullPath = joinPaths(parentPath, firstPath);
108
+ const patterns = normalizedRoutePath.split("|");
109
+ for (const pattern of patterns) {
110
+ const fullPattern = joinPaths(parentPath, pattern);
111
+ const extractedParams = extractParams(fullPattern, pathname);
112
+ if (extractedParams !== null) {
113
+ // Handle redirects
114
+ if (route.redirectTo) {
115
+ return {
116
+ matches: [],
117
+ params: extractedParams,
118
+ redirect: route.redirectTo,
119
+ statusCode: 302,
120
+ meta: route.meta,
121
+ };
122
+ }
123
+ const match = {
124
+ route,
125
+ params: extractedParams,
126
+ pathname,
127
+ pathnameBase: parentPath,
128
+ pattern: fullPattern,
129
+ };
130
+ matches.push(match);
131
+ // Check nested routes
132
+ if (route.children && route.children.length > 0) {
133
+ const childResult = matchServerRoutes(route.children, pathname, fullPath);
134
+ if (childResult.redirect) {
135
+ return childResult;
136
+ }
137
+ if (childResult.matches.length > 0) {
138
+ return {
139
+ matches: [...matches, ...childResult.matches],
140
+ params: { ...extractedParams, ...childResult.params },
141
+ statusCode: childResult.statusCode,
142
+ meta: childResult.meta || route.meta,
143
+ };
144
+ }
145
+ }
146
+ return {
147
+ matches,
148
+ params: extractedParams,
149
+ statusCode: 200,
150
+ meta: route.meta,
151
+ };
152
+ }
153
+ }
154
+ // Check children even if parent doesn't match
155
+ if (route.children) {
156
+ const firstPath = getFirstPath(route.path);
157
+ const childFullPath = joinPaths(parentPath, firstPath);
158
+ const childResult = matchServerRoutes(route.children, pathname, childFullPath);
159
+ if (childResult.matches.length > 0 || childResult.redirect) {
160
+ return childResult;
161
+ }
162
+ }
163
+ }
164
+ // No match found
165
+ return {
166
+ matches: [],
167
+ params: {},
168
+ statusCode: 404,
169
+ };
170
+ }
171
+ /**
172
+ * Prefetch loader data for matched routes
173
+ *
174
+ * This function runs all route loaders in parallel and returns
175
+ * the combined data. Use this on the server before rendering.
176
+ *
177
+ * @example
178
+ * ```ts
179
+ * // server.ts
180
+ * app.get('*', async (req, res) => {
181
+ * const matchResult = matchServerRoutes(routes, req.url);
182
+ *
183
+ * if (matchResult.redirect) {
184
+ * return res.redirect(matchResult.redirect);
185
+ * }
186
+ *
187
+ * const loaderResult = await prefetchLoaderData(
188
+ * matchResult.matches,
189
+ * req.url,
190
+ * { headers: req.headers }
191
+ * );
192
+ *
193
+ * const html = renderToString(
194
+ * <StaticRouter
195
+ * routes={routes}
196
+ * location={req.url}
197
+ * loaderData={loaderResult.data}
198
+ * />
199
+ * );
200
+ *
201
+ * // Inject loader data for hydration
202
+ * const finalHtml = html.replace(
203
+ * '</head>',
204
+ * `<script>window.__LOADER_DATA__ = ${JSON.stringify(loaderResult.data)}</script></head>`
205
+ * );
206
+ *
207
+ * res.send(finalHtml);
208
+ * });
209
+ * ```
210
+ */
211
+ export async function prefetchLoaderData(matches, url, requestInit) {
212
+ const startTime = Date.now();
213
+ const data = {};
214
+ const errors = {};
215
+ const loaderPromises = matches
216
+ .filter((match) => match.route.loader)
217
+ .map(async (match) => {
218
+ const routePath = match.pattern;
219
+ const abortController = new AbortController();
220
+ try {
221
+ // Create a Request object for the loader
222
+ const request = new Request(url, {
223
+ ...requestInit,
224
+ signal: abortController.signal,
225
+ });
226
+ const loaderArgs = {
227
+ params: match.params,
228
+ request,
229
+ signal: abortController.signal,
230
+ };
231
+ const result = await match.route.loader(loaderArgs);
232
+ data[routePath] = result;
233
+ }
234
+ catch (error) {
235
+ errors[routePath] =
236
+ error instanceof Error ? error : new Error(String(error));
237
+ }
238
+ });
239
+ await Promise.all(loaderPromises);
240
+ return {
241
+ data,
242
+ errors,
243
+ loadTime: Date.now() - startTime,
244
+ };
245
+ }
246
+ /**
247
+ * Create a Request object from Node.js IncomingMessage
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * import { createRequestFromNode } from 'router-kit/ssr';
252
+ *
253
+ * app.get('*', (req, res) => {
254
+ * const request = createRequestFromNode(req);
255
+ * // Use request with loaders
256
+ * });
257
+ * ```
258
+ */
259
+ export function createRequestFromNode(nodeRequest, baseUrl = "http://localhost") {
260
+ const url = new URL(nodeRequest.url || "/", baseUrl);
261
+ const headers = new Headers();
262
+ if (nodeRequest.headers) {
263
+ for (const [key, value] of Object.entries(nodeRequest.headers)) {
264
+ if (value) {
265
+ headers.set(key, Array.isArray(value) ? value.join(", ") : value);
266
+ }
267
+ }
268
+ }
269
+ return new Request(url.toString(), {
270
+ method: nodeRequest.method || "GET",
271
+ headers,
272
+ });
273
+ }
274
+ /**
275
+ * Generate script tag for hydrating loader data on the client
276
+ */
277
+ export function getLoaderDataScript(data) {
278
+ const serialized = JSON.stringify(data).replace(/</g, "\\u003c");
279
+ return `<script>window.__ROUTER_KIT_DATA__ = ${serialized}</script>`;
280
+ }
281
+ /**
282
+ * Get loader data from window on the client side
283
+ */
284
+ export function getHydratedLoaderData() {
285
+ if (typeof window === "undefined")
286
+ return null;
287
+ return window.__ROUTER_KIT_DATA__ || null;
288
+ }
@@ -1,8 +1,70 @@
1
- import { JSX } from "react";
1
+ import { ComponentType, JSX, LazyExoticComponent, ReactNode } from "react";
2
+ /**
3
+ * Route configuration interface
4
+ */
2
5
  export interface Route {
6
+ /** Path pattern(s) for the route */
3
7
  path: string | string[];
8
+ /** Component to render */
4
9
  component: JSX.Element;
10
+ /** Nested child routes */
5
11
  children?: Route[];
12
+ /** Index route flag - renders when parent path matches exactly */
13
+ index?: boolean;
14
+ /** Lazy-loaded component */
15
+ lazy?: LazyExoticComponent<ComponentType<any>>;
16
+ /** Route loader function for data fetching */
17
+ loader?: RouteLoader;
18
+ /** Error boundary element for this route */
19
+ errorElement?: JSX.Element;
20
+ /** Redirect to another path */
21
+ redirectTo?: string;
22
+ /** Route guard function */
23
+ guard?: RouteGuard;
24
+ /** Route metadata */
25
+ meta?: RouteMeta;
26
+ }
27
+ /**
28
+ * Route loader function type
29
+ */
30
+ export type RouteLoader<T = any> = (args: LoaderArgs) => Promise<T> | T;
31
+ /**
32
+ * Loader function arguments
33
+ */
34
+ export interface LoaderArgs {
35
+ params: Record<string, string>;
36
+ request: Request;
37
+ signal: AbortSignal;
38
+ }
39
+ /**
40
+ * Route guard function type
41
+ */
42
+ export type RouteGuard = (args: GuardArgs) => boolean | Promise<boolean> | string;
43
+ /**
44
+ * Guard function arguments
45
+ */
46
+ export interface GuardArgs {
47
+ pathname: string;
48
+ params: Record<string, string>;
49
+ search: string;
50
+ }
51
+ /**
52
+ * Route metadata
53
+ */
54
+ export interface RouteMeta {
55
+ title?: string;
56
+ description?: string;
57
+ [key: string]: any;
58
+ }
59
+ /**
60
+ * Match result from route matching
61
+ */
62
+ export interface RouteMatch {
63
+ route: Route;
64
+ params: Record<string, string>;
65
+ pathname: string;
66
+ pathnameBase: string;
67
+ pattern: string;
6
68
  }
7
69
  export interface GetComponent {
8
70
  (routes: Route[], currentPath: string, parentPath?: string): JSX.Element | null;
@@ -12,20 +74,96 @@ export interface Routes {
12
74
  fullPath: string;
13
75
  path: string;
14
76
  }
77
+ /**
78
+ * Navigation options
79
+ */
15
80
  export interface NavigateOptions {
81
+ /** Replace current history entry instead of pushing */
16
82
  replace?: boolean;
83
+ /** State to pass with navigation */
17
84
  state?: any;
85
+ /** Prevent scroll reset after navigation */
86
+ preventScrollReset?: boolean;
87
+ /** Relative navigation base */
88
+ relative?: "route" | "path";
18
89
  }
90
+ /**
91
+ * Navigation function type
92
+ */
93
+ export type NavigateFunction = {
94
+ (to: string, options?: NavigateOptions): void;
95
+ (delta: number): void;
96
+ };
97
+ /**
98
+ * Router context type
99
+ */
19
100
  export interface RouterContextType {
101
+ /** Current pathname */
102
+ pathname: string;
103
+ /** Full path pattern with params (e.g., /users/:id) */
104
+ pattern: string;
105
+ /** Current search string */
106
+ search: string;
107
+ /** Current hash */
108
+ hash: string;
109
+ /** History state */
110
+ state: any;
111
+ /** Route parameters */
112
+ params: Record<string, string>;
113
+ /** Current route match */
114
+ matches: RouteMatch[];
115
+ /** Navigate function */
116
+ navigate: NavigateFunction;
117
+ /** Go back in history */
118
+ back: () => void;
119
+ /** Go forward in history */
120
+ forward: () => void;
121
+ /** Navigation in progress */
122
+ isNavigating: boolean;
123
+ /** Loader data from current route */
124
+ loaderData: any;
125
+ /** Current route meta */
126
+ meta: RouteMeta | null;
127
+ /** @deprecated Use pathname instead */
20
128
  path: string;
129
+ /** @deprecated Use pattern instead */
21
130
  fullPathWithParams: string;
22
- navigate: (to: string, options?: NavigateOptions) => void;
23
131
  }
132
+ /**
133
+ * Location object
134
+ */
24
135
  export interface Location {
136
+ /** Current pathname */
25
137
  pathname: string;
138
+ /** Query string including leading ? */
26
139
  search: string;
140
+ /** Hash including leading # */
27
141
  hash: string;
142
+ /** History state */
28
143
  state: any;
144
+ /** Unique key for this location */
145
+ key: string;
146
+ }
147
+ /**
148
+ * History action types
149
+ */
150
+ export type HistoryAction = "POP" | "PUSH" | "REPLACE";
151
+ /**
152
+ * Navigation blocker function
153
+ */
154
+ export type BlockerFunction = (args: {
155
+ currentLocation: Location;
156
+ nextLocation: Location;
157
+ action: HistoryAction;
158
+ }) => boolean;
159
+ /**
160
+ * Blocker state
161
+ */
162
+ export interface Blocker {
163
+ state: "blocked" | "proceeding" | "unblocked";
164
+ proceed: () => void;
165
+ reset: () => void;
166
+ location?: Location;
29
167
  }
30
168
  export interface RouterError extends Error {
31
169
  code: "NAVIGATION_ABORTED" | "ROUTER_NOT_FOUND" | "INVALID_ROUTE";
@@ -33,4 +171,65 @@ export interface RouterError extends Error {
33
171
  export interface DynamicComponents {
34
172
  (dynamicComponentsObject: Record<string, JSX.Element>, variationParam: string): JSX.Element;
35
173
  }
174
+ /**
175
+ * Link component props
176
+ */
177
+ export interface LinkProps {
178
+ /** Target path */
179
+ to: string;
180
+ /** Children to render */
181
+ children: ReactNode;
182
+ /** CSS class name */
183
+ className?: string;
184
+ /** Navigation options */
185
+ replace?: boolean;
186
+ /** State to pass */
187
+ state?: any;
188
+ /** Prevent scroll reset */
189
+ preventScrollReset?: boolean;
190
+ /** Target attribute */
191
+ target?: string;
192
+ /** Rel attribute */
193
+ rel?: string;
194
+ /** Title attribute */
195
+ title?: string;
196
+ /** onClick handler */
197
+ onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void;
198
+ }
199
+ /**
200
+ * NavLink component props
201
+ */
202
+ export interface NavLinkProps extends LinkProps {
203
+ /** Class name when active */
204
+ activeClassName?: string;
205
+ /** Style when active */
206
+ activeStyle?: React.CSSProperties;
207
+ /** Custom active check function */
208
+ isActive?: (match: RouteMatch | null, location: Location) => boolean;
209
+ /** Match end of path (exact matching) */
210
+ end?: boolean;
211
+ /** Case sensitive matching */
212
+ caseSensitive?: boolean;
213
+ }
214
+ /**
215
+ * Router provider props
216
+ */
217
+ export interface RouterProviderProps {
218
+ routes: Route[];
219
+ /** Base path for all routes */
220
+ basename?: string;
221
+ /** Initial entries for memory history (SSR) */
222
+ initialEntries?: string[];
223
+ /** Fallback element during suspense */
224
+ fallbackElement?: JSX.Element;
225
+ }
226
+ /**
227
+ * Scroll restoration options
228
+ */
229
+ export interface ScrollRestorationProps {
230
+ /** Custom scroll key generator */
231
+ getKey?: (location: Location, matches: RouteMatch[]) => string;
232
+ /** Storage key for scroll positions */
233
+ storageKey?: string;
234
+ }
36
235
  export type { RouterKitError } from "../utils/error/errors";
package/package.json CHANGED
@@ -5,10 +5,22 @@
5
5
  "email": "mohammed.bencheikh.dev@gmail.com",
6
6
  "url": "https://mohammedbencheikh.com/"
7
7
  },
8
- "version": "1.3.4",
9
- "description": "A small React routing provider library",
8
+ "version": "2.0.1",
9
+ "description": "A professional React routing library with guards, loaders, and navigation blocking",
10
10
  "main": "dist/index.js",
11
11
  "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.js"
17
+ },
18
+ "./ssr": {
19
+ "types": "./dist/ssr/index.d.ts",
20
+ "import": "./dist/ssr/index.js",
21
+ "require": "./dist/ssr/index.js"
22
+ }
23
+ },
12
24
  "files": [
13
25
  "dist"
14
26
  ],