svelte-spa-history-router 2.2.0 → 3.0.0-next.2

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 (78) hide show
  1. package/.vscode/extensions.json +3 -0
  2. package/README.md +72 -36
  3. package/example/App.svelte +117 -0
  4. package/{examples/app-svelte5 → example}/index.html +4 -5
  5. package/example/lib/getArticle.ts +13 -0
  6. package/example/lib/getArticles.ts +43 -0
  7. package/example/main.ts +8 -0
  8. package/{examples/app-svelte5/src → example}/pages/Admin.svelte +1 -0
  9. package/example/pages/Blog.svelte +19 -0
  10. package/example/pages/BlogPost.svelte +23 -0
  11. package/example/pages/IntParam.svelte +14 -0
  12. package/example/pages/Message.svelte +9 -0
  13. package/example/pages/Params.svelte +13 -0
  14. package/{examples/app-svelte4/src → example/pages}/Query.svelte +4 -3
  15. package/example/pages/Top.svelte +7 -0
  16. package/example/types.ts +9 -0
  17. package/package.json +16 -12
  18. package/playwright-report/index.html +71 -0
  19. package/src/Router.svelte +104 -75
  20. package/src/currentURL.ts +9 -0
  21. package/src/index.ts +7 -0
  22. package/src/{link.js → link.ts} +4 -7
  23. package/src/push.ts +18 -0
  24. package/src/redirect.ts +9 -0
  25. package/src/spa-context.ts +15 -0
  26. package/src/spa-event.ts +1 -0
  27. package/src/types.ts +28 -32
  28. package/test-results/.last-run.json +4 -0
  29. package/tests/e2e.spec.ts +133 -0
  30. package/tsconfig.app.json +27 -0
  31. package/tsconfig.json +7 -0
  32. package/tsconfig.node.json +24 -0
  33. package/{examples/app-svelte5/vite.config.js → vite.config.ts} +3 -2
  34. package/examples/app-svelte4/dist/Article.js +0 -286
  35. package/examples/app-svelte4/dist/Article.js.map +0 -1
  36. package/examples/app-svelte4/dist/Login.js +0 -214
  37. package/examples/app-svelte4/dist/Login.js.map +0 -1
  38. package/examples/app-svelte4/dist/Query.js +0 -143
  39. package/examples/app-svelte4/dist/Query.js.map +0 -1
  40. package/examples/app-svelte4/dist/index.html +0 -11
  41. package/examples/app-svelte4/dist/main.js +0 -2
  42. package/examples/app-svelte4/dist/main.js.map +0 -1
  43. package/examples/app-svelte4/dist/main2.js +0 -2479
  44. package/examples/app-svelte4/dist/main2.js.map +0 -1
  45. package/examples/app-svelte4/package-lock.json +0 -845
  46. package/examples/app-svelte4/package.json +0 -23
  47. package/examples/app-svelte4/rollup.config.js +0 -56
  48. package/examples/app-svelte4/server.js +0 -115
  49. package/examples/app-svelte4/src/Admin.svelte +0 -3
  50. package/examples/app-svelte4/src/App.svelte +0 -56
  51. package/examples/app-svelte4/src/Article.svelte +0 -21
  52. package/examples/app-svelte4/src/Home.svelte +0 -28
  53. package/examples/app-svelte4/src/Login.svelte +0 -21
  54. package/examples/app-svelte4/src/data-source.js +0 -49
  55. package/examples/app-svelte4/src/main.js +0 -7
  56. package/examples/app-svelte4/src/store.js +0 -11
  57. package/examples/app-svelte4/tests/e2e.test.js +0 -129
  58. package/examples/app-svelte5/jsconfig.json +0 -17
  59. package/examples/app-svelte5/package-lock.json +0 -1258
  60. package/examples/app-svelte5/package.json +0 -23
  61. package/examples/app-svelte5/src/App.svelte +0 -65
  62. package/examples/app-svelte5/src/articles.js +0 -43
  63. package/examples/app-svelte5/src/main.js +0 -9
  64. package/examples/app-svelte5/src/pages/Blog.svelte +0 -18
  65. package/examples/app-svelte5/src/pages/Guide.svelte +0 -21
  66. package/examples/app-svelte5/src/pages/Home.svelte +0 -6
  67. package/examples/app-svelte5/src/pages/NotFound.svelte +0 -1
  68. package/examples/app-svelte5/src/pages/Post.svelte +0 -21
  69. package/examples/app-svelte5/svelte.config.js +0 -7
  70. package/examples/app-svelte5/tests/e2e.spec.js +0 -69
  71. package/jsconfig.json +0 -17
  72. package/src/index.d.ts +0 -48
  73. package/src/index.js +0 -19
  74. package/src/push.js +0 -19
  75. package/src/stores.js +0 -67
  76. /package/{examples/app-svelte4/src → example/pages}/NotFound.svelte +0 -0
  77. /package/{examples/app-svelte5/src → example}/vite-env.d.ts +0 -0
  78. /package/{examples/app-svelte5/playwright.config.js → playwright.config.js} +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["svelte.svelte-vscode"]
3
+ }
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  History base router for [Svelte](https://svelte.dev/) SPA (Single Page Application).
4
4
 
5
5
  > [!TIP]
6
- > The offcial routing library of Svelte is [SvelteKit](https://svelte.dev/docs/kit/introduction). This library is intented to be used for small project.
6
+ > The offcial routing library of Svelte is [SvelteKit](https://svelte.dev/docs/kit/introduction). This library is intented to be used for small/simple project.
7
7
 
8
8
 
9
9
  ## Features
@@ -52,17 +52,17 @@ For example:
52
52
  ```
53
53
 
54
54
  * `Routes` require a `routes` parameter.
55
- * `routes` is a list of route objects. route object has `path`, `component`, and `resolver` properties.
55
+ * `routes` is a list of route objects. route object has `path` property, and either `component` or `resolver` property.
56
56
 
57
57
  * `path` can be a regular expression. `^` and `$` are automatically added when matching.
58
- * `component` is a SvelteComponent. there are no specific requirements for component.
59
- * `resolver` is a function to determine component dynamically (optional).
58
+ * `component` is a Svelte component. there are no specific requirements for component.
59
+ * `resolver` is a function to determine component dynamically.
60
60
 
61
61
  * Matching is simply performed in the order defined by `routes`.
62
62
 
63
- ### routeParams
63
+ ### Path variable
64
64
 
65
- Matched paramaters is passed to component as `params` property.
65
+ Matched paramaters are passed to component as `params` property.
66
66
 
67
67
  For example:
68
68
 
@@ -70,7 +70,7 @@ For example:
70
70
  # Article.svelte
71
71
 
72
72
  <script lang="ts">
73
- let { params } = $props();
73
+ let { params }: { params: { postId: string } = $props();
74
74
 
75
75
  const postId = $derived(parseInt(params.postId));
76
76
  </script>
@@ -79,25 +79,11 @@ For example:
79
79
  </div>
80
80
  ```
81
81
 
82
- [Additional] For svelte4, `routeParams` is a store to contain matched value to current route.
83
-
84
- ```html
85
- # Article.svelte
86
-
87
- <script>
88
- import { routeParams } from 'svelte-spa-history-router';
89
- </script>
90
-
91
- <div class="article">
92
- postId: {$routeParams.postId}
93
- </div>
94
- ```
95
-
96
82
  ### Navigation methods
97
83
 
98
84
  To navigate another page, `link` and `push` are available.
99
85
 
100
- * `link` used with a `a` tag like below
86
+ * `link` is used with a `a` tag like below
101
87
 
102
88
  ```html
103
89
  import { link } from 'svelte-spa-history-router';
@@ -105,12 +91,12 @@ import { link } from 'svelte-spa-history-router';
105
91
  <a use:link href="/">Home</a>
106
92
  ```
107
93
 
108
- * `push` used to navigate programatically
94
+ * `push` is used to navigate programatically
109
95
 
110
96
  ```html
111
97
  import { push } from 'svelte-spa-history-router';
112
98
 
113
- <button on:click={ () => push('/') }>Go to Home</button>
99
+ <button onclick={ () => push('/') }>Go to Home</button>
114
100
  ```
115
101
 
116
102
  ### resolver
@@ -133,18 +119,16 @@ Example: code spliting (dynamic import)
133
119
  Example: dynamic routing and pass value to component props.
134
120
 
135
121
  ```html
136
- <script>
122
+ <script lang="ts">
137
123
  import { Router } from 'svelte-spa-history-router';
138
124
 
139
125
  import Article from "./Article.svelte";
140
126
  import NotFound from "./NotFound.svelte";
141
127
 
142
- async function prefetchArticle({ params, props }) {
128
+ async function prefetchArticle(params: Record<string, string>) {
143
129
  const article = await getArticle(params.postId);
144
130
  if (article) {
145
- // pass value to component props
146
- props.article = article;
147
- return Article;
131
+ return { component: Article, props: { article } };
148
132
  } else {
149
133
  return NotFound;
150
134
  }
@@ -160,13 +144,16 @@ Example: dynamic routing and pass value to component props.
160
144
  Example: guard
161
145
 
162
146
  ```html
163
- <script>
147
+ <script lang="ts">
164
148
  import { Router, redirect } from 'svelte-spa-history-router';
165
149
 
166
150
  import Admin from "./Admin.svelte";
167
151
 
168
- function adminGuard(route) {
169
- if (!isAdmin($user)) {
152
+
153
+ let user: User = $state()
154
+
155
+ function adminGuard() {
156
+ if (!isAdmin(user)) {
170
157
  return redirect("/");
171
158
  }
172
159
  return Admin;
@@ -182,20 +169,60 @@ Example: guard
182
169
 
183
170
  (Added in v2.0.0)
184
171
 
185
- ### currentURL
172
+ (Changed resolver interface in v3.0.0-next.1)
173
+
174
+ ### currentURL()
186
175
 
187
- store to detect URL changes (including query string or hash)
176
+ state to detect URL changes (including query string or hash)
188
177
 
189
178
  ```html
190
179
  <script>
191
180
  import { currentURL } from "svelte-spa-history-router";
192
181
 
193
- $: name = $currentURL.searchParams.get("name") || 'unknown';
182
+ let name = $derived(currentURL().searchParams.get("name") ?? "unknown");
194
183
  </script>
195
184
  <div>{ name }</div>
196
185
  ```
197
186
 
198
- (Added in 2.1.0)
187
+ (Added in v2.1.0)
188
+
189
+ (Replaced to svelte5 `$state()` in v3.0.0-next.1)
190
+
191
+ ### Typing
192
+
193
+ svelte-spa-history-router provides `Route` type to check combination of component and props.
194
+
195
+ ```typescript
196
+ <script lang="ts">
197
+ import type { Route } from "svelte-spa-history-router"
198
+
199
+ // BlogPost requires article property
200
+ import type BlogPost from "./pages/BlogPost.svelte"
201
+
202
+ import Top from "./pages/Top.svelte"
203
+
204
+ const routes: [
205
+ Route<typeof Top>,
206
+ Route<typeof BlogPost | typeof NotFound>,
207
+ ]: [
208
+ { path: "/", component: Top },
209
+ {
210
+ path: "/blog/posts/(?<slug>.*)",
211
+ resolver: async (params: Record<"slug", string>) => {
212
+ const article = await getArticle(params.slug);
213
+ if (article) {
214
+ const component = (await import("./pages/BlogPost.svelte")).default;
215
+ return { component, props: { article } }
216
+ } else {
217
+ return NotFound;
218
+ }
219
+ },
220
+ },
221
+ ];
222
+ </script>
223
+ ```
224
+
225
+ (Added in v3.0.0-next.1)
199
226
 
200
227
  ### Full example:
201
228
 
@@ -203,6 +230,15 @@ store to detect URL changes (including query string or hash)
203
230
 
204
231
  ## ChangeLog
205
232
 
233
+ ### 3.0.0-next.1
234
+
235
+ * *[Breaking change]* Drop Svelte4 support
236
+
237
+ * Remove stores of `routeParams` and `currentURL`
238
+
239
+ * *[Breaking change]* Change resolver interface
240
+ * Add `currentURL()` which is rewriten to use `$state()`
241
+
206
242
  ### 2.2.0
207
243
 
208
244
  * Support Svelte5
@@ -0,0 +1,117 @@
1
+ <script lang="ts">
2
+ import type { Route } from "svelte-spa-history-router"
3
+ import { Router, link, push, redirect } from "svelte-spa-history-router"
4
+
5
+ import type Admin from "./pages/Admin.svelte"
6
+ import type Blog from "./pages/Blog.svelte"
7
+ import type BlogPost from "./pages/BlogPost.svelte"
8
+ import type Query from "./pages/Query.svelte"
9
+
10
+ import IntParam from "./pages/IntParam.svelte"
11
+ import Message from "./pages/Message.svelte"
12
+ import NotFound from "./pages/NotFound.svelte"
13
+ import Params from "./pages/Params.svelte"
14
+ import Top from "./pages/Top.svelte"
15
+
16
+ import { getArticle } from "./lib/getArticle"
17
+
18
+
19
+ const routes: [
20
+ Route,
21
+ Route<typeof Params>,
22
+ Route<typeof IntParam>,
23
+ Route<typeof IntParam | typeof Message>,
24
+ Route<typeof Blog>,
25
+ Route<typeof BlogPost | typeof NotFound>,
26
+ Route<typeof Admin>,
27
+ Route<typeof Query>,
28
+ Route<typeof NotFound>,
29
+ ] = [
30
+ { path: "/", component: Top },
31
+ // path variable via params
32
+ { path: "/params/(?<slug>.*)", component: Params },
33
+ // typed props
34
+ {
35
+ path: "/int-param/(?<num>\\d+)",
36
+ resolver: (params: Record<"num", string>) => ({
37
+ component: IntParam,
38
+ props: { num: parseInt(params.num) }
39
+ }),
40
+ },
41
+ {
42
+ path: "/conditional/(?<arg>.+)",
43
+ resolver: (params: Record<"arg", string>) => {
44
+ const arg = parseInt(params.arg)
45
+ if (!Number.isNaN(arg)) {
46
+ return { component: IntParam, props: { num: arg }}
47
+ }
48
+ return {
49
+ component: Message,
50
+ props: { message: `Unexpected param: ${params.arg}` }
51
+ }
52
+ }
53
+ },
54
+ // spliting
55
+ {
56
+ path: "/blog",
57
+ resolver: () => import("./pages/Blog.svelte"),
58
+ },
59
+ // async resolver with props
60
+ // path variable with slash
61
+ // prefetch
62
+ // spliting
63
+ // return component
64
+ {
65
+ path: "/blog/posts/(?<slug>.*)",
66
+ resolver: async (params: Record<"slug", string>) => {
67
+ const article = await getArticle(params.slug);
68
+ if (article) {
69
+ const component = (await import("./pages/BlogPost.svelte")).default;
70
+ return { component, props: { article } }
71
+ } else {
72
+ return NotFound;
73
+ }
74
+ },
75
+ },
76
+ // guard
77
+ // redirect
78
+ {
79
+ path: "/admin",
80
+ resolver: () => {
81
+ if (user === "admin") {
82
+ return import("./pages/Admin.svelte");
83
+ } else {
84
+ return redirect("/");
85
+ }
86
+ },
87
+ },
88
+ {
89
+ path: "/query",
90
+ resolver: () => import("./pages/Query.svelte")
91
+ },
92
+ { path: ".*", component: NotFound },
93
+ ]
94
+
95
+ let user = $state("anonymous");
96
+ </script>
97
+ <main>
98
+ <header>
99
+ <nav>
100
+ <a use:link href="/">Top</a> |
101
+ <a use:link href="/params/foo/bar">params</a> |
102
+ <a use:link href="/int-param/3">int param</a> |
103
+ <a use:link href="/conditional/1">conditional (1)</a> |
104
+ <a use:link href="/conditional/a">conditional (a)</a> |
105
+ <a use:link href="/blog">blog</a> |
106
+ <a use:link href="/admin">admin</a> |
107
+ <a use:link href="/query">query</a> |
108
+
109
+ {#if user === "anonymous"}
110
+ <button id="login" onclick={() => { user = "admin" }}>Login</button>
111
+ {:else}
112
+ user: { user } <button onclick={() => { user = "anonymous"; push("/"); }}>Logout</button>
113
+ {/if}
114
+ </nav>
115
+ </header>
116
+ <Router {routes} />
117
+ </main>
@@ -1,14 +1,13 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>Vite + Svelte</title>
8
- <!--app-head-->
7
+ <title>Vite + Svelte + TS</title>
9
8
  </head>
10
9
  <body>
11
- <div id="app"><!--app-html--></div>
12
- <script type="module" src="/src/main.js"></script>
10
+ <div id="app"></div>
11
+ <script type="module" src="/main.ts"></script>
13
12
  </body>
14
13
  </html>
@@ -0,0 +1,13 @@
1
+ import type { Article } from "../types"
2
+
3
+ import { getArticles } from "./getArticles"
4
+
5
+
6
+ const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
7
+
8
+
9
+ export async function getArticle(id: string): Promise<Article | undefined> {
10
+ await sleep(50);
11
+ const articles = await getArticles();
12
+ return articles.find(a => a.id === id);
13
+ }
@@ -0,0 +1,43 @@
1
+ import type { Article } from "../types"
2
+
3
+
4
+ const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));
5
+
6
+
7
+ const articles: Article[] = [
8
+ {
9
+ id: '2024/04/01/test-fragment',
10
+ title: 'test fragment',
11
+ date: "2024-04-01",
12
+ html: `<a id="top" href="#bottom">to bottom</a>
13
+ <div style="height:800px">spacer</div>
14
+ <a id="bottom" href="#top">to top</a>`,
15
+ },
16
+ {
17
+ id: '2024/03/01/baz',
18
+ title: 'baz',
19
+ date: "2024-03-01",
20
+ html: `<p>baz!</p>`,
21
+ prev: '2024/02/01/bar',
22
+ },
23
+ {
24
+ id: '2024/02/01/bar',
25
+ title: 'bar',
26
+ date: "2024-02-01",
27
+ html: `<p>bar!</p>`,
28
+ next: '2024/03/01/baz',
29
+ prev: '2024/01/01/foo',
30
+ },
31
+ {
32
+ id: '2024/01/01/foo',
33
+ title: 'foo',
34
+ date: "2024-01-01",
35
+ html: `<p>foo!</p>`,
36
+ next: '2024/02/01/bar',
37
+ },
38
+ ];
39
+
40
+ export async function getArticles(): Promise<Article[]> {
41
+ await sleep(100);
42
+ return articles;
43
+ }
@@ -0,0 +1,8 @@
1
+ import { mount } from 'svelte'
2
+ import App from './App.svelte'
3
+
4
+ const app = mount(App, {
5
+ target: document.getElementById('app')!,
6
+ })
7
+
8
+ export default app
@@ -3,4 +3,5 @@
3
3
  </svelte:head>
4
4
  <main class="admin">
5
5
  <h1>Admin</h1>
6
+ <p>admin page</p>
6
7
  </main>
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import { link } from "svelte-spa-history-router"
3
+
4
+ import { getArticles } from "../lib/getArticles"
5
+ </script>
6
+ <svelte:head>
7
+ <title>Blog</title>
8
+ </svelte:head>
9
+ <main class="blog">
10
+ {#await getArticles() then articles}
11
+ <h1>Blog</h1>
12
+ <ul>
13
+ {#each articles as article}
14
+ <li>{ article.date } - <a use:link href={`/blog/posts/${article.id}`}>{ article.title }</a></li>
15
+ {/each}
16
+ <li>2024-01-01 - <a use:link href="/blog/posts/2024/01/01/deleted">deleted</a></li>
17
+ </ul>
18
+ {/await}
19
+ </main>
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ import type { Article } from "../types"
3
+
4
+ import { link } from "svelte-spa-history-router"
5
+
6
+ let { article }: { article: Article } = $props()
7
+ </script>
8
+ <svelte:head>
9
+ <title>{ article.title }</title>
10
+ </svelte:head>
11
+ <main class="post">
12
+ <h1>{ article.title }</h1>
13
+ <div>{ article.date }</div>
14
+ <div>{@html article.html }</div>
15
+ <div>
16
+ {#if article.prev }
17
+ <a use:link href={`/blog/posts/${article.prev}`}>prev</a>
18
+ {/if}
19
+ {#if article.next }
20
+ <a use:link href={`/blog/posts/${article.next}`}>next</a>
21
+ {/if}
22
+ </div>
23
+ </main>
@@ -0,0 +1,14 @@
1
+ <script lang="ts">
2
+ let {
3
+ num
4
+ }: {
5
+ num: number
6
+ } = $props();
7
+ </script>
8
+ <svelte:head>
9
+ <title>int param</title>
10
+ </svelte:head>
11
+ <main class="int-param">
12
+ <p class="value">value: { num }</p>
13
+ <p class="twice">twice: { num * 2 }</p>
14
+ </main>
@@ -0,0 +1,9 @@
1
+ <script lang="ts">
2
+ let { message = "" }: { message: string } = $props()
3
+ </script>
4
+ <svelte:head>
5
+ <title>Message</title>
6
+ </svelte:head>
7
+ <main class="message">
8
+ {#if message}<p>{message}</p>{/if}
9
+ </main>
@@ -0,0 +1,13 @@
1
+ <script lang="ts">
2
+ let {
3
+ params
4
+ }: {
5
+ params: { slug: string }
6
+ } = $props();
7
+ </script>
8
+ <svelte:head>
9
+ <title>Slug { params.slug }</title>
10
+ </svelte:head>
11
+ <main class="params">
12
+ <p class="slug">slug: { params.slug }</p>
13
+ </main>
@@ -1,13 +1,14 @@
1
1
  <script>
2
2
  import { link, currentURL } from "svelte-spa-history-router";
3
3
 
4
- $: name = $currentURL.searchParams.get("name") ?? 'unknown';
4
+
5
+ let name = $derived(currentURL().searchParams.get("name") ?? 'unknown');
5
6
  </script>
6
7
  <svelte:head>
7
8
  <title>query</title>
8
9
  </svelte:head>
9
- <div class="query">
10
+ <main class="query">
10
11
  <p>name: <span id="name">{ name }</span></p>
11
12
  <a use:link href="/query?name=foo">foo</a>
12
13
  <a use:link href="/query?name=bar">bar</a>
13
- </div>
14
+ </main>
@@ -0,0 +1,7 @@
1
+ <svelte:head>
2
+ <title>Top</title>
3
+ </svelte:head>
4
+ <h1>Top</h1>
5
+ <main class="top">
6
+ Basic route.
7
+ </main>
@@ -0,0 +1,9 @@
1
+
2
+ export interface Article {
3
+ id: string;
4
+ title: string;
5
+ date: string;
6
+ html: string;
7
+ next?: string;
8
+ prev?: string;
9
+ }
package/package.json CHANGED
@@ -1,28 +1,32 @@
1
1
  {
2
2
  "name": "svelte-spa-history-router",
3
- "version": "2.2.0",
3
+ "version": "3.0.0-next.2",
4
4
  "description": "History base router for Svelte SPA",
5
5
  "type": "module",
6
- "main": "src/index.js",
7
- "svelte": "src/index.js",
6
+ "main": "src/index.ts",
7
+ "svelte": "src/index.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "svelte": "./src/index.js"
10
+ "svelte": "./src/index.ts"
11
11
  }
12
12
  },
13
- "types": "src/index.d.ts",
14
13
  "scripts": {
15
- "dev": "cd examples/app-svelte4 && npm run dev",
16
- "test": "cd examples/app-svelte4 && npm run test",
17
- "format": "prettier --write 'src/**/*.js'",
18
- "check": "npx svelte-check"
14
+ "dev": "vite",
15
+ "test": "playwright test",
16
+ "check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json"
19
17
  },
20
18
  "peerDependencies": {
21
- "svelte": "*"
19
+ "svelte": ">5.0.0"
22
20
  },
23
21
  "devDependencies": {
24
- "prettier": "3.3.3",
25
- "svelte": "4.2.19"
22
+ "@playwright/test": "1.49.1",
23
+ "@sveltejs/vite-plugin-svelte": "5.0.3",
24
+ "@tsconfig/svelte": "5.0.4",
25
+ "playwright": "1.49.1",
26
+ "svelte": "5.16.0",
27
+ "svelte-check": "4.1.1",
28
+ "typescript": "5.7.2",
29
+ "vite": "6.0.6"
26
30
  },
27
31
  "author": "ykrods",
28
32
  "license": "MIT",