@authon/svelte 0.2.1 → 0.3.1
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.ko.md +50 -0
- package/README.md +161 -51
- package/dist/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- package/src/components/SignIn.svelte +39 -0
- package/src/components/SignUp.svelte +39 -0
package/README.ko.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[English](./README.md) | **한국어**
|
|
2
|
+
|
|
3
|
+
# @authon/svelte
|
|
4
|
+
|
|
5
|
+
> Svelte 인증 -- 반응형 스토어 -- 셀프 호스팅 Clerk 대안
|
|
6
|
+
|
|
7
|
+
## 설치
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @authon/svelte
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 빠른 시작
|
|
14
|
+
|
|
15
|
+
```svelte
|
|
16
|
+
<!-- +layout.svelte -->
|
|
17
|
+
<script lang="ts">
|
|
18
|
+
import { initAuthon } from '@authon/svelte';
|
|
19
|
+
import { onDestroy } from 'svelte';
|
|
20
|
+
const authon = initAuthon('pk_live_...', { apiUrl: 'https://your-authon-server.com' });
|
|
21
|
+
onDestroy(() => authon.destroy());
|
|
22
|
+
</script>
|
|
23
|
+
<slot />
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```svelte
|
|
27
|
+
<!-- +page.svelte -->
|
|
28
|
+
<script lang="ts">
|
|
29
|
+
import { getAuthon } from '@authon/svelte';
|
|
30
|
+
const { user, isSignedIn, openSignIn, signOut } = getAuthon();
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
{#if $isSignedIn}
|
|
34
|
+
<p>환영합니다, {$user?.displayName}</p>
|
|
35
|
+
<button on:click={signOut}>로그아웃</button>
|
|
36
|
+
{:else}
|
|
37
|
+
<button on:click={openSignIn}>로그인</button>
|
|
38
|
+
{/if}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 환경 변수
|
|
42
|
+
|
|
43
|
+
| 변수 | 필수 | 설명 |
|
|
44
|
+
|------|------|------|
|
|
45
|
+
| `PUBLIC_AUTHON_API_URL` | Yes | Authon 서버 URL |
|
|
46
|
+
| `PUBLIC_AUTHON_PUBLISHABLE_KEY` | Yes | 퍼블리셔블 키 |
|
|
47
|
+
|
|
48
|
+
## 라이선스
|
|
49
|
+
|
|
50
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,94 +1,204 @@
|
|
|
1
|
+
**English** | [한국어](./README.ko.md)
|
|
2
|
+
|
|
1
3
|
# @authon/svelte
|
|
2
4
|
|
|
3
|
-
Svelte
|
|
5
|
+
> Drop-in Svelte authentication with reactive stores — self-hosted Clerk alternative, Auth0 alternative
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@authon/svelte)
|
|
8
|
+
[](../../LICENSE)
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
Before installing the SDK, create an Authon project and get your API keys:
|
|
13
|
+
|
|
14
|
+
1. **Create a project** at [Authon Dashboard](https://authon.dev/dashboard/overview)
|
|
15
|
+
- Click "Create Project" and enter your app name
|
|
16
|
+
- Select the authentication methods you want (Email/Password, OAuth providers, etc.)
|
|
17
|
+
|
|
18
|
+
2. **Get your API keys** from Project Settings → API Keys
|
|
19
|
+
- **Publishable Key** (`pk_live_...` or `pk_test_...`) — safe to use in client-side code
|
|
20
|
+
- **Secret Key** (`sk_live_...` or `sk_test_...`) — server-side only, never expose to clients
|
|
21
|
+
|
|
22
|
+
3. **Configure OAuth providers** (optional) in Project Settings → OAuth
|
|
23
|
+
- Add Google, Apple, GitHub, etc. with their respective Client ID and Secret
|
|
24
|
+
- Set the redirect URL to `https://api.authon.dev/v1/auth/oauth/redirect`
|
|
25
|
+
|
|
26
|
+
> **Test vs Live keys:** Use `pk_test_...` during development. Switch to `pk_live_...` before deploying to production. Test keys use a sandbox environment with no rate limits.
|
|
4
27
|
|
|
5
28
|
## Install
|
|
6
29
|
|
|
7
30
|
```bash
|
|
8
31
|
npm install @authon/svelte
|
|
9
|
-
# or
|
|
10
|
-
pnpm add @authon/svelte
|
|
11
32
|
```
|
|
12
33
|
|
|
13
|
-
Requires `svelte >= 4.0.0`.
|
|
14
|
-
|
|
15
34
|
## Quick Start
|
|
16
35
|
|
|
17
|
-
|
|
36
|
+
```svelte
|
|
37
|
+
<!-- src/routes/+layout.svelte -->
|
|
38
|
+
<script lang="ts">
|
|
39
|
+
import { initAuthon } from '@authon/svelte';
|
|
40
|
+
import { onDestroy } from 'svelte';
|
|
18
41
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
42
|
+
const authon = initAuthon('pk_live_YOUR_PUBLISHABLE_KEY', {
|
|
43
|
+
apiUrl: 'https://your-authon-server.com',
|
|
44
|
+
theme: 'auto',
|
|
45
|
+
});
|
|
22
46
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
26
|
-
```
|
|
47
|
+
onDestroy(() => authon.destroy());
|
|
48
|
+
</script>
|
|
27
49
|
|
|
28
|
-
|
|
50
|
+
<slot />
|
|
51
|
+
```
|
|
29
52
|
|
|
30
53
|
```svelte
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
import {
|
|
54
|
+
<!-- src/routes/+page.svelte -->
|
|
55
|
+
<script lang="ts">
|
|
56
|
+
import { getAuthon } from '@authon/svelte';
|
|
57
|
+
const { user, isSignedIn, isLoading, openSignIn, signOut } = getAuthon();
|
|
34
58
|
</script>
|
|
35
59
|
|
|
36
60
|
{#if $isLoading}
|
|
37
61
|
<p>Loading...</p>
|
|
38
62
|
{:else if $isSignedIn}
|
|
39
63
|
<p>Welcome, {$user?.displayName}</p>
|
|
40
|
-
<button on:click={signOut}>Sign
|
|
64
|
+
<button on:click={signOut}>Sign out</button>
|
|
41
65
|
{:else}
|
|
42
|
-
<button on:click={openSignIn}>Sign
|
|
66
|
+
<button on:click={openSignIn}>Sign in</button>
|
|
43
67
|
{/if}
|
|
44
68
|
```
|
|
45
69
|
|
|
46
|
-
|
|
70
|
+
## Common Tasks
|
|
71
|
+
|
|
72
|
+
### Add Google OAuth Login
|
|
47
73
|
|
|
48
74
|
```svelte
|
|
49
|
-
<script>
|
|
50
|
-
import {
|
|
75
|
+
<script lang="ts">
|
|
76
|
+
import { getAuthon } from '@authon/svelte';
|
|
77
|
+
const { client } = getAuthon();
|
|
51
78
|
</script>
|
|
52
79
|
|
|
53
|
-
<
|
|
54
|
-
<UserButton />
|
|
55
|
-
</SignedIn>
|
|
56
|
-
<SignedOut>
|
|
57
|
-
<button on:click={openSignIn}>Sign In</button>
|
|
58
|
-
</SignedOut>
|
|
80
|
+
<button on:click={() => client.signInWithOAuth('google')}>Sign in with Google</button>
|
|
59
81
|
```
|
|
60
82
|
|
|
61
|
-
|
|
83
|
+
### Protect a Route
|
|
84
|
+
|
|
85
|
+
```svelte
|
|
86
|
+
<!-- src/routes/dashboard/+page.svelte -->
|
|
87
|
+
<script lang="ts">
|
|
88
|
+
import { getAuthon } from '@authon/svelte';
|
|
89
|
+
import { goto } from '$app/navigation';
|
|
90
|
+
import { onMount } from 'svelte';
|
|
91
|
+
|
|
92
|
+
const { isSignedIn, isLoading } = getAuthon();
|
|
93
|
+
|
|
94
|
+
onMount(() => {
|
|
95
|
+
if (!$isLoading && !$isSignedIn) goto('/sign-in');
|
|
96
|
+
});
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
{#if $isSignedIn}
|
|
100
|
+
<h1>Dashboard</h1>
|
|
101
|
+
{/if}
|
|
102
|
+
```
|
|
62
103
|
|
|
63
|
-
###
|
|
104
|
+
### Get Current User
|
|
64
105
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
106
|
+
```svelte
|
|
107
|
+
<script lang="ts">
|
|
108
|
+
import { getAuthon } from '@authon/svelte';
|
|
109
|
+
const { user, isLoading } = getAuthon();
|
|
110
|
+
</script>
|
|
70
111
|
|
|
71
|
-
|
|
112
|
+
{#if $isLoading}
|
|
113
|
+
<p>Loading...</p>
|
|
114
|
+
{:else if $user}
|
|
115
|
+
<p>Email: {$user.email}</p>
|
|
116
|
+
<p>Name: {$user.displayName}</p>
|
|
117
|
+
{:else}
|
|
118
|
+
<p>Not signed in</p>
|
|
119
|
+
{/if}
|
|
120
|
+
```
|
|
72
121
|
|
|
73
|
-
|
|
74
|
-
|----------|---------|-------------|
|
|
75
|
-
| `openSignIn()` | `Promise<void>` | Open sign-in modal |
|
|
76
|
-
| `openSignUp()` | `Promise<void>` | Open sign-up modal |
|
|
77
|
-
| `signOut()` | `Promise<void>` | Sign out |
|
|
78
|
-
| `getToken()` | `string \| null` | Get current access token |
|
|
122
|
+
### Add Email/Password Auth
|
|
79
123
|
|
|
80
|
-
|
|
124
|
+
```svelte
|
|
125
|
+
<script lang="ts">
|
|
126
|
+
import { getAuthon } from '@authon/svelte';
|
|
127
|
+
const { client } = getAuthon();
|
|
128
|
+
let email = '';
|
|
129
|
+
let password = '';
|
|
130
|
+
|
|
131
|
+
async function handleSignIn() {
|
|
132
|
+
await client.signInWithEmail(email, password);
|
|
133
|
+
}
|
|
134
|
+
</script>
|
|
81
135
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
136
|
+
<form on:submit|preventDefault={handleSignIn}>
|
|
137
|
+
<input bind:value={email} type="email" placeholder="Email" />
|
|
138
|
+
<input bind:value={password} type="password" placeholder="Password" />
|
|
139
|
+
<button type="submit">Sign in</button>
|
|
140
|
+
</form>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Handle Sign Out
|
|
144
|
+
|
|
145
|
+
```svelte
|
|
146
|
+
<script lang="ts">
|
|
147
|
+
import { getAuthon } from '@authon/svelte';
|
|
148
|
+
const { signOut } = getAuthon();
|
|
149
|
+
</script>
|
|
87
150
|
|
|
88
|
-
|
|
151
|
+
<button on:click={signOut}>Sign Out</button>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Environment Variables
|
|
155
|
+
|
|
156
|
+
| Variable | Required | Description |
|
|
157
|
+
|----------|----------|-------------|
|
|
158
|
+
| `PUBLIC_AUTHON_API_URL` | Yes | Your Authon server URL |
|
|
159
|
+
| `PUBLIC_AUTHON_PUBLISHABLE_KEY` | Yes | Project publishable key |
|
|
160
|
+
|
|
161
|
+
## API Reference
|
|
89
162
|
|
|
90
|
-
|
|
163
|
+
### Setup
|
|
164
|
+
|
|
165
|
+
| Function | Description |
|
|
166
|
+
|----------|-------------|
|
|
167
|
+
| `initAuthon(key, config?)` | Create store and set in Svelte context (call in root layout) |
|
|
168
|
+
| `getAuthon()` | Get `AuthonStore` from context (call in child components) |
|
|
169
|
+
| `createAuthonStore(key, config?)` | Low-level store factory (without context) |
|
|
170
|
+
|
|
171
|
+
### AuthonStore
|
|
172
|
+
|
|
173
|
+
| Property / Method | Type |
|
|
174
|
+
|-------------------|------|
|
|
175
|
+
| `user` | `Readable<AuthonUser \| null>` |
|
|
176
|
+
| `isSignedIn` | `Readable<boolean>` |
|
|
177
|
+
| `isLoading` | `Readable<boolean>` |
|
|
178
|
+
| `client` | `Authon` |
|
|
179
|
+
| `signOut()` | `Promise<void>` |
|
|
180
|
+
| `openSignIn()` | `Promise<void>` |
|
|
181
|
+
| `openSignUp()` | `Promise<void>` |
|
|
182
|
+
| `getToken()` | `string \| null` |
|
|
183
|
+
| `web3GetNonce(...)` | Web3 nonce request |
|
|
184
|
+
| `web3Verify(...)` | Web3 sign-in |
|
|
185
|
+
| `passwordlessSendCode(...)` | Send magic link or OTP |
|
|
186
|
+
| `passwordlessVerifyCode(...)` | Verify OTP |
|
|
187
|
+
| `passkeyRegister(...)` | Register passkey |
|
|
188
|
+
| `passkeyAuthenticate(...)` | Auth with passkey |
|
|
189
|
+
| `destroy()` | Cleanup |
|
|
190
|
+
|
|
191
|
+
## Comparison
|
|
192
|
+
|
|
193
|
+
| Feature | Authon | Clerk | Auth.js |
|
|
194
|
+
|---------|--------|-------|---------|
|
|
195
|
+
| Self-hosted | Yes | No | Partial |
|
|
196
|
+
| Pricing | Free | $25/mo+ | Free |
|
|
197
|
+
| OAuth providers | 10+ | 20+ | 80+ |
|
|
198
|
+
| ShadowDOM modal | Yes | No | No |
|
|
199
|
+
| MFA/Passkeys | Yes | Yes | Plugin |
|
|
200
|
+
| Web3 auth | Yes | No | No |
|
|
91
201
|
|
|
92
202
|
## License
|
|
93
203
|
|
|
94
|
-
|
|
204
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -62,7 +62,21 @@ function createAuthonStore(publishableKey, config) {
|
|
|
62
62
|
openSignUp: () => client.openSignUp(),
|
|
63
63
|
getToken: () => client.getToken(),
|
|
64
64
|
destroy: () => client.destroy(),
|
|
65
|
-
client
|
|
65
|
+
client,
|
|
66
|
+
// Web3
|
|
67
|
+
web3GetNonce: (address, chain, walletType, chainId) => client.web3GetNonce(address, chain, walletType, chainId),
|
|
68
|
+
web3Verify: (message, signature, address, chain, walletType) => client.web3Verify(message, signature, address, chain, walletType),
|
|
69
|
+
web3LinkWallet: (params) => client.linkWallet(params),
|
|
70
|
+
web3UnlinkWallet: (walletId) => client.unlinkWallet(walletId),
|
|
71
|
+
web3GetWallets: () => client.listWallets(),
|
|
72
|
+
// Passwordless
|
|
73
|
+
passwordlessSendCode: (email, type = "otp") => type === "magic-link" ? client.sendMagicLink(email) : client.sendEmailOtp(email),
|
|
74
|
+
passwordlessVerifyCode: (email, code) => client.verifyPasswordless({ email, code }),
|
|
75
|
+
// Passkeys
|
|
76
|
+
passkeyRegister: (name) => client.registerPasskey(name),
|
|
77
|
+
passkeyAuthenticate: (email) => client.authenticateWithPasskey(email),
|
|
78
|
+
passkeyList: () => client.listPasskeys(),
|
|
79
|
+
passkeyDelete: (credentialId) => client.revokePasskey(credentialId)
|
|
66
80
|
};
|
|
67
81
|
}
|
|
68
82
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/store.ts","../src/context.ts","../src/SocialButtons.ts"],"sourcesContent":["export { createAuthonStore } from './store';\nexport type { AuthonStore } from './store';\nexport { initAuthon, getAuthon } from './context';\nexport { renderSocialButtons } from './SocialButtons';\nexport type { SocialButtonsOptions } from './SocialButtons';\n","import { writable, derived, type Readable } from 'svelte/store';\nimport { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\nexport interface AuthonStore {\n user: Readable<AuthonUser | null>;\n isSignedIn: Readable<boolean>;\n isLoading: Readable<boolean>;\n signOut: () => Promise<void>;\n openSignIn: () => Promise<void>;\n openSignUp: () => Promise<void>;\n getToken: () => string | null;\n destroy: () => void;\n client: Authon;\n}\n\n/**\n * Creates an Authon store with reactive Svelte stores.\n *\n * Usage:\n * ```ts\n * import { createAuthonStore } from '@authon/svelte'\n *\n * const authon = createAuthonStore('pk_live_...')\n *\n * // In your component:\n * $: user = $authon.user\n * $: isSignedIn = $authon.isSignedIn\n * ```\n */\nexport function createAuthonStore(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const client = new Authon(publishableKey, config);\n const userStore = writable<AuthonUser | null>(null);\n const isLoadingStore = writable(true);\n\n const isSignedIn = derived(userStore, ($user) => $user !== null);\n\n client.on('signedIn', (user) => {\n userStore.set(user as AuthonUser);\n isLoadingStore.set(false);\n });\n\n client.on('signedOut', () => {\n userStore.set(null);\n });\n\n client.on('error', () => {\n isLoadingStore.set(false);\n });\n\n const existingUser = client.getUser();\n if (existingUser) {\n userStore.set(existingUser);\n }\n isLoadingStore.set(false);\n\n return {\n user: { subscribe: userStore.subscribe },\n isSignedIn,\n isLoading: { subscribe: isLoadingStore.subscribe },\n signOut: async () => {\n await client.signOut();\n userStore.set(null);\n },\n openSignIn: () => client.openSignIn(),\n openSignUp: () => client.openSignUp(),\n getToken: () => client.getToken(),\n destroy: () => client.destroy(),\n client,\n };\n}\n","import { setContext, getContext } from 'svelte';\nimport type { AuthonConfig } from '@authon/js';\nimport { createAuthonStore, type AuthonStore } from './store';\n\nconst AUTHON_CONTEXT_KEY = Symbol('authon');\n\n/**\n * Initialize Authon in a Svelte component tree.\n * Call this in your root layout or top-level component.\n *\n * Usage in +layout.svelte:\n * ```svelte\n * <script>\n * import { initAuthon } from '@authon/svelte'\n * const authon = initAuthon('pk_live_...')\n * </script>\n * ```\n */\nexport function initAuthon(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const store = createAuthonStore(publishableKey, config);\n setContext(AUTHON_CONTEXT_KEY, store);\n return store;\n}\n\n/**\n * Get the Authon store from Svelte context.\n * Must be called within a component tree where `initAuthon` was called.\n *\n * Usage:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * const { user, isSignedIn, signOut } = getAuthon()\n * </script>\n * ```\n */\nexport function getAuthon(): AuthonStore {\n const store = getContext<AuthonStore | undefined>(AUTHON_CONTEXT_KEY);\n if (!store) {\n throw new Error('getAuthon() must be called within a component tree where initAuthon() was called.');\n }\n return store;\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { getProviderButtonConfig, type Authon } from '@authon/js';\n\nexport interface SocialButtonsOptions {\n /** Authon client instance */\n client: Authon;\n /** Target container element */\n container: HTMLElement;\n /** Called after successful OAuth sign-in */\n onSuccess?: () => void;\n /** Called on OAuth error */\n onError?: (error: Error) => void;\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Gap between buttons in px (default: 10, compact default: 12) */\n gap?: number;\n /** Custom labels per provider */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius in px (default: 10) */\n borderRadius?: number;\n /** Button height in px (default: 48) */\n height?: number;\n /** Button size for compact mode in px (default: 48) */\n size?: number;\n}\n\n/**\n * Render social login buttons into a container element.\n *\n * Usage in +page.svelte:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * import { renderSocialButtons } from '@authon/svelte'\n * import { onMount } from 'svelte'\n *\n * const { client } = getAuthon()\n * let container: HTMLElement\n *\n * onMount(() => {\n * const cleanup = renderSocialButtons({\n * client,\n * container,\n * compact: true,\n * onError: (err) => console.error(err),\n * })\n * return cleanup\n * })\n * </script>\n *\n * <div bind:this={container}></div>\n * ```\n */\nexport function renderSocialButtons(options: SocialButtonsOptions): () => void {\n const {\n client,\n container,\n onSuccess,\n onError,\n compact = false,\n gap,\n labels,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n } = options;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n let loadingProvider: string | null = null;\n let buttons: HTMLButtonElement[] = [];\n\n const handleClick = async (provider: OAuthProviderType, btn: HTMLButtonElement) => {\n if (loadingProvider) return;\n loadingProvider = provider;\n btn.innerHTML = '<span style=\"display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite\"></span>';\n buttons.forEach((b) => (b.disabled = true));\n\n try {\n await client.signInWithOAuth(provider);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n loadingProvider = null;\n renderButtons(providers);\n }\n };\n\n let providers: OAuthProviderType[] = [];\n\n function renderButtons(providerList: OAuthProviderType[]) {\n container.innerHTML = '';\n buttons = [];\n\n // Inject keyframe if not present\n if (!document.getElementById('authon-spin-style')) {\n const style = document.createElement('style');\n style.id = 'authon-spin-style';\n style.textContent = '@keyframes authon-spin{to{transform:rotate(360deg)}}';\n document.head.appendChild(style);\n }\n\n const wrapper = document.createElement('div');\n wrapper.style.display = 'flex';\n wrapper.style.gap = `${resolvedGap}px`;\n\n if (compact) {\n wrapper.style.flexDirection = 'row';\n wrapper.style.flexWrap = 'wrap';\n wrapper.style.justifyContent = 'center';\n } else {\n wrapper.style.flexDirection = 'column';\n }\n\n for (const provider of providerList) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const config = getProviderButtonConfig(provider);\n const iconSvg = config.iconSvg\n .replace(/width=\"\\d+\"/, `width=\"${resolvedIconSize}\"`)\n .replace(/height=\"\\d+\"/, `height=\"${resolvedIconSize}\"`);\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n\n const btn = document.createElement('button');\n btn.setAttribute('aria-label', `Sign in with ${displayName}`);\n btn.style.display = 'flex';\n btn.style.alignItems = 'center';\n btn.style.justifyContent = 'center';\n btn.style.border = needsBorder ? '1px solid #dadce0' : 'none';\n btn.style.cursor = 'pointer';\n btn.style.backgroundColor = colors.bg;\n btn.style.color = colors.text;\n btn.style.borderRadius = `${borderRadius}px`;\n btn.style.transition = 'opacity 0.15s';\n btn.style.fontFamily = 'inherit';\n\n if (compact) {\n btn.style.width = `${size}px`;\n btn.style.height = `${size}px`;\n btn.style.padding = '0';\n btn.innerHTML = `<span style=\"display:flex;align-items:center\">${iconSvg}</span>`;\n } else {\n btn.style.width = '100%';\n btn.style.height = `${height}px`;\n btn.style.gap = '10px';\n btn.style.paddingLeft = '16px';\n btn.style.paddingRight = '16px';\n const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;\n btn.innerHTML = `<span style=\"display:flex;align-items:center;flex-shrink:0\">${iconSvg}</span><span style=\"font-size:15px;font-weight:600;white-space:nowrap\">${buttonLabel}</span>`;\n }\n\n btn.addEventListener('click', () => handleClick(provider, btn));\n btn.addEventListener('mouseenter', () => (btn.style.opacity = '0.85'));\n btn.addEventListener('mouseleave', () => (btn.style.opacity = '1'));\n\n buttons.push(btn);\n wrapper.appendChild(btn);\n }\n\n container.appendChild(wrapper);\n }\n\n // Init\n client.getProviders().then((p: OAuthProviderType[]) => {\n providers = p;\n if (providers.length > 0) {\n renderButtons(providers);\n }\n });\n\n // Cleanup\n return () => {\n container.innerHTML = '';\n buttons = [];\n };\n}\n"],"mappings":"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","names":["import_js"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/store.ts","../src/context.ts","../src/SocialButtons.ts"],"sourcesContent":["export { createAuthonStore } from './store';\nexport type { AuthonStore } from './store';\nexport { initAuthon, getAuthon } from './context';\nexport { renderSocialButtons } from './SocialButtons';\nexport type { SocialButtonsOptions } from './SocialButtons';\nexport type {\n PasskeyCredential,\n Web3Chain,\n Web3NonceResponse,\n Web3Wallet,\n Web3WalletType,\n} from '@authon/shared';\n\n// Svelte components are exported as raw .svelte source for the consumer's compiler.\n// Import them directly:\n// import SignIn from '@authon/svelte/SignIn.svelte'\n// import SignUp from '@authon/svelte/SignUp.svelte'\n","import { writable, derived, type Readable } from 'svelte/store';\nimport { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type {\n AuthonUser,\n PasskeyCredential,\n Web3Chain,\n Web3NonceResponse,\n Web3Wallet,\n Web3WalletType,\n} from '@authon/shared';\n\nexport interface AuthonStore {\n user: Readable<AuthonUser | null>;\n isSignedIn: Readable<boolean>;\n isLoading: Readable<boolean>;\n signOut: () => Promise<void>;\n openSignIn: () => Promise<void>;\n openSignUp: () => Promise<void>;\n getToken: () => string | null;\n destroy: () => void;\n client: Authon;\n // Web3\n web3GetNonce: (address: string, chain: Web3Chain, walletType: Web3WalletType, chainId?: number) => Promise<Web3NonceResponse>;\n web3Verify: (message: string, signature: string, address: string, chain: Web3Chain, walletType: Web3WalletType) => Promise<AuthonUser>;\n web3LinkWallet: (params: { address: string; chain: Web3Chain; walletType: Web3WalletType; chainId?: number; message: string; signature: string }) => Promise<Web3Wallet>;\n web3UnlinkWallet: (walletId: string) => Promise<void>;\n web3GetWallets: () => Promise<Web3Wallet[]>;\n // Passwordless\n passwordlessSendCode: (email: string, type?: 'magic-link' | 'otp') => Promise<void>;\n passwordlessVerifyCode: (email: string, code: string) => Promise<AuthonUser>;\n // Passkeys\n passkeyRegister: (name?: string) => Promise<PasskeyCredential>;\n passkeyAuthenticate: (email?: string) => Promise<AuthonUser>;\n passkeyList: () => Promise<PasskeyCredential[]>;\n passkeyDelete: (credentialId: string) => Promise<void>;\n}\n\n/**\n * Creates an Authon store with reactive Svelte stores.\n *\n * Usage:\n * ```ts\n * import { createAuthonStore } from '@authon/svelte'\n *\n * const authon = createAuthonStore('pk_live_...')\n *\n * // In your component:\n * $: user = $authon.user\n * $: isSignedIn = $authon.isSignedIn\n * ```\n */\nexport function createAuthonStore(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const client = new Authon(publishableKey, config);\n const userStore = writable<AuthonUser | null>(null);\n const isLoadingStore = writable(true);\n\n const isSignedIn = derived(userStore, ($user) => $user !== null);\n\n client.on('signedIn', (user) => {\n userStore.set(user as AuthonUser);\n isLoadingStore.set(false);\n });\n\n client.on('signedOut', () => {\n userStore.set(null);\n });\n\n client.on('error', () => {\n isLoadingStore.set(false);\n });\n\n const existingUser = client.getUser();\n if (existingUser) {\n userStore.set(existingUser);\n }\n isLoadingStore.set(false);\n\n return {\n user: { subscribe: userStore.subscribe },\n isSignedIn,\n isLoading: { subscribe: isLoadingStore.subscribe },\n signOut: async () => {\n await client.signOut();\n userStore.set(null);\n },\n openSignIn: () => client.openSignIn(),\n openSignUp: () => client.openSignUp(),\n getToken: () => client.getToken(),\n destroy: () => client.destroy(),\n client,\n // Web3\n web3GetNonce: (address, chain, walletType, chainId?) =>\n client.web3GetNonce(address, chain, walletType, chainId),\n web3Verify: (message, signature, address, chain, walletType) =>\n client.web3Verify(message, signature, address, chain, walletType),\n web3LinkWallet: (params) => client.linkWallet(params),\n web3UnlinkWallet: (walletId) => client.unlinkWallet(walletId),\n web3GetWallets: () => client.listWallets(),\n // Passwordless\n passwordlessSendCode: (email, type = 'otp') =>\n type === 'magic-link' ? client.sendMagicLink(email) : client.sendEmailOtp(email),\n passwordlessVerifyCode: (email, code) => client.verifyPasswordless({ email, code }),\n // Passkeys\n passkeyRegister: (name?) => client.registerPasskey(name),\n passkeyAuthenticate: (email?) => client.authenticateWithPasskey(email),\n passkeyList: () => client.listPasskeys(),\n passkeyDelete: (credentialId) => client.revokePasskey(credentialId),\n };\n}\n","import { setContext, getContext } from 'svelte';\nimport type { AuthonConfig } from '@authon/js';\nimport { createAuthonStore, type AuthonStore } from './store';\n\nconst AUTHON_CONTEXT_KEY = Symbol('authon');\n\n/**\n * Initialize Authon in a Svelte component tree.\n * Call this in your root layout or top-level component.\n *\n * Usage in +layout.svelte:\n * ```svelte\n * <script>\n * import { initAuthon } from '@authon/svelte'\n * const authon = initAuthon('pk_live_...')\n * </script>\n * ```\n */\nexport function initAuthon(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const store = createAuthonStore(publishableKey, config);\n setContext(AUTHON_CONTEXT_KEY, store);\n return store;\n}\n\n/**\n * Get the Authon store from Svelte context.\n * Must be called within a component tree where `initAuthon` was called.\n *\n * Usage:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * const { user, isSignedIn, signOut } = getAuthon()\n * </script>\n * ```\n */\nexport function getAuthon(): AuthonStore {\n const store = getContext<AuthonStore | undefined>(AUTHON_CONTEXT_KEY);\n if (!store) {\n throw new Error('getAuthon() must be called within a component tree where initAuthon() was called.');\n }\n return store;\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { getProviderButtonConfig, type Authon } from '@authon/js';\n\nexport interface SocialButtonsOptions {\n /** Authon client instance */\n client: Authon;\n /** Target container element */\n container: HTMLElement;\n /** Called after successful OAuth sign-in */\n onSuccess?: () => void;\n /** Called on OAuth error */\n onError?: (error: Error) => void;\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Gap between buttons in px (default: 10, compact default: 12) */\n gap?: number;\n /** Custom labels per provider */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius in px (default: 10) */\n borderRadius?: number;\n /** Button height in px (default: 48) */\n height?: number;\n /** Button size for compact mode in px (default: 48) */\n size?: number;\n}\n\n/**\n * Render social login buttons into a container element.\n *\n * Usage in +page.svelte:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * import { renderSocialButtons } from '@authon/svelte'\n * import { onMount } from 'svelte'\n *\n * const { client } = getAuthon()\n * let container: HTMLElement\n *\n * onMount(() => {\n * const cleanup = renderSocialButtons({\n * client,\n * container,\n * compact: true,\n * onError: (err) => console.error(err),\n * })\n * return cleanup\n * })\n * </script>\n *\n * <div bind:this={container}></div>\n * ```\n */\nexport function renderSocialButtons(options: SocialButtonsOptions): () => void {\n const {\n client,\n container,\n onSuccess,\n onError,\n compact = false,\n gap,\n labels,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n } = options;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n let loadingProvider: string | null = null;\n let buttons: HTMLButtonElement[] = [];\n\n const handleClick = async (provider: OAuthProviderType, btn: HTMLButtonElement) => {\n if (loadingProvider) return;\n loadingProvider = provider;\n btn.innerHTML = '<span style=\"display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite\"></span>';\n buttons.forEach((b) => (b.disabled = true));\n\n try {\n await client.signInWithOAuth(provider);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n loadingProvider = null;\n renderButtons(providers);\n }\n };\n\n let providers: OAuthProviderType[] = [];\n\n function renderButtons(providerList: OAuthProviderType[]) {\n container.innerHTML = '';\n buttons = [];\n\n // Inject keyframe if not present\n if (!document.getElementById('authon-spin-style')) {\n const style = document.createElement('style');\n style.id = 'authon-spin-style';\n style.textContent = '@keyframes authon-spin{to{transform:rotate(360deg)}}';\n document.head.appendChild(style);\n }\n\n const wrapper = document.createElement('div');\n wrapper.style.display = 'flex';\n wrapper.style.gap = `${resolvedGap}px`;\n\n if (compact) {\n wrapper.style.flexDirection = 'row';\n wrapper.style.flexWrap = 'wrap';\n wrapper.style.justifyContent = 'center';\n } else {\n wrapper.style.flexDirection = 'column';\n }\n\n for (const provider of providerList) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const config = getProviderButtonConfig(provider);\n const iconSvg = config.iconSvg\n .replace(/width=\"\\d+\"/, `width=\"${resolvedIconSize}\"`)\n .replace(/height=\"\\d+\"/, `height=\"${resolvedIconSize}\"`);\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n\n const btn = document.createElement('button');\n btn.setAttribute('aria-label', `Sign in with ${displayName}`);\n btn.style.display = 'flex';\n btn.style.alignItems = 'center';\n btn.style.justifyContent = 'center';\n btn.style.border = needsBorder ? '1px solid #dadce0' : 'none';\n btn.style.cursor = 'pointer';\n btn.style.backgroundColor = colors.bg;\n btn.style.color = colors.text;\n btn.style.borderRadius = `${borderRadius}px`;\n btn.style.transition = 'opacity 0.15s';\n btn.style.fontFamily = 'inherit';\n\n if (compact) {\n btn.style.width = `${size}px`;\n btn.style.height = `${size}px`;\n btn.style.padding = '0';\n btn.innerHTML = `<span style=\"display:flex;align-items:center\">${iconSvg}</span>`;\n } else {\n btn.style.width = '100%';\n btn.style.height = `${height}px`;\n btn.style.gap = '10px';\n btn.style.paddingLeft = '16px';\n btn.style.paddingRight = '16px';\n const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;\n btn.innerHTML = `<span style=\"display:flex;align-items:center;flex-shrink:0\">${iconSvg}</span><span style=\"font-size:15px;font-weight:600;white-space:nowrap\">${buttonLabel}</span>`;\n }\n\n btn.addEventListener('click', () => handleClick(provider, btn));\n btn.addEventListener('mouseenter', () => (btn.style.opacity = '0.85'));\n btn.addEventListener('mouseleave', () => (btn.style.opacity = '1'));\n\n buttons.push(btn);\n wrapper.appendChild(btn);\n }\n\n container.appendChild(wrapper);\n }\n\n // Init\n client.getProviders().then((p: OAuthProviderType[]) => {\n providers = p;\n if (providers.length > 0) {\n renderButtons(providers);\n }\n });\n\n // Cleanup\n return () => {\n container.innerHTML = '';\n buttons = [];\n };\n}\n"],"mappings":"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","names":["import_js"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Readable } from 'svelte/store';
|
|
2
2
|
import { Authon, AuthonConfig } from '@authon/js';
|
|
3
|
-
import { AuthonUser, OAuthProviderType } from '@authon/shared';
|
|
3
|
+
import { AuthonUser, Web3Chain, Web3WalletType, Web3NonceResponse, Web3Wallet, PasskeyCredential, OAuthProviderType } from '@authon/shared';
|
|
4
|
+
export { PasskeyCredential, Web3Chain, Web3NonceResponse, Web3Wallet, Web3WalletType } from '@authon/shared';
|
|
4
5
|
|
|
5
6
|
interface AuthonStore {
|
|
6
7
|
user: Readable<AuthonUser | null>;
|
|
@@ -12,6 +13,24 @@ interface AuthonStore {
|
|
|
12
13
|
getToken: () => string | null;
|
|
13
14
|
destroy: () => void;
|
|
14
15
|
client: Authon;
|
|
16
|
+
web3GetNonce: (address: string, chain: Web3Chain, walletType: Web3WalletType, chainId?: number) => Promise<Web3NonceResponse>;
|
|
17
|
+
web3Verify: (message: string, signature: string, address: string, chain: Web3Chain, walletType: Web3WalletType) => Promise<AuthonUser>;
|
|
18
|
+
web3LinkWallet: (params: {
|
|
19
|
+
address: string;
|
|
20
|
+
chain: Web3Chain;
|
|
21
|
+
walletType: Web3WalletType;
|
|
22
|
+
chainId?: number;
|
|
23
|
+
message: string;
|
|
24
|
+
signature: string;
|
|
25
|
+
}) => Promise<Web3Wallet>;
|
|
26
|
+
web3UnlinkWallet: (walletId: string) => Promise<void>;
|
|
27
|
+
web3GetWallets: () => Promise<Web3Wallet[]>;
|
|
28
|
+
passwordlessSendCode: (email: string, type?: 'magic-link' | 'otp') => Promise<void>;
|
|
29
|
+
passwordlessVerifyCode: (email: string, code: string) => Promise<AuthonUser>;
|
|
30
|
+
passkeyRegister: (name?: string) => Promise<PasskeyCredential>;
|
|
31
|
+
passkeyAuthenticate: (email?: string) => Promise<AuthonUser>;
|
|
32
|
+
passkeyList: () => Promise<PasskeyCredential[]>;
|
|
33
|
+
passkeyDelete: (credentialId: string) => Promise<void>;
|
|
15
34
|
}
|
|
16
35
|
/**
|
|
17
36
|
* Creates an Authon store with reactive Svelte stores.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Readable } from 'svelte/store';
|
|
2
2
|
import { Authon, AuthonConfig } from '@authon/js';
|
|
3
|
-
import { AuthonUser, OAuthProviderType } from '@authon/shared';
|
|
3
|
+
import { AuthonUser, Web3Chain, Web3WalletType, Web3NonceResponse, Web3Wallet, PasskeyCredential, OAuthProviderType } from '@authon/shared';
|
|
4
|
+
export { PasskeyCredential, Web3Chain, Web3NonceResponse, Web3Wallet, Web3WalletType } from '@authon/shared';
|
|
4
5
|
|
|
5
6
|
interface AuthonStore {
|
|
6
7
|
user: Readable<AuthonUser | null>;
|
|
@@ -12,6 +13,24 @@ interface AuthonStore {
|
|
|
12
13
|
getToken: () => string | null;
|
|
13
14
|
destroy: () => void;
|
|
14
15
|
client: Authon;
|
|
16
|
+
web3GetNonce: (address: string, chain: Web3Chain, walletType: Web3WalletType, chainId?: number) => Promise<Web3NonceResponse>;
|
|
17
|
+
web3Verify: (message: string, signature: string, address: string, chain: Web3Chain, walletType: Web3WalletType) => Promise<AuthonUser>;
|
|
18
|
+
web3LinkWallet: (params: {
|
|
19
|
+
address: string;
|
|
20
|
+
chain: Web3Chain;
|
|
21
|
+
walletType: Web3WalletType;
|
|
22
|
+
chainId?: number;
|
|
23
|
+
message: string;
|
|
24
|
+
signature: string;
|
|
25
|
+
}) => Promise<Web3Wallet>;
|
|
26
|
+
web3UnlinkWallet: (walletId: string) => Promise<void>;
|
|
27
|
+
web3GetWallets: () => Promise<Web3Wallet[]>;
|
|
28
|
+
passwordlessSendCode: (email: string, type?: 'magic-link' | 'otp') => Promise<void>;
|
|
29
|
+
passwordlessVerifyCode: (email: string, code: string) => Promise<AuthonUser>;
|
|
30
|
+
passkeyRegister: (name?: string) => Promise<PasskeyCredential>;
|
|
31
|
+
passkeyAuthenticate: (email?: string) => Promise<AuthonUser>;
|
|
32
|
+
passkeyList: () => Promise<PasskeyCredential[]>;
|
|
33
|
+
passkeyDelete: (credentialId: string) => Promise<void>;
|
|
15
34
|
}
|
|
16
35
|
/**
|
|
17
36
|
* Creates an Authon store with reactive Svelte stores.
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,21 @@ function createAuthonStore(publishableKey, config) {
|
|
|
33
33
|
openSignUp: () => client.openSignUp(),
|
|
34
34
|
getToken: () => client.getToken(),
|
|
35
35
|
destroy: () => client.destroy(),
|
|
36
|
-
client
|
|
36
|
+
client,
|
|
37
|
+
// Web3
|
|
38
|
+
web3GetNonce: (address, chain, walletType, chainId) => client.web3GetNonce(address, chain, walletType, chainId),
|
|
39
|
+
web3Verify: (message, signature, address, chain, walletType) => client.web3Verify(message, signature, address, chain, walletType),
|
|
40
|
+
web3LinkWallet: (params) => client.linkWallet(params),
|
|
41
|
+
web3UnlinkWallet: (walletId) => client.unlinkWallet(walletId),
|
|
42
|
+
web3GetWallets: () => client.listWallets(),
|
|
43
|
+
// Passwordless
|
|
44
|
+
passwordlessSendCode: (email, type = "otp") => type === "magic-link" ? client.sendMagicLink(email) : client.sendEmailOtp(email),
|
|
45
|
+
passwordlessVerifyCode: (email, code) => client.verifyPasswordless({ email, code }),
|
|
46
|
+
// Passkeys
|
|
47
|
+
passkeyRegister: (name) => client.registerPasskey(name),
|
|
48
|
+
passkeyAuthenticate: (email) => client.authenticateWithPasskey(email),
|
|
49
|
+
passkeyList: () => client.listPasskeys(),
|
|
50
|
+
passkeyDelete: (credentialId) => client.revokePasskey(credentialId)
|
|
37
51
|
};
|
|
38
52
|
}
|
|
39
53
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store.ts","../src/context.ts","../src/SocialButtons.ts"],"sourcesContent":["import { writable, derived, type Readable } from 'svelte/store';\nimport { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\nexport interface AuthonStore {\n user: Readable<AuthonUser | null>;\n isSignedIn: Readable<boolean>;\n isLoading: Readable<boolean>;\n signOut: () => Promise<void>;\n openSignIn: () => Promise<void>;\n openSignUp: () => Promise<void>;\n getToken: () => string | null;\n destroy: () => void;\n client: Authon;\n}\n\n/**\n * Creates an Authon store with reactive Svelte stores.\n *\n * Usage:\n * ```ts\n * import { createAuthonStore } from '@authon/svelte'\n *\n * const authon = createAuthonStore('pk_live_...')\n *\n * // In your component:\n * $: user = $authon.user\n * $: isSignedIn = $authon.isSignedIn\n * ```\n */\nexport function createAuthonStore(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const client = new Authon(publishableKey, config);\n const userStore = writable<AuthonUser | null>(null);\n const isLoadingStore = writable(true);\n\n const isSignedIn = derived(userStore, ($user) => $user !== null);\n\n client.on('signedIn', (user) => {\n userStore.set(user as AuthonUser);\n isLoadingStore.set(false);\n });\n\n client.on('signedOut', () => {\n userStore.set(null);\n });\n\n client.on('error', () => {\n isLoadingStore.set(false);\n });\n\n const existingUser = client.getUser();\n if (existingUser) {\n userStore.set(existingUser);\n }\n isLoadingStore.set(false);\n\n return {\n user: { subscribe: userStore.subscribe },\n isSignedIn,\n isLoading: { subscribe: isLoadingStore.subscribe },\n signOut: async () => {\n await client.signOut();\n userStore.set(null);\n },\n openSignIn: () => client.openSignIn(),\n openSignUp: () => client.openSignUp(),\n getToken: () => client.getToken(),\n destroy: () => client.destroy(),\n client,\n };\n}\n","import { setContext, getContext } from 'svelte';\nimport type { AuthonConfig } from '@authon/js';\nimport { createAuthonStore, type AuthonStore } from './store';\n\nconst AUTHON_CONTEXT_KEY = Symbol('authon');\n\n/**\n * Initialize Authon in a Svelte component tree.\n * Call this in your root layout or top-level component.\n *\n * Usage in +layout.svelte:\n * ```svelte\n * <script>\n * import { initAuthon } from '@authon/svelte'\n * const authon = initAuthon('pk_live_...')\n * </script>\n * ```\n */\nexport function initAuthon(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const store = createAuthonStore(publishableKey, config);\n setContext(AUTHON_CONTEXT_KEY, store);\n return store;\n}\n\n/**\n * Get the Authon store from Svelte context.\n * Must be called within a component tree where `initAuthon` was called.\n *\n * Usage:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * const { user, isSignedIn, signOut } = getAuthon()\n * </script>\n * ```\n */\nexport function getAuthon(): AuthonStore {\n const store = getContext<AuthonStore | undefined>(AUTHON_CONTEXT_KEY);\n if (!store) {\n throw new Error('getAuthon() must be called within a component tree where initAuthon() was called.');\n }\n return store;\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { getProviderButtonConfig, type Authon } from '@authon/js';\n\nexport interface SocialButtonsOptions {\n /** Authon client instance */\n client: Authon;\n /** Target container element */\n container: HTMLElement;\n /** Called after successful OAuth sign-in */\n onSuccess?: () => void;\n /** Called on OAuth error */\n onError?: (error: Error) => void;\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Gap between buttons in px (default: 10, compact default: 12) */\n gap?: number;\n /** Custom labels per provider */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius in px (default: 10) */\n borderRadius?: number;\n /** Button height in px (default: 48) */\n height?: number;\n /** Button size for compact mode in px (default: 48) */\n size?: number;\n}\n\n/**\n * Render social login buttons into a container element.\n *\n * Usage in +page.svelte:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * import { renderSocialButtons } from '@authon/svelte'\n * import { onMount } from 'svelte'\n *\n * const { client } = getAuthon()\n * let container: HTMLElement\n *\n * onMount(() => {\n * const cleanup = renderSocialButtons({\n * client,\n * container,\n * compact: true,\n * onError: (err) => console.error(err),\n * })\n * return cleanup\n * })\n * </script>\n *\n * <div bind:this={container}></div>\n * ```\n */\nexport function renderSocialButtons(options: SocialButtonsOptions): () => void {\n const {\n client,\n container,\n onSuccess,\n onError,\n compact = false,\n gap,\n labels,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n } = options;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n let loadingProvider: string | null = null;\n let buttons: HTMLButtonElement[] = [];\n\n const handleClick = async (provider: OAuthProviderType, btn: HTMLButtonElement) => {\n if (loadingProvider) return;\n loadingProvider = provider;\n btn.innerHTML = '<span style=\"display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite\"></span>';\n buttons.forEach((b) => (b.disabled = true));\n\n try {\n await client.signInWithOAuth(provider);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n loadingProvider = null;\n renderButtons(providers);\n }\n };\n\n let providers: OAuthProviderType[] = [];\n\n function renderButtons(providerList: OAuthProviderType[]) {\n container.innerHTML = '';\n buttons = [];\n\n // Inject keyframe if not present\n if (!document.getElementById('authon-spin-style')) {\n const style = document.createElement('style');\n style.id = 'authon-spin-style';\n style.textContent = '@keyframes authon-spin{to{transform:rotate(360deg)}}';\n document.head.appendChild(style);\n }\n\n const wrapper = document.createElement('div');\n wrapper.style.display = 'flex';\n wrapper.style.gap = `${resolvedGap}px`;\n\n if (compact) {\n wrapper.style.flexDirection = 'row';\n wrapper.style.flexWrap = 'wrap';\n wrapper.style.justifyContent = 'center';\n } else {\n wrapper.style.flexDirection = 'column';\n }\n\n for (const provider of providerList) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const config = getProviderButtonConfig(provider);\n const iconSvg = config.iconSvg\n .replace(/width=\"\\d+\"/, `width=\"${resolvedIconSize}\"`)\n .replace(/height=\"\\d+\"/, `height=\"${resolvedIconSize}\"`);\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n\n const btn = document.createElement('button');\n btn.setAttribute('aria-label', `Sign in with ${displayName}`);\n btn.style.display = 'flex';\n btn.style.alignItems = 'center';\n btn.style.justifyContent = 'center';\n btn.style.border = needsBorder ? '1px solid #dadce0' : 'none';\n btn.style.cursor = 'pointer';\n btn.style.backgroundColor = colors.bg;\n btn.style.color = colors.text;\n btn.style.borderRadius = `${borderRadius}px`;\n btn.style.transition = 'opacity 0.15s';\n btn.style.fontFamily = 'inherit';\n\n if (compact) {\n btn.style.width = `${size}px`;\n btn.style.height = `${size}px`;\n btn.style.padding = '0';\n btn.innerHTML = `<span style=\"display:flex;align-items:center\">${iconSvg}</span>`;\n } else {\n btn.style.width = '100%';\n btn.style.height = `${height}px`;\n btn.style.gap = '10px';\n btn.style.paddingLeft = '16px';\n btn.style.paddingRight = '16px';\n const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;\n btn.innerHTML = `<span style=\"display:flex;align-items:center;flex-shrink:0\">${iconSvg}</span><span style=\"font-size:15px;font-weight:600;white-space:nowrap\">${buttonLabel}</span>`;\n }\n\n btn.addEventListener('click', () => handleClick(provider, btn));\n btn.addEventListener('mouseenter', () => (btn.style.opacity = '0.85'));\n btn.addEventListener('mouseleave', () => (btn.style.opacity = '1'));\n\n buttons.push(btn);\n wrapper.appendChild(btn);\n }\n\n container.appendChild(wrapper);\n }\n\n // Init\n client.getProviders().then((p: OAuthProviderType[]) => {\n providers = p;\n if (providers.length > 0) {\n renderButtons(providers);\n }\n });\n\n // Cleanup\n return () => {\n container.innerHTML = '';\n buttons = [];\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/store.ts","../src/context.ts","../src/SocialButtons.ts"],"sourcesContent":["import { writable, derived, type Readable } from 'svelte/store';\nimport { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type {\n AuthonUser,\n PasskeyCredential,\n Web3Chain,\n Web3NonceResponse,\n Web3Wallet,\n Web3WalletType,\n} from '@authon/shared';\n\nexport interface AuthonStore {\n user: Readable<AuthonUser | null>;\n isSignedIn: Readable<boolean>;\n isLoading: Readable<boolean>;\n signOut: () => Promise<void>;\n openSignIn: () => Promise<void>;\n openSignUp: () => Promise<void>;\n getToken: () => string | null;\n destroy: () => void;\n client: Authon;\n // Web3\n web3GetNonce: (address: string, chain: Web3Chain, walletType: Web3WalletType, chainId?: number) => Promise<Web3NonceResponse>;\n web3Verify: (message: string, signature: string, address: string, chain: Web3Chain, walletType: Web3WalletType) => Promise<AuthonUser>;\n web3LinkWallet: (params: { address: string; chain: Web3Chain; walletType: Web3WalletType; chainId?: number; message: string; signature: string }) => Promise<Web3Wallet>;\n web3UnlinkWallet: (walletId: string) => Promise<void>;\n web3GetWallets: () => Promise<Web3Wallet[]>;\n // Passwordless\n passwordlessSendCode: (email: string, type?: 'magic-link' | 'otp') => Promise<void>;\n passwordlessVerifyCode: (email: string, code: string) => Promise<AuthonUser>;\n // Passkeys\n passkeyRegister: (name?: string) => Promise<PasskeyCredential>;\n passkeyAuthenticate: (email?: string) => Promise<AuthonUser>;\n passkeyList: () => Promise<PasskeyCredential[]>;\n passkeyDelete: (credentialId: string) => Promise<void>;\n}\n\n/**\n * Creates an Authon store with reactive Svelte stores.\n *\n * Usage:\n * ```ts\n * import { createAuthonStore } from '@authon/svelte'\n *\n * const authon = createAuthonStore('pk_live_...')\n *\n * // In your component:\n * $: user = $authon.user\n * $: isSignedIn = $authon.isSignedIn\n * ```\n */\nexport function createAuthonStore(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const client = new Authon(publishableKey, config);\n const userStore = writable<AuthonUser | null>(null);\n const isLoadingStore = writable(true);\n\n const isSignedIn = derived(userStore, ($user) => $user !== null);\n\n client.on('signedIn', (user) => {\n userStore.set(user as AuthonUser);\n isLoadingStore.set(false);\n });\n\n client.on('signedOut', () => {\n userStore.set(null);\n });\n\n client.on('error', () => {\n isLoadingStore.set(false);\n });\n\n const existingUser = client.getUser();\n if (existingUser) {\n userStore.set(existingUser);\n }\n isLoadingStore.set(false);\n\n return {\n user: { subscribe: userStore.subscribe },\n isSignedIn,\n isLoading: { subscribe: isLoadingStore.subscribe },\n signOut: async () => {\n await client.signOut();\n userStore.set(null);\n },\n openSignIn: () => client.openSignIn(),\n openSignUp: () => client.openSignUp(),\n getToken: () => client.getToken(),\n destroy: () => client.destroy(),\n client,\n // Web3\n web3GetNonce: (address, chain, walletType, chainId?) =>\n client.web3GetNonce(address, chain, walletType, chainId),\n web3Verify: (message, signature, address, chain, walletType) =>\n client.web3Verify(message, signature, address, chain, walletType),\n web3LinkWallet: (params) => client.linkWallet(params),\n web3UnlinkWallet: (walletId) => client.unlinkWallet(walletId),\n web3GetWallets: () => client.listWallets(),\n // Passwordless\n passwordlessSendCode: (email, type = 'otp') =>\n type === 'magic-link' ? client.sendMagicLink(email) : client.sendEmailOtp(email),\n passwordlessVerifyCode: (email, code) => client.verifyPasswordless({ email, code }),\n // Passkeys\n passkeyRegister: (name?) => client.registerPasskey(name),\n passkeyAuthenticate: (email?) => client.authenticateWithPasskey(email),\n passkeyList: () => client.listPasskeys(),\n passkeyDelete: (credentialId) => client.revokePasskey(credentialId),\n };\n}\n","import { setContext, getContext } from 'svelte';\nimport type { AuthonConfig } from '@authon/js';\nimport { createAuthonStore, type AuthonStore } from './store';\n\nconst AUTHON_CONTEXT_KEY = Symbol('authon');\n\n/**\n * Initialize Authon in a Svelte component tree.\n * Call this in your root layout or top-level component.\n *\n * Usage in +layout.svelte:\n * ```svelte\n * <script>\n * import { initAuthon } from '@authon/svelte'\n * const authon = initAuthon('pk_live_...')\n * </script>\n * ```\n */\nexport function initAuthon(\n publishableKey: string,\n config?: Omit<AuthonConfig, 'mode'>,\n): AuthonStore {\n const store = createAuthonStore(publishableKey, config);\n setContext(AUTHON_CONTEXT_KEY, store);\n return store;\n}\n\n/**\n * Get the Authon store from Svelte context.\n * Must be called within a component tree where `initAuthon` was called.\n *\n * Usage:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * const { user, isSignedIn, signOut } = getAuthon()\n * </script>\n * ```\n */\nexport function getAuthon(): AuthonStore {\n const store = getContext<AuthonStore | undefined>(AUTHON_CONTEXT_KEY);\n if (!store) {\n throw new Error('getAuthon() must be called within a component tree where initAuthon() was called.');\n }\n return store;\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { getProviderButtonConfig, type Authon } from '@authon/js';\n\nexport interface SocialButtonsOptions {\n /** Authon client instance */\n client: Authon;\n /** Target container element */\n container: HTMLElement;\n /** Called after successful OAuth sign-in */\n onSuccess?: () => void;\n /** Called on OAuth error */\n onError?: (error: Error) => void;\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Gap between buttons in px (default: 10, compact default: 12) */\n gap?: number;\n /** Custom labels per provider */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius in px (default: 10) */\n borderRadius?: number;\n /** Button height in px (default: 48) */\n height?: number;\n /** Button size for compact mode in px (default: 48) */\n size?: number;\n}\n\n/**\n * Render social login buttons into a container element.\n *\n * Usage in +page.svelte:\n * ```svelte\n * <script>\n * import { getAuthon } from '@authon/svelte'\n * import { renderSocialButtons } from '@authon/svelte'\n * import { onMount } from 'svelte'\n *\n * const { client } = getAuthon()\n * let container: HTMLElement\n *\n * onMount(() => {\n * const cleanup = renderSocialButtons({\n * client,\n * container,\n * compact: true,\n * onError: (err) => console.error(err),\n * })\n * return cleanup\n * })\n * </script>\n *\n * <div bind:this={container}></div>\n * ```\n */\nexport function renderSocialButtons(options: SocialButtonsOptions): () => void {\n const {\n client,\n container,\n onSuccess,\n onError,\n compact = false,\n gap,\n labels,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n } = options;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n let loadingProvider: string | null = null;\n let buttons: HTMLButtonElement[] = [];\n\n const handleClick = async (provider: OAuthProviderType, btn: HTMLButtonElement) => {\n if (loadingProvider) return;\n loadingProvider = provider;\n btn.innerHTML = '<span style=\"display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite\"></span>';\n buttons.forEach((b) => (b.disabled = true));\n\n try {\n await client.signInWithOAuth(provider);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n loadingProvider = null;\n renderButtons(providers);\n }\n };\n\n let providers: OAuthProviderType[] = [];\n\n function renderButtons(providerList: OAuthProviderType[]) {\n container.innerHTML = '';\n buttons = [];\n\n // Inject keyframe if not present\n if (!document.getElementById('authon-spin-style')) {\n const style = document.createElement('style');\n style.id = 'authon-spin-style';\n style.textContent = '@keyframes authon-spin{to{transform:rotate(360deg)}}';\n document.head.appendChild(style);\n }\n\n const wrapper = document.createElement('div');\n wrapper.style.display = 'flex';\n wrapper.style.gap = `${resolvedGap}px`;\n\n if (compact) {\n wrapper.style.flexDirection = 'row';\n wrapper.style.flexWrap = 'wrap';\n wrapper.style.justifyContent = 'center';\n } else {\n wrapper.style.flexDirection = 'column';\n }\n\n for (const provider of providerList) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const config = getProviderButtonConfig(provider);\n const iconSvg = config.iconSvg\n .replace(/width=\"\\d+\"/, `width=\"${resolvedIconSize}\"`)\n .replace(/height=\"\\d+\"/, `height=\"${resolvedIconSize}\"`);\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n\n const btn = document.createElement('button');\n btn.setAttribute('aria-label', `Sign in with ${displayName}`);\n btn.style.display = 'flex';\n btn.style.alignItems = 'center';\n btn.style.justifyContent = 'center';\n btn.style.border = needsBorder ? '1px solid #dadce0' : 'none';\n btn.style.cursor = 'pointer';\n btn.style.backgroundColor = colors.bg;\n btn.style.color = colors.text;\n btn.style.borderRadius = `${borderRadius}px`;\n btn.style.transition = 'opacity 0.15s';\n btn.style.fontFamily = 'inherit';\n\n if (compact) {\n btn.style.width = `${size}px`;\n btn.style.height = `${size}px`;\n btn.style.padding = '0';\n btn.innerHTML = `<span style=\"display:flex;align-items:center\">${iconSvg}</span>`;\n } else {\n btn.style.width = '100%';\n btn.style.height = `${height}px`;\n btn.style.gap = '10px';\n btn.style.paddingLeft = '16px';\n btn.style.paddingRight = '16px';\n const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;\n btn.innerHTML = `<span style=\"display:flex;align-items:center;flex-shrink:0\">${iconSvg}</span><span style=\"font-size:15px;font-weight:600;white-space:nowrap\">${buttonLabel}</span>`;\n }\n\n btn.addEventListener('click', () => handleClick(provider, btn));\n btn.addEventListener('mouseenter', () => (btn.style.opacity = '0.85'));\n btn.addEventListener('mouseleave', () => (btn.style.opacity = '1'));\n\n buttons.push(btn);\n wrapper.appendChild(btn);\n }\n\n container.appendChild(wrapper);\n }\n\n // Init\n client.getProviders().then((p: OAuthProviderType[]) => {\n providers = p;\n if (providers.length > 0) {\n renderButtons(providers);\n }\n });\n\n // Cleanup\n return () => {\n container.innerHTML = '';\n buttons = [];\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@authon/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Authon Svelte SDK — stores and components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -11,10 +11,13 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
|
-
}
|
|
14
|
+
},
|
|
15
|
+
"./SignIn.svelte": "./src/components/SignIn.svelte",
|
|
16
|
+
"./SignUp.svelte": "./src/components/SignUp.svelte"
|
|
15
17
|
},
|
|
16
18
|
"files": [
|
|
17
|
-
"dist"
|
|
19
|
+
"dist",
|
|
20
|
+
"src/components"
|
|
18
21
|
],
|
|
19
22
|
"scripts": {
|
|
20
23
|
"build": "tsup",
|
|
@@ -37,8 +40,8 @@
|
|
|
37
40
|
"store"
|
|
38
41
|
],
|
|
39
42
|
"dependencies": {
|
|
40
|
-
"@authon/js": "
|
|
41
|
-
"@authon/shared": "
|
|
43
|
+
"@authon/js": "workspace:^",
|
|
44
|
+
"@authon/shared": "workspace:^"
|
|
42
45
|
},
|
|
43
46
|
"peerDependencies": {
|
|
44
47
|
"svelte": "^4.0.0 || ^5.0.0"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, onDestroy, createEventDispatcher } from 'svelte';
|
|
3
|
+
import { Authon } from '@authon/js';
|
|
4
|
+
import type { AuthonUser } from '@authon/shared';
|
|
5
|
+
|
|
6
|
+
export let publishableKey: string;
|
|
7
|
+
export let apiUrl: string = 'https://api.authon.dev';
|
|
8
|
+
export let theme: 'light' | 'dark' | 'auto' = 'auto';
|
|
9
|
+
export let locale: string | undefined = undefined;
|
|
10
|
+
|
|
11
|
+
const dispatch = createEventDispatcher<{ signIn: { user: AuthonUser } }>();
|
|
12
|
+
|
|
13
|
+
let container: HTMLDivElement;
|
|
14
|
+
let authonInstance: Authon | null = null;
|
|
15
|
+
let unsubscribe: (() => void) | null = null;
|
|
16
|
+
const containerId = `authon-signin-${Math.random().toString(36).slice(2, 8)}`;
|
|
17
|
+
|
|
18
|
+
onMount(() => {
|
|
19
|
+
container.id = containerId;
|
|
20
|
+
authonInstance = new Authon(publishableKey, {
|
|
21
|
+
mode: 'embedded',
|
|
22
|
+
containerId,
|
|
23
|
+
apiUrl,
|
|
24
|
+
theme,
|
|
25
|
+
locale,
|
|
26
|
+
});
|
|
27
|
+
unsubscribe = authonInstance.on('signedIn', (user) => {
|
|
28
|
+
dispatch('signIn', { user: user as AuthonUser });
|
|
29
|
+
});
|
|
30
|
+
authonInstance.openSignIn();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
onDestroy(() => {
|
|
34
|
+
unsubscribe?.();
|
|
35
|
+
authonInstance?.destroy();
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div bind:this={container}></div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, onDestroy, createEventDispatcher } from 'svelte';
|
|
3
|
+
import { Authon } from '@authon/js';
|
|
4
|
+
import type { AuthonUser } from '@authon/shared';
|
|
5
|
+
|
|
6
|
+
export let publishableKey: string;
|
|
7
|
+
export let apiUrl: string = 'https://api.authon.dev';
|
|
8
|
+
export let theme: 'light' | 'dark' | 'auto' = 'auto';
|
|
9
|
+
export let locale: string | undefined = undefined;
|
|
10
|
+
|
|
11
|
+
const dispatch = createEventDispatcher<{ signUp: { user: AuthonUser } }>();
|
|
12
|
+
|
|
13
|
+
let container: HTMLDivElement;
|
|
14
|
+
let authonInstance: Authon | null = null;
|
|
15
|
+
let unsubscribe: (() => void) | null = null;
|
|
16
|
+
const containerId = `authon-signup-${Math.random().toString(36).slice(2, 8)}`;
|
|
17
|
+
|
|
18
|
+
onMount(() => {
|
|
19
|
+
container.id = containerId;
|
|
20
|
+
authonInstance = new Authon(publishableKey, {
|
|
21
|
+
mode: 'embedded',
|
|
22
|
+
containerId,
|
|
23
|
+
apiUrl,
|
|
24
|
+
theme,
|
|
25
|
+
locale,
|
|
26
|
+
});
|
|
27
|
+
unsubscribe = authonInstance.on('signedIn', (user) => {
|
|
28
|
+
dispatch('signUp', { user: user as AuthonUser });
|
|
29
|
+
});
|
|
30
|
+
authonInstance.openSignUp();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
onDestroy(() => {
|
|
34
|
+
unsubscribe?.();
|
|
35
|
+
authonInstance?.destroy();
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div bind:this={container}></div>
|