sveltekit-auth-example 5.1.1 → 5.1.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.
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/app.html +1 -0
- package/src/lib/google.ts +3 -2
- package/src/routes/+layout.svelte +15 -15
- package/src/routes/layout.css +7 -3
- package/src/routes/login/+page.svelte +14 -2
- package/src/routes/profile/+page.svelte +1 -1
- package/src/routes/register/+page.svelte +14 -2
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sveltekit-auth-example",
|
|
3
3
|
"description": "SvelteKit Authentication Example",
|
|
4
|
-
"version": "5.1.
|
|
4
|
+
"version": "5.1.2",
|
|
5
5
|
"author": "Nate Stuyvesant",
|
|
6
6
|
"license": "https://github.com/nstuyvesant/sveltekit-auth-example/blob/master/LICENSE",
|
|
7
7
|
"repository": {
|
package/src/app.html
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" sizes="any" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<meta name="color-scheme" content="light dark" />
|
|
7
8
|
<script
|
|
8
9
|
nonce="%sveltekit.nonce%"
|
|
9
10
|
src="https://accounts.google.com/gsi/client"
|
package/src/lib/google.ts
CHANGED
|
@@ -5,11 +5,12 @@ import { redirectAfterLogin } from '$lib/auth-redirect'
|
|
|
5
5
|
export function renderGoogleButton() {
|
|
6
6
|
const btn = document.getElementById('googleButton')
|
|
7
7
|
if (btn) {
|
|
8
|
+
const width = btn.offsetWidth || btn.parentElement?.offsetWidth || 400
|
|
8
9
|
google.accounts.id.renderButton(btn, {
|
|
9
10
|
type: 'standard',
|
|
10
|
-
theme: '
|
|
11
|
+
theme: 'outline',
|
|
11
12
|
size: 'large',
|
|
12
|
-
width:
|
|
13
|
+
width: Math.floor(width)
|
|
13
14
|
})
|
|
14
15
|
}
|
|
15
16
|
}
|
|
@@ -55,13 +55,13 @@
|
|
|
55
55
|
|
|
56
56
|
<svelte:window onclick={handleWindowClick} />
|
|
57
57
|
|
|
58
|
-
<nav class="tw:bg-gray-100 tw:border-b tw:border-gray-200">
|
|
58
|
+
<nav class="tw:bg-gray-100 tw:border-b tw:border-gray-200 tw:dark:bg-gray-900 tw:dark:border-gray-700">
|
|
59
59
|
<div class="tw:mx-auto tw:max-w-5xl tw:px-4 tw:flex tw:items-center tw:justify-between tw:h-14">
|
|
60
|
-
<a class="tw:font-semibold tw:text-gray-800 tw:no-underline" href="/">SvelteKit-Auth-Example</a>
|
|
60
|
+
<a class="tw:font-semibold tw:text-gray-800 tw:no-underline tw:dark:text-gray-100" href="/">SvelteKit-Auth-Example</a>
|
|
61
61
|
|
|
62
62
|
<!-- Mobile toggle -->
|
|
63
63
|
<button
|
|
64
|
-
class="tw:sm:hidden tw:p-2 tw:rounded tw:text-gray-600 hover:tw:bg-gray-200"
|
|
64
|
+
class="tw:sm:hidden tw:p-2 tw:rounded tw:text-gray-600 hover:tw:bg-gray-200 tw:dark:text-gray-300 tw:dark:hover:bg-gray-700"
|
|
65
65
|
aria-label="Toggle navigation"
|
|
66
66
|
onclick={() => (navOpen = !navOpen)}
|
|
67
67
|
>
|
|
@@ -71,22 +71,22 @@
|
|
|
71
71
|
</button>
|
|
72
72
|
|
|
73
73
|
<!-- Nav links -->
|
|
74
|
-
<div class="tw:hidden tw:sm:flex tw:items-center tw:gap-6 {navOpen ? '!tw:flex tw:flex-col tw:absolute tw:top-14 tw:left-0 tw:right-0 tw:bg-gray-100 tw:p-4 tw:border-b tw:border-gray-200' : ''}">
|
|
75
|
-
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900" href="/">Home</a>
|
|
76
|
-
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900" href="/info">Info</a>
|
|
74
|
+
<div class="tw:hidden tw:sm:flex tw:items-center tw:gap-6 {navOpen ? '!tw:flex tw:flex-col tw:absolute tw:top-14 tw:left-0 tw:right-0 tw:bg-gray-100 tw:dark:bg-gray-900 tw:p-4 tw:border-b tw:border-gray-200 tw:dark:border-gray-700' : ''}">
|
|
75
|
+
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900 tw:dark:text-gray-300 tw:dark:hover:text-white" href="/">Home</a>
|
|
76
|
+
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900 tw:dark:text-gray-300 tw:dark:hover:text-white" href="/info">Info</a>
|
|
77
77
|
|
|
78
78
|
{#if appState.user?.role === 'admin'}
|
|
79
|
-
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900" href="/admin">Admin</a>
|
|
79
|
+
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900 tw:dark:text-gray-300 tw:dark:hover:text-white" href="/admin">Admin</a>
|
|
80
80
|
{/if}
|
|
81
81
|
{#if appState.user && appState.user.role !== 'student'}
|
|
82
|
-
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900" href="/teachers">Teachers</a>
|
|
82
|
+
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900 tw:dark:text-gray-300 tw:dark:hover:text-white" href="/teachers">Teachers</a>
|
|
83
83
|
{/if}
|
|
84
84
|
|
|
85
85
|
{#if appState.user}
|
|
86
86
|
<!-- User dropdown -->
|
|
87
87
|
<div class="tw:relative" bind:this={dropdownEl}>
|
|
88
88
|
<button
|
|
89
|
-
class="tw:flex tw:items-center tw:gap-1 tw:text-sm tw:text-gray-700 hover:tw:text-gray-900 tw:bg-transparent tw:border-0 tw:cursor-pointer"
|
|
89
|
+
class="tw:flex tw:items-center tw:gap-1 tw:text-sm tw:text-gray-700 hover:tw:text-gray-900 tw:bg-transparent tw:border-0 tw:cursor-pointer tw:dark:text-gray-300 tw:dark:hover:text-white"
|
|
90
90
|
onclick={() => (dropdownOpen = !dropdownOpen)}
|
|
91
91
|
aria-expanded={dropdownOpen}
|
|
92
92
|
aria-haspopup="true"
|
|
@@ -101,13 +101,13 @@
|
|
|
101
101
|
</svg>
|
|
102
102
|
</button>
|
|
103
103
|
{#if dropdownOpen}
|
|
104
|
-
<ul class="tw:absolute tw:right-0 tw:mt-1 tw:w-36 tw:rounded tw:border tw:border-gray-200 tw:bg-white tw:shadow-md tw:py-1 tw:z-50 tw:list-none">
|
|
105
|
-
<li><a class="tw:block tw:px-4 tw:py-2 tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:bg-gray-100" href="/profile">Profile</a></li>
|
|
104
|
+
<ul class="tw:absolute tw:right-0 tw:mt-1 tw:w-36 tw:rounded tw:border tw:border-gray-200 tw:bg-white tw:shadow-md tw:py-1 tw:z-50 tw:list-none tw:dark:bg-gray-800 tw:dark:border-gray-700">
|
|
105
|
+
<li><a class="tw:block tw:px-4 tw:py-2 tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:bg-gray-100 tw:dark:text-gray-300 tw:dark:hover:bg-gray-700" href="/profile">Profile</a></li>
|
|
106
106
|
{#if appState.user?.id !== 0}
|
|
107
107
|
<li>
|
|
108
108
|
<button
|
|
109
109
|
onclick={logout}
|
|
110
|
-
class="tw:block tw:w-full tw:text-left tw:px-4 tw:py-2 tw:text-sm tw:text-gray-700 tw:bg-transparent tw:border-0 tw:cursor-pointer hover:tw:bg-gray-100"
|
|
110
|
+
class="tw:block tw:w-full tw:text-left tw:px-4 tw:py-2 tw:text-sm tw:text-gray-700 tw:bg-transparent tw:border-0 tw:cursor-pointer hover:tw:bg-gray-100 tw:dark:text-gray-300 tw:dark:hover:bg-gray-700"
|
|
111
111
|
>Logout</button>
|
|
112
112
|
</li>
|
|
113
113
|
{/if}
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
{/if}
|
|
116
116
|
</div>
|
|
117
117
|
{:else}
|
|
118
|
-
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900" href="/login">Login</a>
|
|
118
|
+
<a class="tw:text-sm tw:text-gray-700 tw:no-underline hover:tw:text-gray-900 tw:dark:text-gray-300 tw:dark:hover:text-white" href="/login">Login</a>
|
|
119
119
|
{/if}
|
|
120
120
|
</div>
|
|
121
121
|
</div>
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
role="alert"
|
|
132
132
|
aria-live="assertive"
|
|
133
133
|
aria-atomic="true"
|
|
134
|
-
class="tw:fixed tw:top-4 tw:right-4 tw:z-50 tw:min-w-64 tw:rounded tw:shadow-lg tw:border tw:border-gray-200 tw:bg-white tw:overflow-hidden"
|
|
134
|
+
class="tw:fixed tw:top-4 tw:right-4 tw:z-50 tw:min-w-64 tw:rounded tw:shadow-lg tw:border tw:border-gray-200 tw:bg-white tw:overflow-hidden tw:dark:bg-gray-800 tw:dark:border-gray-700"
|
|
135
135
|
>
|
|
136
136
|
<div class="tw:flex tw:items-center tw:justify-between tw:bg-blue-600 tw:px-4 tw:py-2">
|
|
137
137
|
<strong class="tw:text-white tw:text-sm">{appState.toast.title}</strong>
|
|
@@ -141,6 +141,6 @@
|
|
|
141
141
|
class="tw:text-white tw:bg-transparent tw:border-0 tw:cursor-pointer tw:text-lg tw:leading-none"
|
|
142
142
|
onclick={() => (appState.toast = { ...appState.toast, isOpen: false })}>×</button>
|
|
143
143
|
</div>
|
|
144
|
-
<div class="tw:px-4 tw:py-3 tw:text-sm">{appState.toast.body}</div>
|
|
144
|
+
<div class="tw:px-4 tw:py-3 tw:text-sm tw:dark:text-gray-100">{appState.toast.body}</div>
|
|
145
145
|
</div>
|
|
146
146
|
{/if}
|
package/src/routes/layout.css
CHANGED
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
html,
|
|
14
14
|
:host {
|
|
15
|
-
@apply tw:font-sans tw:text-gray-800;
|
|
15
|
+
@apply tw:font-sans tw:text-gray-800 tw:bg-white;
|
|
16
|
+
@variant dark {
|
|
17
|
+
@apply tw:text-gray-100 tw:bg-gray-900;
|
|
18
|
+
}
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -22,8 +25,9 @@
|
|
|
22
25
|
display: block;
|
|
23
26
|
width: 100%;
|
|
24
27
|
margin-top: 0.25rem;
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
appearance: none;
|
|
29
|
+
-webkit-appearance: none;
|
|
30
|
+
@apply tw:rounded tw:border tw:border-gray-300 tw:bg-white tw:text-gray-900 tw:dark:bg-gray-800 tw:dark:border-gray-600 tw:dark:text-gray-200;
|
|
27
31
|
padding: 0.375rem 0.75rem;
|
|
28
32
|
font-size: var(--text-sm, 0.875rem);
|
|
29
33
|
line-height: var(--tw-leading-sm, 1.25rem);
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
onMount(() => {
|
|
39
39
|
initializeGoogleAccounts()
|
|
40
40
|
renderGoogleButton()
|
|
41
|
-
|
|
42
41
|
focusedField?.focus()
|
|
43
42
|
})
|
|
44
43
|
|
|
@@ -86,7 +85,20 @@
|
|
|
86
85
|
<h4>Sign In</h4>
|
|
87
86
|
<p>Welcome back.</p>
|
|
88
87
|
|
|
89
|
-
<div
|
|
88
|
+
<div class="tw:group tw:relative tw:w-full">
|
|
89
|
+
<!-- Real Google button: invisible but receives clicks -->
|
|
90
|
+
<div id="googleButton" class="tw:opacity-0 tw:w-full"></div>
|
|
91
|
+
<!-- Visual overlay: looks good, no pointer events -->
|
|
92
|
+
<div class="tw:pointer-events-none tw:absolute tw:inset-0 tw:flex tw:items-center tw:justify-center tw:gap-3 tw:rounded tw:border tw:border-gray-300 tw:bg-white tw:group-hover:bg-gray-50 tw:text-sm tw:font-medium tw:text-gray-700 tw:dark:bg-gray-800 tw:dark:group-hover:bg-gray-700 tw:dark:border-gray-600 tw:dark:text-gray-200">
|
|
93
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
|
|
94
|
+
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
|
|
95
|
+
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
|
|
96
|
+
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l3.66-2.84z" fill="#FBBC05"/>
|
|
97
|
+
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
|
|
98
|
+
</svg>
|
|
99
|
+
Sign in with Google
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
90
102
|
|
|
91
103
|
<div class="tw:flex tw:items-center tw:gap-2 tw:text-gray-400 tw:text-sm">
|
|
92
104
|
<span class="tw:flex-1 tw:border-t tw:border-gray-300"></span>
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
<p class="tw:text-sm tw:text-gray-500 tw:mb-2">Danger zone</p>
|
|
209
209
|
<button
|
|
210
210
|
type="button"
|
|
211
|
-
class="tw:w-full tw:rounded tw:border tw:border-red-
|
|
211
|
+
class="tw:w-full tw:rounded tw:border tw:border-red-600 tw:bg-red-600 tw:px-4 tw:py-2 tw:text-sm tw:font-medium tw:text-white tw:cursor-pointer hover:tw:bg-red-700 hover:tw:border-red-700 disabled:tw:opacity-50 disabled:tw:cursor-not-allowed"
|
|
212
212
|
disabled={deleting}
|
|
213
213
|
onclick={deleteAccount}
|
|
214
214
|
>
|
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
onMount(() => {
|
|
55
55
|
initializeGoogleAccounts()
|
|
56
56
|
renderGoogleButton()
|
|
57
|
-
|
|
58
57
|
focusedField?.focus()
|
|
59
58
|
})
|
|
60
59
|
|
|
@@ -117,7 +116,20 @@
|
|
|
117
116
|
<h4>Register</h4>
|
|
118
117
|
<p>Welcome to our community.</p>
|
|
119
118
|
|
|
120
|
-
<div
|
|
119
|
+
<div class="tw:relative tw:w-full">
|
|
120
|
+
<!-- Real Google button: invisible but receives clicks -->
|
|
121
|
+
<div id="googleButton" class="tw:opacity-0 tw:w-full"></div>
|
|
122
|
+
<!-- Visual overlay: looks good, no pointer events -->
|
|
123
|
+
<div class="tw:pointer-events-none tw:absolute tw:inset-0 tw:flex tw:items-center tw:justify-center tw:gap-3 tw:rounded tw:border tw:border-gray-300 tw:bg-white tw:text-sm tw:font-medium tw:text-gray-700 tw:dark:bg-gray-800 tw:dark:border-gray-600 tw:dark:text-gray-200">
|
|
124
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
|
|
125
|
+
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
|
|
126
|
+
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
|
|
127
|
+
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l3.66-2.84z" fill="#FBBC05"/>
|
|
128
|
+
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
|
|
129
|
+
</svg>
|
|
130
|
+
Sign in with Google
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
121
133
|
|
|
122
134
|
<label class="tw:block tw:text-sm tw:font-medium" for="email">
|
|
123
135
|
Email
|