Skip to content

Commit 35f836f

Browse files
committed
Update Svelte 4 playground
1 parent 29916b1 commit 35f836f

12 files changed

+568
-15
lines changed

playgrounds/svelte4/resources/js/Components/Layout.svelte

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
<script>
2-
import { inertia, page } from '@inertiajs/svelte'
2+
import { inertia } from '@inertiajs/svelte'
3+
4+
export let appName
35
</script>
46

57
<nav class="flex items-center space-x-6 bg-slate-800 px-10 py-6 text-white">
6-
<div class="rounded-lg bg-slate-700 px-4 py-1">{$page.props.appName}</div>
7-
<a href="/" use:inertia class="hover:underline">Home</a>
8-
<a href="/users" use:inertia class="hover:underline">Users</a>
9-
<a href="/article" use:inertia class="hover:underline">Article</a>
10-
<a href="/form" use:inertia class="hover:underline">Form</a>
8+
<div class="rounded-lg bg-slate-700 px-4 py-1">{appName}</div>
9+
<!-- <Link href="/" prefetch class="hover:underline">Home</Link> -->
10+
<!-- <Link href="/users" prefetch cacheFor={['2s', '1m']} class="hover:underline">Users</Link> -->
11+
<!-- <Link href="/article" prefetch="click" class="hover:underline">Article</Link> -->
12+
<a href="/" use:inertia={{ prefetch: true }} class="hover:underline">Home</a>
13+
<a href="/users" use:inertia={{ prefetch: true, cacheFor: ['2s', '1m'] }} class="hover:underline">Users</a>
14+
<a href="/article" use:inertia={{ prefetch: 'click' }} class="hover:underline">Article</a>
15+
<a href="/form" use:inertia={{ prefetch: ['mount', 'click'] }} class="hover:underline">Form</a>
1116
<button use:inertia={{ method: 'post', href: '/logout' }} type="button" class="hover:underline">Logout</button>
17+
<a href="/goodbye" use:inertia class="hover:underline">External</a>
18+
<a href="/async" use:inertia class="hover:underline">Async Request</a>
19+
<a href="/defer" use:inertia class="hover:underline">Defer</a>
20+
<a href="/poll" use:inertia class="hover:underline">Poll</a>
21+
<a href="/infinite-scroll" use:inertia class="hover:underline">To Infinity</a>
1222
</nav>
1323

1424
<main class="px-10 py-8">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<svg class="mr-2 h-5 w-5 animate-spin text-black" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
2+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
3+
<path
4+
class="opacity-75"
5+
fill="currentColor"
6+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
7+
></path>
8+
</svg>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
let className = ''
3+
export { className as class }
4+
</script>
5+
6+
<div {...$$restProps} class="mt-6 grid grid-cols-3 gap-4 {className}">
7+
<slot />
8+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
let className
3+
export { className as class }
4+
</script>
5+
6+
<div {...$$restProps} class="rounded border border-gray-300 p-4 text-sm text-gray-500 {className}">
7+
{#if $$slots.title}
8+
<div class="mb-2 font-bold">
9+
<slot name="title" />
10+
</div>
11+
{/if}
12+
13+
<slot />
14+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<script context="module">
2+
export { default as layout } from '../Components/Layout.svelte'
3+
</script>
4+
5+
<script lang="ts">
6+
import { router, useForm } from '@inertiajs/svelte'
7+
import TestGrid from '../Components/TestGrid.svelte'
8+
import TestGridItem from '../Components/TestGridItem.svelte'
9+
10+
export let appName
11+
export let jonathan: boolean
12+
export let taylor: boolean
13+
export let joe: boolean
14+
15+
let reloadCount = 0
16+
const form = useForm({ jonathan, taylor, joe })
17+
18+
$: console.log('watched reload count value', reloadCount)
19+
20+
function submit() {
21+
router.post(
22+
'/async/checkbox',
23+
{
24+
jonathan: $form.jonathan,
25+
taylor: $form.taylor,
26+
joe: $form.joe,
27+
},
28+
{
29+
async: true,
30+
},
31+
)
32+
}
33+
34+
function simulateConflict() {
35+
router.reload({
36+
only: ['sleep'],
37+
})
38+
router.visit('/sleepy/2')
39+
}
40+
41+
function triggerVisitThenReload() {
42+
router.visit('/sleepy/1')
43+
router.reload({
44+
only: ['sleep'],
45+
})
46+
}
47+
48+
function triggerLongReload() {
49+
router.reload({
50+
only: ['sleep'],
51+
onFinish() {
52+
console.log('finished reload')
53+
reloadCount++
54+
console.log('incremented reload count')
55+
},
56+
})
57+
}
58+
59+
function triggerCancel() {
60+
router.post(
61+
'/sleepy/3',
62+
{},
63+
{
64+
onCancelToken: (token) => {
65+
console.log('onCancelToken')
66+
67+
setTimeout(() => {
68+
console.log('CANCELLING!')
69+
token.cancel()
70+
}, 1000)
71+
},
72+
},
73+
)
74+
}
75+
76+
function triggerCancelAfterFinish() {
77+
let cancelToken
78+
79+
router.post(
80+
'/sleepy/1',
81+
{},
82+
{
83+
onCancelToken: (token) => {
84+
console.log('onCancelToken')
85+
86+
cancelToken = token
87+
},
88+
onFinish: () => {
89+
console.log('onFinish')
90+
console.log('CANCELLING!')
91+
cancelToken.cancel()
92+
},
93+
},
94+
)
95+
}
96+
</script>
97+
98+
<svelte:head>
99+
<title>Async Request - {appName}</title>
100+
</svelte:head>
101+
102+
<h1 class="text-3xl">Async Request</h1>
103+
<p class="mt-6">Reload Count: {reloadCount}</p>
104+
105+
<TestGrid>
106+
<TestGridItem class="space-y-4">
107+
<p>Trigger an async reload that takes a moment and immediately programmatically visit another page</p>
108+
<button class="rounded bg-green-600 px-4 py-2 text-white" on:click={simulateConflict}>Reload → Visit</button>
109+
</TestGridItem>
110+
111+
<TestGridItem class="space-y-4">
112+
<form on:change={submit}>
113+
<label class="block">
114+
<input bind:checked={$form.jonathan} type="checkbox" class="mr-2" />
115+
Jonathan
116+
</label>
117+
<label class="block">
118+
<input bind:checked={$form.taylor} type="checkbox" class="mr-2" />
119+
Taylor
120+
</label>
121+
<label class="block">
122+
<input bind:checked={$form.joe} type="checkbox" class="mr-2" />
123+
Joe
124+
</label>
125+
</form>
126+
<p>You can check these on and off and then navigate to another page and the requests should still complete.</p>
127+
<p>Toggling "Joe" on will cause a redirect to "Article", simulating an authorized action e.g.</p>
128+
</TestGridItem>
129+
130+
<TestGridItem class="space-y-4">
131+
<p>Trigger programmatic visit and an async reload one after another</p>
132+
133+
<p>Reload should still happen but won't re-direct back to the reloaded component, we should respect the visit</p>
134+
135+
<button on:click={triggerVisitThenReload} class="rounded bg-green-600 px-4 py-2 text-white">Visit → Reload</button>
136+
</TestGridItem>
137+
138+
<TestGridItem class="space-y-4">
139+
<p>Simply trigger a 4 second reload so you can navigate or do whatever you'd like during it.</p>
140+
<button on:click={triggerLongReload} class="rounded bg-green-600 px-4 py-2 text-white">Trigger Long Reload</button>
141+
</TestGridItem>
142+
143+
<TestGridItem class="space-y-4">
144+
<p>Trigger an automatic cancellation from the token.</p>
145+
<button on:click={triggerCancel} class="rounded bg-green-600 px-4 py-2 text-white">Trigger Cancel</button>
146+
</TestGridItem>
147+
148+
<TestGridItem class="space-y-4">
149+
<p>Trigger an automatic cancellation from the token after finishing request.</p>
150+
<button on:click={triggerCancelAfterFinish} class="rounded bg-green-600 px-4 py-2 text-white">
151+
Trigger Cancel After Finish
152+
</button>
153+
</TestGridItem>
154+
</TestGrid>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<script context="module">
2+
export { default as layout } from '../Components/Layout.svelte'
3+
</script>
4+
5+
<script lang="ts">
6+
import { Deferred, WhenVisible } from '@inertiajs/svelte'
7+
import Spinner from '../Components/Spinner.svelte'
8+
import TestGrid from '../Components/TestGrid.svelte'
9+
import TestGridItem from '../Components/TestGridItem.svelte'
10+
11+
type Users = {
12+
id: number
13+
name: string
14+
email: string
15+
}
16+
17+
type Organizations = {
18+
id: number
19+
name: string
20+
url: string
21+
}
22+
23+
type Foods = {
24+
id: number
25+
name: string
26+
}
27+
28+
type Surprise = {
29+
id: number
30+
name: string
31+
}
32+
33+
type Dogs = {
34+
id: number
35+
name: string
36+
}
37+
38+
type Lunch = {
39+
id: number
40+
name: string
41+
}
42+
43+
export let appName
44+
export let users: Users[] = []
45+
export let organizations: Organizations[] = []
46+
export let foods: Foods[] = []
47+
export let surprise: Surprise[] = []
48+
export let dogs: Dogs[] = []
49+
export let lunch: Lunch[] = []
50+
</script>
51+
52+
<svelte:head>
53+
<title>Async Request - {appName}</title>
54+
</svelte:head>
55+
56+
<h1 class="text-3xl">Deferred Props</h1>
57+
58+
<div class="p-4 mt-6 bg-yellow-200 border border-yellow-500 rounded">
59+
<p>Page is loaded!</p>
60+
</div>
61+
62+
<TestGrid>
63+
<TestGridItem>
64+
<Deferred data="users">
65+
<svelte:fragment slot="fallback">
66+
<p>Loading Users...</p>
67+
</svelte:fragment>
68+
69+
<div>
70+
{#each users as user (user.id)}
71+
<p>#{user.id}: {user.name} ({user.email})</p>
72+
{/each}
73+
</div>
74+
</Deferred>
75+
</TestGridItem>
76+
77+
<TestGridItem>
78+
<Deferred data="foods">
79+
<svelte:fragment slot="fallback">
80+
<p>Loading Foods...</p>
81+
</svelte:fragment>
82+
83+
<div>
84+
{#each foods as food (food.id)}
85+
<p>#{food.id}: {food.name}</p>
86+
{/each}
87+
</div>
88+
</Deferred>
89+
</TestGridItem>
90+
91+
<TestGridItem>
92+
<Deferred data="organizations">
93+
<svelte:fragment slot="fallback">
94+
<p>Loading Organizations...</p>
95+
</svelte:fragment>
96+
97+
<div>
98+
{#each organizations as org (org.id)}
99+
<p>#{org.id}: {org.name} ({org.url})</p>
100+
{/each}
101+
</div>
102+
</Deferred>
103+
</TestGridItem>
104+
</TestGrid>
105+
106+
<div class="mt-72">
107+
<WhenVisible data="surprise">
108+
<svelte:fragment slot="fallback">
109+
<div class="h-24">
110+
<div class="flex items-center"><Spinner /> Loading Surprise...</div>
111+
</div>
112+
</svelte:fragment>
113+
114+
<div>
115+
{#each surprise as s (s.id)}
116+
<p>#{s.id}: {s.name}</p>
117+
{/each}
118+
</div>
119+
</WhenVisible>
120+
</div>
121+
122+
<div class="mt-72">
123+
<WhenVisible data={['dogs', 'lunch']} buffer={200}>
124+
<svelte:fragment slot="fallback">
125+
<div class="h-24">
126+
<div class="flex items-center"><Spinner /> Loading Dogs and Lunch...</div>
127+
</div>
128+
</svelte:fragment>
129+
130+
<div class="flex space-x-6">
131+
<div>
132+
{#each dogs as dog (dog.id)}
133+
<p>#{dog.id}: {dog.name}</p>
134+
{/each}
135+
</div>
136+
137+
<div>
138+
{#each lunch as item (item.id)}
139+
<p>#{item.id}: {item.name}</p>
140+
{/each}
141+
</div>
142+
</div>
143+
</WhenVisible>
144+
</div>

playgrounds/svelte4/resources/js/Pages/Form.svelte

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
export let appName
99
10-
let form = useForm('NewUser', {
10+
const form = useForm('NewUser', {
1111
name: '',
1212
company: '',
1313
role: '',

playgrounds/svelte4/resources/js/Pages/Home.svelte

+12-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</script>
44

55
<script>
6-
import { inertia } from '@inertiajs/svelte'
6+
import { inertia, router } from '@inertiajs/svelte'
77
export let appName
88
</script>
99

@@ -13,6 +13,14 @@
1313

1414
<h1 class="text-3xl">Home</h1>
1515

16-
<p class="mt-6">
17-
<a href="/article#far-down" use:inertia class="text-blue-700 underline">Link to bottom of article page</a>
18-
</p>
16+
<div class="mt-6 space-y-4">
17+
<div>
18+
<a href="/article#far-down" use:inertia class="text-blue-700 underline">Link to bottom of article page</a>
19+
</div>
20+
21+
<div>
22+
<button type="button" class="rounded-lg bg-blue-500 px-4 py-2 text-white" on:click={() => router.clearHistory()}>
23+
Clear history
24+
</button>
25+
</div>
26+
</div>

0 commit comments

Comments
 (0)