@real-router/solid 0.1.1 → 0.2.0
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.
- package/README.md +22 -1
- package/dist/cjs/index.d.ts +10 -3
- package/dist/cjs/index.js +32 -0
- package/dist/esm/index.d.mts +10 -3
- package/dist/esm/index.mjs +33 -2
- package/dist/types/components/RouterErrorBoundary.d.ts +9 -0
- package/dist/types/components/RouterErrorBoundary.d.ts.map +1 -0
- package/dist/types/hooks/useRouterError.d.ts +4 -0
- package/dist/types/hooks/useRouterError.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/components/RouterErrorBoundary.tsx +53 -0
- package/src/hooks/useRouterError.tsx +23 -0
- package/src/index.tsx +4 -0
package/README.md
CHANGED
|
@@ -192,6 +192,27 @@ Without `fallback`, no `<Suspense>` boundary is added. The prop is optional.
|
|
|
192
192
|
|
|
193
193
|
> **Note:** `keepAlive` is not supported. Solid has no equivalent of React's `<Activity>` API. Components dispose completely when navigating away.
|
|
194
194
|
|
|
195
|
+
### `<RouterErrorBoundary>`
|
|
196
|
+
|
|
197
|
+
Declarative error handling for navigation errors. Shows a fallback **alongside** children (not instead of) when a guard rejects or a route is not found.
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import { RouterErrorBoundary } from "@real-router/solid";
|
|
201
|
+
|
|
202
|
+
<RouterErrorBoundary
|
|
203
|
+
fallback={(error, resetError) => (
|
|
204
|
+
<div class="toast">
|
|
205
|
+
{error.code} <button onClick={resetError}>Dismiss</button>
|
|
206
|
+
</div>
|
|
207
|
+
)}
|
|
208
|
+
onError={(error) => analytics.track("nav_error", { code: error.code })}
|
|
209
|
+
>
|
|
210
|
+
<Link routeName="protected">Go to Protected</Link>
|
|
211
|
+
</RouterErrorBoundary>;
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Auto-resets on next successful navigation. Works with both `<Link>` and imperative `router.navigate()`.
|
|
215
|
+
|
|
195
216
|
## Directives
|
|
196
217
|
|
|
197
218
|
### `use:link`
|
|
@@ -292,7 +313,7 @@ When enabled, a visually hidden `aria-live` region announces each navigation. Fo
|
|
|
292
313
|
|
|
293
314
|
Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
|
|
294
315
|
|
|
295
|
-
- [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [Link](https://github.com/greydragon888/real-router/wiki/Link)
|
|
316
|
+
- [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link)
|
|
296
317
|
- [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator) · [useRouteUtils](https://github.com/greydragon888/real-router/wiki/useRouteUtils) · [useRouterTransition](https://github.com/greydragon888/real-router/wiki/useRouterTransition)
|
|
297
318
|
|
|
298
319
|
## Examples
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as solid_js from 'solid-js';
|
|
2
2
|
import { JSX, Accessor, ParentProps } from 'solid-js';
|
|
3
3
|
import * as _real_router_core from '@real-router/core';
|
|
4
|
-
import { Params, NavigationOptions, State, Router, Navigator } from '@real-router/core';
|
|
4
|
+
import { Params, NavigationOptions, State, RouterError, Router, Navigator } from '@real-router/core';
|
|
5
5
|
export { Navigator } from '@real-router/core';
|
|
6
6
|
import { RouteUtils } from '@real-router/route-utils';
|
|
7
7
|
import { RouterTransitionSnapshot, RouterSource } from '@real-router/sources';
|
|
@@ -56,6 +56,13 @@ interface LinkProps<P extends Params = Params> extends Omit<JSX.HTMLAttributes<H
|
|
|
56
56
|
|
|
57
57
|
declare function Link<P extends Params = Params>(props: Readonly<LinkProps<P>>): JSX.Element;
|
|
58
58
|
|
|
59
|
+
interface RouterErrorBoundaryProps {
|
|
60
|
+
readonly children: JSX.Element;
|
|
61
|
+
readonly fallback: (error: RouterError, resetError: () => void) => JSX.Element;
|
|
62
|
+
readonly onError?: (error: RouterError, toRoute: State | null, fromRoute: State | null) => void;
|
|
63
|
+
}
|
|
64
|
+
declare function RouterErrorBoundary(props: RouterErrorBoundaryProps): JSX.Element;
|
|
65
|
+
|
|
59
66
|
interface LinkDirectiveOptions<P extends Params = Params> {
|
|
60
67
|
routeName: string;
|
|
61
68
|
routeParams?: P;
|
|
@@ -100,5 +107,5 @@ declare function createSignalFromSource<T>(source: RouterSource<T>): Accessor<T>
|
|
|
100
107
|
|
|
101
108
|
declare function createStoreFromSource<T extends object>(source: RouterSource<T>): T;
|
|
102
109
|
|
|
103
|
-
export { Link, RouteContext, RouteView, RouterContext, RouterProvider, createSignalFromSource, createStoreFromSource, link, useNavigator, useRoute, useRouteNode, useRouteNodeStore, useRouteStore, useRouteUtils, useRouter, useRouterTransition };
|
|
104
|
-
export type { LinkDirectiveOptions, LinkProps, RouteState, MatchProps as RouteViewMatchProps, NotFoundProps as RouteViewNotFoundProps, RouteViewProps };
|
|
110
|
+
export { Link, RouteContext, RouteView, RouterContext, RouterErrorBoundary, RouterProvider, createSignalFromSource, createStoreFromSource, link, useNavigator, useRoute, useRouteNode, useRouteNodeStore, useRouteStore, useRouteUtils, useRouter, useRouterTransition };
|
|
111
|
+
export type { LinkDirectiveOptions, LinkProps, RouteState, MatchProps as RouteViewMatchProps, NotFoundProps as RouteViewNotFoundProps, RouteViewProps, RouterErrorBoundaryProps };
|
package/dist/cjs/index.js
CHANGED
|
@@ -208,6 +208,37 @@ function Link(props) {
|
|
|
208
208
|
})();
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
const cache = new WeakMap();
|
|
212
|
+
function useRouterError() {
|
|
213
|
+
const router = useRouter();
|
|
214
|
+
let source = cache.get(router);
|
|
215
|
+
if (!source) {
|
|
216
|
+
source = sources.createErrorSource(router);
|
|
217
|
+
cache.set(router, source);
|
|
218
|
+
}
|
|
219
|
+
return createSignalFromSource(source);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function RouterErrorBoundary(props) {
|
|
223
|
+
const snapshot = useRouterError();
|
|
224
|
+
const [dismissedVersion, setDismissedVersion] = solidJs.createSignal(-1);
|
|
225
|
+
solidJs.createEffect(() => {
|
|
226
|
+
const snap = snapshot();
|
|
227
|
+
if (snap.error) {
|
|
228
|
+
props.onError?.(snap.error, snap.toRoute, snap.fromRoute);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
const visibleError = solidJs.createMemo(() => {
|
|
232
|
+
const snap = snapshot();
|
|
233
|
+
return snap.version > dismissedVersion() ? snap.error : null;
|
|
234
|
+
});
|
|
235
|
+
const resetError = () => setDismissedVersion(snapshot().version);
|
|
236
|
+
return [web.memo(() => props.children), web.memo(() => {
|
|
237
|
+
const error = visibleError();
|
|
238
|
+
return error ? props.fallback(error, resetError) : null;
|
|
239
|
+
})];
|
|
240
|
+
}
|
|
241
|
+
|
|
211
242
|
function link(element, accessor) {
|
|
212
243
|
const router = useRouter();
|
|
213
244
|
const options = accessor();
|
|
@@ -337,6 +368,7 @@ exports.Link = Link;
|
|
|
337
368
|
exports.RouteContext = RouteContext;
|
|
338
369
|
exports.RouteView = RouteView;
|
|
339
370
|
exports.RouterContext = RouterContext;
|
|
371
|
+
exports.RouterErrorBoundary = RouterErrorBoundary;
|
|
340
372
|
exports.RouterProvider = RouterProvider;
|
|
341
373
|
exports.createSignalFromSource = createSignalFromSource;
|
|
342
374
|
exports.createStoreFromSource = createStoreFromSource;
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as solid_js from 'solid-js';
|
|
2
2
|
import { JSX, Accessor, ParentProps } from 'solid-js';
|
|
3
3
|
import * as _real_router_core from '@real-router/core';
|
|
4
|
-
import { Params, NavigationOptions, State, Router, Navigator } from '@real-router/core';
|
|
4
|
+
import { Params, NavigationOptions, State, RouterError, Router, Navigator } from '@real-router/core';
|
|
5
5
|
export { Navigator } from '@real-router/core';
|
|
6
6
|
import { RouteUtils } from '@real-router/route-utils';
|
|
7
7
|
import { RouterTransitionSnapshot, RouterSource } from '@real-router/sources';
|
|
@@ -56,6 +56,13 @@ interface LinkProps<P extends Params = Params> extends Omit<JSX.HTMLAttributes<H
|
|
|
56
56
|
|
|
57
57
|
declare function Link<P extends Params = Params>(props: Readonly<LinkProps<P>>): JSX.Element;
|
|
58
58
|
|
|
59
|
+
interface RouterErrorBoundaryProps {
|
|
60
|
+
readonly children: JSX.Element;
|
|
61
|
+
readonly fallback: (error: RouterError, resetError: () => void) => JSX.Element;
|
|
62
|
+
readonly onError?: (error: RouterError, toRoute: State | null, fromRoute: State | null) => void;
|
|
63
|
+
}
|
|
64
|
+
declare function RouterErrorBoundary(props: RouterErrorBoundaryProps): JSX.Element;
|
|
65
|
+
|
|
59
66
|
interface LinkDirectiveOptions<P extends Params = Params> {
|
|
60
67
|
routeName: string;
|
|
61
68
|
routeParams?: P;
|
|
@@ -100,5 +107,5 @@ declare function createSignalFromSource<T>(source: RouterSource<T>): Accessor<T>
|
|
|
100
107
|
|
|
101
108
|
declare function createStoreFromSource<T extends object>(source: RouterSource<T>): T;
|
|
102
109
|
|
|
103
|
-
export { Link, RouteContext, RouteView, RouterContext, RouterProvider, createSignalFromSource, createStoreFromSource, link, useNavigator, useRoute, useRouteNode, useRouteNodeStore, useRouteStore, useRouteUtils, useRouter, useRouterTransition };
|
|
104
|
-
export type { LinkDirectiveOptions, LinkProps, RouteState, MatchProps as RouteViewMatchProps, NotFoundProps as RouteViewNotFoundProps, RouteViewProps };
|
|
110
|
+
export { Link, RouteContext, RouteView, RouterContext, RouterErrorBoundary, RouterProvider, createSignalFromSource, createStoreFromSource, link, useNavigator, useRoute, useRouteNode, useRouteNodeStore, useRouteStore, useRouteUtils, useRouter, useRouterTransition };
|
|
111
|
+
export type { LinkDirectiveOptions, LinkProps, RouteState, MatchProps as RouteViewMatchProps, NotFoundProps as RouteViewNotFoundProps, RouteViewProps, RouterErrorBoundaryProps };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createComponent, memo, spread, mergeProps as mergeProps$1, insert, template } from 'solid-js/web';
|
|
2
|
-
import { createRouteNodeSource, createActiveRouteSource, createRouteSource, createTransitionSource } from '@real-router/sources';
|
|
2
|
+
import { createRouteNodeSource, createActiveRouteSource, createErrorSource, createRouteSource, createTransitionSource } from '@real-router/sources';
|
|
3
3
|
import { Suspense, createSignal, onCleanup, createContext, useContext, children, mergeProps, splitProps, createMemo, createEffect, onMount, createSelector } from 'solid-js';
|
|
4
4
|
import { getPluginApi } from '@real-router/core/api';
|
|
5
5
|
import { startsWithSegment, getRouteUtils } from '@real-router/route-utils';
|
|
@@ -206,6 +206,37 @@ function Link(props) {
|
|
|
206
206
|
})();
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
const cache = new WeakMap();
|
|
210
|
+
function useRouterError() {
|
|
211
|
+
const router = useRouter();
|
|
212
|
+
let source = cache.get(router);
|
|
213
|
+
if (!source) {
|
|
214
|
+
source = createErrorSource(router);
|
|
215
|
+
cache.set(router, source);
|
|
216
|
+
}
|
|
217
|
+
return createSignalFromSource(source);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function RouterErrorBoundary(props) {
|
|
221
|
+
const snapshot = useRouterError();
|
|
222
|
+
const [dismissedVersion, setDismissedVersion] = createSignal(-1);
|
|
223
|
+
createEffect(() => {
|
|
224
|
+
const snap = snapshot();
|
|
225
|
+
if (snap.error) {
|
|
226
|
+
props.onError?.(snap.error, snap.toRoute, snap.fromRoute);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
const visibleError = createMemo(() => {
|
|
230
|
+
const snap = snapshot();
|
|
231
|
+
return snap.version > dismissedVersion() ? snap.error : null;
|
|
232
|
+
});
|
|
233
|
+
const resetError = () => setDismissedVersion(snapshot().version);
|
|
234
|
+
return [memo(() => props.children), memo(() => {
|
|
235
|
+
const error = visibleError();
|
|
236
|
+
return error ? props.fallback(error, resetError) : null;
|
|
237
|
+
})];
|
|
238
|
+
}
|
|
239
|
+
|
|
209
240
|
function link(element, accessor) {
|
|
210
241
|
const router = useRouter();
|
|
211
242
|
const options = accessor();
|
|
@@ -331,4 +362,4 @@ function RouterProvider(props) {
|
|
|
331
362
|
});
|
|
332
363
|
}
|
|
333
364
|
|
|
334
|
-
export { Link, RouteContext, RouteView, RouterContext, RouterProvider, createSignalFromSource, createStoreFromSource, link, useNavigator, useRoute, useRouteNode, useRouteNodeStore, useRouteStore, useRouteUtils, useRouter, useRouterTransition };
|
|
365
|
+
export { Link, RouteContext, RouteView, RouterContext, RouterErrorBoundary, RouterProvider, createSignalFromSource, createStoreFromSource, link, useNavigator, useRoute, useRouteNode, useRouteNodeStore, useRouteStore, useRouteUtils, useRouter, useRouterTransition };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RouterError, State } from "@real-router/core";
|
|
2
|
+
import type { JSX } from "solid-js";
|
|
3
|
+
export interface RouterErrorBoundaryProps {
|
|
4
|
+
readonly children: JSX.Element;
|
|
5
|
+
readonly fallback: (error: RouterError, resetError: () => void) => JSX.Element;
|
|
6
|
+
readonly onError?: (error: RouterError, toRoute: State | null, fromRoute: State | null) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function RouterErrorBoundary(props: RouterErrorBoundaryProps): JSX.Element;
|
|
9
|
+
//# sourceMappingURL=RouterErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouterErrorBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/RouterErrorBoundary.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,CACjB,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,IAAI,KACnB,GAAG,CAAC,OAAO,CAAC;IACjB,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,KAAK,GAAG,IAAI,EACrB,SAAS,EAAE,KAAK,GAAG,IAAI,KACpB,IAAI,CAAC;CACX;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,GAAG,CAAC,OAAO,CA8Bb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRouterError.d.ts","sourceRoot":"","sources":["../../../src/hooks/useRouterError.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAIzC,wBAAgB,cAAc,IAAI,QAAQ,CAAC,mBAAmB,CAAC,CAW9D"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { RouteView } from "./components/RouteView";
|
|
2
2
|
export { Link } from "./components/Link";
|
|
3
|
+
export { RouterErrorBoundary } from "./components/RouterErrorBoundary";
|
|
3
4
|
export { link } from "./directives/link";
|
|
4
5
|
export { useRouter } from "./hooks/useRouter";
|
|
5
6
|
export { useNavigator } from "./hooks/useNavigator";
|
|
@@ -14,6 +15,7 @@ export { RouterContext, RouteContext } from "./context";
|
|
|
14
15
|
export { createSignalFromSource } from "./createSignalFromSource";
|
|
15
16
|
export { createStoreFromSource } from "./createStoreFromSource";
|
|
16
17
|
export type { LinkProps, RouteState } from "./types";
|
|
18
|
+
export type { RouterErrorBoundaryProps } from "./components/RouterErrorBoundary";
|
|
17
19
|
export type { LinkDirectiveOptions } from "./directives/link";
|
|
18
20
|
export type { RouteViewProps, RouteViewMatchProps, RouteViewNotFoundProps, } from "./components/RouteView";
|
|
19
21
|
export type { Navigator } from "@real-router/core";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErD,YAAY,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAEjF,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/solid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "Solid.js integration for Real-Router",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
"license": "MIT",
|
|
52
52
|
"sideEffects": false,
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@real-router/core": "^0.39.0",
|
|
55
54
|
"@real-router/route-utils": "^0.1.6",
|
|
56
|
-
"@real-router/
|
|
57
|
-
"
|
|
55
|
+
"@real-router/core": "^0.40.1",
|
|
56
|
+
"@real-router/sources": "^0.3.0",
|
|
57
|
+
"dom-utils": "^0.2.2"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@babel/core": "7.29.0",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"solid-js": "1.9.5",
|
|
73
73
|
"vite-plugin-solid": "2.11.11",
|
|
74
74
|
"vitest": "4.1.0",
|
|
75
|
-
"@real-router/browser-plugin": "^0.10.
|
|
75
|
+
"@real-router/browser-plugin": "^0.10.6"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
78
|
"solid-js": ">=1.7.0"
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"type-check": "tsc --noEmit",
|
|
85
85
|
"lint": "eslint --cache --ext .ts,.tsx src/ tests/ --fix --max-warnings 0",
|
|
86
86
|
"lint:package": "publint",
|
|
87
|
-
"lint:types": "attw --pack ."
|
|
87
|
+
"lint:types": "attw --pack .",
|
|
88
|
+
"build:dist-only": "rimraf dist && tsc -p tsconfig.build.json && rollup -c rollup.config.mjs"
|
|
88
89
|
}
|
|
89
90
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createEffect, createMemo, createSignal } from "solid-js";
|
|
2
|
+
|
|
3
|
+
import { useRouterError } from "../hooks/useRouterError";
|
|
4
|
+
|
|
5
|
+
import type { RouterError, State } from "@real-router/core";
|
|
6
|
+
import type { JSX } from "solid-js";
|
|
7
|
+
|
|
8
|
+
export interface RouterErrorBoundaryProps {
|
|
9
|
+
readonly children: JSX.Element;
|
|
10
|
+
readonly fallback: (
|
|
11
|
+
error: RouterError,
|
|
12
|
+
resetError: () => void,
|
|
13
|
+
) => JSX.Element;
|
|
14
|
+
readonly onError?: (
|
|
15
|
+
error: RouterError,
|
|
16
|
+
toRoute: State | null,
|
|
17
|
+
fromRoute: State | null,
|
|
18
|
+
) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function RouterErrorBoundary(
|
|
22
|
+
props: RouterErrorBoundaryProps,
|
|
23
|
+
): JSX.Element {
|
|
24
|
+
const snapshot = useRouterError();
|
|
25
|
+
const [dismissedVersion, setDismissedVersion] = createSignal(-1);
|
|
26
|
+
|
|
27
|
+
createEffect(() => {
|
|
28
|
+
const snap = snapshot();
|
|
29
|
+
|
|
30
|
+
if (snap.error) {
|
|
31
|
+
props.onError?.(snap.error, snap.toRoute, snap.fromRoute);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const visibleError = createMemo(() => {
|
|
36
|
+
const snap = snapshot();
|
|
37
|
+
|
|
38
|
+
return snap.version > dismissedVersion() ? snap.error : null;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const resetError = () => setDismissedVersion(snapshot().version);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
{props.children}
|
|
46
|
+
{(() => {
|
|
47
|
+
const error = visibleError();
|
|
48
|
+
|
|
49
|
+
return error ? props.fallback(error, resetError) : null;
|
|
50
|
+
})()}
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createErrorSource } from "@real-router/sources";
|
|
2
|
+
|
|
3
|
+
import { createSignalFromSource } from "../createSignalFromSource";
|
|
4
|
+
import { useRouter } from "./useRouter";
|
|
5
|
+
|
|
6
|
+
import type { Router } from "@real-router/core";
|
|
7
|
+
import type { RouterErrorSnapshot, RouterSource } from "@real-router/sources";
|
|
8
|
+
import type { Accessor } from "solid-js";
|
|
9
|
+
|
|
10
|
+
const cache = new WeakMap<Router, RouterSource<RouterErrorSnapshot>>();
|
|
11
|
+
|
|
12
|
+
export function useRouterError(): Accessor<RouterErrorSnapshot> {
|
|
13
|
+
const router = useRouter();
|
|
14
|
+
|
|
15
|
+
let source = cache.get(router);
|
|
16
|
+
|
|
17
|
+
if (!source) {
|
|
18
|
+
source = createErrorSource(router);
|
|
19
|
+
cache.set(router, source);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return createSignalFromSource(source);
|
|
23
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -2,6 +2,8 @@ export { RouteView } from "./components/RouteView";
|
|
|
2
2
|
|
|
3
3
|
export { Link } from "./components/Link";
|
|
4
4
|
|
|
5
|
+
export { RouterErrorBoundary } from "./components/RouterErrorBoundary";
|
|
6
|
+
|
|
5
7
|
export { link } from "./directives/link";
|
|
6
8
|
|
|
7
9
|
export { useRouter } from "./hooks/useRouter";
|
|
@@ -30,6 +32,8 @@ export { createStoreFromSource } from "./createStoreFromSource";
|
|
|
30
32
|
|
|
31
33
|
export type { LinkProps, RouteState } from "./types";
|
|
32
34
|
|
|
35
|
+
export type { RouterErrorBoundaryProps } from "./components/RouterErrorBoundary";
|
|
36
|
+
|
|
33
37
|
export type { LinkDirectiveOptions } from "./directives/link";
|
|
34
38
|
|
|
35
39
|
export type {
|