@real-router/svelte 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 +25 -1
- package/dist/components/RouterErrorBoundary.svelte +47 -0
- package/dist/components/RouterErrorBoundary.svelte.d.ts +10 -0
- package/dist/composables/useRouterError.svelte.d.ts +4 -0
- package/dist/composables/useRouterError.svelte.js +13 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/package.json +7 -6
- package/src/components/RouterErrorBoundary.svelte +47 -0
- package/src/composables/useRouterError.svelte.ts +21 -0
- package/src/index.ts +6 -1
package/README.md
CHANGED
|
@@ -196,6 +196,30 @@ Snippet names must be valid JavaScript identifiers and match the first segment o
|
|
|
196
196
|
|
|
197
197
|
> **Note:** `keepAlive` is not supported. Svelte has no equivalent of React's `<Activity>` API or Vue's `<KeepAlive>`. Components are destroyed when navigating away.
|
|
198
198
|
|
|
199
|
+
### `<RouterErrorBoundary>`
|
|
200
|
+
|
|
201
|
+
Declarative error handling for navigation errors. Shows a fallback **alongside** children (not instead of) when a guard rejects or a route is not found.
|
|
202
|
+
|
|
203
|
+
```svelte
|
|
204
|
+
<script lang="ts">
|
|
205
|
+
import { RouterErrorBoundary } from "@real-router/svelte";
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<RouterErrorBoundary
|
|
209
|
+
onError={(error) => analytics.track("nav_error", { code: error.code })}
|
|
210
|
+
>
|
|
211
|
+
{#snippet fallback(error, resetError)}
|
|
212
|
+
<div class="toast">
|
|
213
|
+
{error.code} <button onclick={resetError}>Dismiss</button>
|
|
214
|
+
</div>
|
|
215
|
+
{/snippet}
|
|
216
|
+
|
|
217
|
+
<Link routeName="protected">Go to Protected</Link>
|
|
218
|
+
</RouterErrorBoundary>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Auto-resets on next successful navigation. Works with both `<Link>` and imperative `router.navigate()`.
|
|
222
|
+
|
|
199
223
|
## Actions
|
|
200
224
|
|
|
201
225
|
### `createLinkAction`
|
|
@@ -334,7 +358,7 @@ When enabled, a visually hidden `aria-live` region announces each navigation. Fo
|
|
|
334
358
|
|
|
335
359
|
Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
|
|
336
360
|
|
|
337
|
-
- [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)
|
|
361
|
+
- [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)
|
|
338
362
|
- [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)
|
|
339
363
|
|
|
340
364
|
## Examples
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { untrack } from "svelte";
|
|
3
|
+
|
|
4
|
+
import { useRouterError } from "../composables/useRouterError.svelte";
|
|
5
|
+
|
|
6
|
+
import type { RouterError, State } from "@real-router/core";
|
|
7
|
+
import type { Snippet } from "svelte";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
children: Snippet;
|
|
11
|
+
fallback: Snippet<[RouterError, () => void]>;
|
|
12
|
+
onError?: (
|
|
13
|
+
error: RouterError,
|
|
14
|
+
toRoute: State | null,
|
|
15
|
+
fromRoute: State | null,
|
|
16
|
+
) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let { children, fallback, onError }: Props = $props();
|
|
20
|
+
|
|
21
|
+
const snapshot = useRouterError();
|
|
22
|
+
let dismissedVersion = $state(-1);
|
|
23
|
+
|
|
24
|
+
const visibleError = $derived(
|
|
25
|
+
snapshot.current.version > dismissedVersion
|
|
26
|
+
? snapshot.current.error
|
|
27
|
+
: null,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
function resetError(): void {
|
|
31
|
+
dismissedVersion = snapshot.current.version;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
$effect(() => {
|
|
35
|
+
if (snapshot.current.error) {
|
|
36
|
+
const { error, toRoute, fromRoute } = snapshot.current;
|
|
37
|
+
untrack(() => {
|
|
38
|
+
onError?.(error, toRoute, fromRoute);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{@render children?.()}
|
|
45
|
+
{#if visibleError}
|
|
46
|
+
{@render fallback(visibleError, resetError)}
|
|
47
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RouterError, State } from "@real-router/core";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
interface Props {
|
|
4
|
+
children: Snippet;
|
|
5
|
+
fallback: Snippet<[RouterError, () => void]>;
|
|
6
|
+
onError?: (error: RouterError, toRoute: State | null, fromRoute: State | null) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const RouterErrorBoundary: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type RouterErrorBoundary = ReturnType<typeof RouterErrorBoundary>;
|
|
10
|
+
export default RouterErrorBoundary;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createErrorSource } from "@real-router/sources";
|
|
2
|
+
import { createReactiveSource } from "../createReactiveSource.svelte";
|
|
3
|
+
import { useRouter } from "./useRouter.svelte";
|
|
4
|
+
const cache = new WeakMap();
|
|
5
|
+
export function useRouterError() {
|
|
6
|
+
const router = useRouter();
|
|
7
|
+
let source = cache.get(router);
|
|
8
|
+
if (!source) {
|
|
9
|
+
source = createErrorSource(router);
|
|
10
|
+
cache.set(router, source);
|
|
11
|
+
}
|
|
12
|
+
return createReactiveSource(source);
|
|
13
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as RouteView } from "./components/RouteView.svelte";
|
|
2
2
|
export { default as Link } from "./components/Link.svelte";
|
|
3
3
|
export { default as Lazy } from "./components/Lazy.svelte";
|
|
4
|
+
export { default as RouterErrorBoundary } from "./components/RouterErrorBoundary.svelte";
|
|
4
5
|
export { createReactiveSource } from "./createReactiveSource.svelte";
|
|
5
6
|
export { useRouter } from "./composables/useRouter.svelte";
|
|
6
7
|
export { useNavigator } from "./composables/useNavigator.svelte";
|
|
@@ -14,4 +15,4 @@ export { default as RouterProvider } from "./RouterProvider.svelte";
|
|
|
14
15
|
export { ROUTER_KEY, NAVIGATOR_KEY, ROUTE_KEY } from "./context";
|
|
15
16
|
export type { LinkProps, RouteContext } from "./types";
|
|
16
17
|
export type { Navigator } from "@real-router/core";
|
|
17
|
-
export type { RouterTransitionSnapshot } from "@real-router/sources";
|
|
18
|
+
export type { RouterTransitionSnapshot, RouterErrorSnapshot, } from "@real-router/sources";
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export { default as RouteView } from "./components/RouteView.svelte";
|
|
3
3
|
export { default as Link } from "./components/Link.svelte";
|
|
4
4
|
export { default as Lazy } from "./components/Lazy.svelte";
|
|
5
|
+
export { default as RouterErrorBoundary } from "./components/RouterErrorBoundary.svelte";
|
|
5
6
|
// Reactive Primitives
|
|
6
7
|
export { createReactiveSource } from "./createReactiveSource.svelte";
|
|
7
8
|
// Composables
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Svelte 5 integration for Real-Router",
|
|
6
6
|
"svelte": "./dist/index.js",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"sideEffects": false,
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@real-router/core": "^0.
|
|
47
|
+
"@real-router/core": "^0.40.1",
|
|
48
48
|
"@real-router/route-utils": "^0.1.6",
|
|
49
|
-
"@real-router/sources": "^0.
|
|
50
|
-
"dom-utils": "^0.2.
|
|
49
|
+
"@real-router/sources": "^0.3.0",
|
|
50
|
+
"dom-utils": "^0.2.2"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@sveltejs/package": "2.5.7",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"svelte": "5.54.0",
|
|
60
60
|
"svelte-check": "4.4.5",
|
|
61
61
|
"svelte-eslint-parser": "1.6.0",
|
|
62
|
-
"@real-router/browser-plugin": "^0.10.
|
|
62
|
+
"@real-router/browser-plugin": "^0.10.6"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"svelte": ">=5.7.0"
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"test": "vitest",
|
|
70
70
|
"test:stress": "vitest run --config vitest.config.stress.mts",
|
|
71
71
|
"type-check": "svelte-check --tsconfig ./tsconfig.json",
|
|
72
|
-
"lint": "eslint --cache src/ tests/ --fix --max-warnings 0"
|
|
72
|
+
"lint": "eslint --cache src/ tests/ --fix --max-warnings 0",
|
|
73
|
+
"build:dist-only": "svelte-package -i src -o dist"
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { untrack } from "svelte";
|
|
3
|
+
|
|
4
|
+
import { useRouterError } from "../composables/useRouterError.svelte";
|
|
5
|
+
|
|
6
|
+
import type { RouterError, State } from "@real-router/core";
|
|
7
|
+
import type { Snippet } from "svelte";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
children: Snippet;
|
|
11
|
+
fallback: Snippet<[RouterError, () => void]>;
|
|
12
|
+
onError?: (
|
|
13
|
+
error: RouterError,
|
|
14
|
+
toRoute: State | null,
|
|
15
|
+
fromRoute: State | null,
|
|
16
|
+
) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let { children, fallback, onError }: Props = $props();
|
|
20
|
+
|
|
21
|
+
const snapshot = useRouterError();
|
|
22
|
+
let dismissedVersion = $state(-1);
|
|
23
|
+
|
|
24
|
+
const visibleError = $derived(
|
|
25
|
+
snapshot.current.version > dismissedVersion
|
|
26
|
+
? snapshot.current.error
|
|
27
|
+
: null,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
function resetError(): void {
|
|
31
|
+
dismissedVersion = snapshot.current.version;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
$effect(() => {
|
|
35
|
+
if (snapshot.current.error) {
|
|
36
|
+
const { error, toRoute, fromRoute } = snapshot.current;
|
|
37
|
+
untrack(() => {
|
|
38
|
+
onError?.(error, toRoute, fromRoute);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{@render children?.()}
|
|
45
|
+
{#if visibleError}
|
|
46
|
+
{@render fallback(visibleError, resetError)}
|
|
47
|
+
{/if}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createErrorSource } from "@real-router/sources";
|
|
2
|
+
|
|
3
|
+
import { createReactiveSource } from "../createReactiveSource.svelte";
|
|
4
|
+
import { useRouter } from "./useRouter.svelte";
|
|
5
|
+
|
|
6
|
+
import type { Router } from "@real-router/core";
|
|
7
|
+
import type { RouterErrorSnapshot, RouterSource } from "@real-router/sources";
|
|
8
|
+
|
|
9
|
+
const cache = new WeakMap<Router, RouterSource<RouterErrorSnapshot>>();
|
|
10
|
+
|
|
11
|
+
export function useRouterError(): { readonly current: RouterErrorSnapshot } {
|
|
12
|
+
const router = useRouter();
|
|
13
|
+
|
|
14
|
+
let source = cache.get(router);
|
|
15
|
+
if (!source) {
|
|
16
|
+
source = createErrorSource(router);
|
|
17
|
+
cache.set(router, source);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return createReactiveSource(source);
|
|
21
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,8 @@ export { default as Link } from "./components/Link.svelte";
|
|
|
5
5
|
|
|
6
6
|
export { default as Lazy } from "./components/Lazy.svelte";
|
|
7
7
|
|
|
8
|
+
export { default as RouterErrorBoundary } from "./components/RouterErrorBoundary.svelte";
|
|
9
|
+
|
|
8
10
|
// Reactive Primitives
|
|
9
11
|
export { createReactiveSource } from "./createReactiveSource.svelte";
|
|
10
12
|
|
|
@@ -36,4 +38,7 @@ export type { LinkProps, RouteContext } from "./types";
|
|
|
36
38
|
|
|
37
39
|
export type { Navigator } from "@real-router/core";
|
|
38
40
|
|
|
39
|
-
export type {
|
|
41
|
+
export type {
|
|
42
|
+
RouterTransitionSnapshot,
|
|
43
|
+
RouterErrorSnapshot,
|
|
44
|
+
} from "@real-router/sources";
|