@saasmakers/ui 2.0.10 → 2.0.12

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.
@@ -1,5 +1,6 @@
1
1
  html,
2
2
  body {
3
+ scrollbar-gutter: stable;
3
4
  touch-action: manipulation;
4
5
  }
5
6
 
@@ -0,0 +1,225 @@
1
+ <script lang="ts" setup>
2
+ import { isSocialLoginCancellation } from '../../utils/auth'
3
+
4
+ const props = withDefaults(defineProps<AuthBox>(), {
5
+ action: 'login',
6
+ hasBox: false,
7
+ })
8
+
9
+ const { t } = useI18n()
10
+ const { isAndroid } = useCapacitor()
11
+ const isClosed = ref(false)
12
+ const emailToReactivate = ref('')
13
+ const reactivatingAccount = ref(false)
14
+ const reactivationSuccessful = ref(false)
15
+
16
+ const authenticating = reactive({
17
+ apple: false,
18
+ google: false,
19
+ })
20
+
21
+ onMounted(() => {
22
+ if (isClosed.value) {
23
+ isClosed.value = false
24
+ }
25
+ })
26
+
27
+ function onAccountClosed(email: string) {
28
+ emailToReactivate.value = email
29
+ isClosed.value = true
30
+ }
31
+
32
+ async function onReactivateAccount() {
33
+ reactivatingAccount.value = true
34
+
35
+ try {
36
+ await props.onReactivate({ email: emailToReactivate.value })
37
+
38
+ isClosed.value = false
39
+ reactivationSuccessful.value = true
40
+ }
41
+ catch (error) {
42
+ console.error(error)
43
+ }
44
+ finally {
45
+ reactivatingAccount.value = false
46
+ }
47
+ }
48
+
49
+ function onSocialConnectError(error: unknown) {
50
+ if (isSocialLoginCancellation(error)) {
51
+ return
52
+ }
53
+
54
+ console.error(error)
55
+ }
56
+
57
+ async function onSocialConnectSuccess(payload: AuthSocialConnectSuccess) {
58
+ authenticating[payload.provider] = true
59
+
60
+ try {
61
+ const result = await props.onSocialLogin(payload)
62
+
63
+ if (result.isClosed) {
64
+ onAccountClosed(result.email ?? '')
65
+ }
66
+ }
67
+ catch (error) {
68
+ console.error(error)
69
+ }
70
+ finally {
71
+ authenticating[payload.provider] = false
72
+ }
73
+ }
74
+ </script>
75
+
76
+ <template>
77
+ <div
78
+ class="flex flex-col items-center"
79
+ :class="{ 'rounded-lg bg-gray-100 dark:bg-gray-900 border shadow-sm border-gray-200 dark:border-gray-800 p-6 sm:p-10': hasBox }"
80
+ >
81
+ <div class="w-full flex flex-col gap-6 sm:w-96">
82
+ <BaseAlert
83
+ v-if="isClosed"
84
+ size="xs"
85
+ status="error"
86
+ >
87
+ <div class="flex flex-col gap-2 text-xs">
88
+ <span>{{ t('authUserAccountClosed') }}</span>
89
+
90
+ <span
91
+ v-if="!reactivatingAccount"
92
+ class="cursor-pointer underline"
93
+ role="button"
94
+ tabindex="0"
95
+ @click="onReactivateAccount"
96
+ @keydown.enter="onReactivateAccount"
97
+ @keydown.space.prevent="onReactivateAccount"
98
+ >
99
+ {{ t('reactivateAccount') }}
100
+ </span>
101
+
102
+ <span v-else>
103
+ {{ t('reactivatingAccount') }}
104
+ </span>
105
+ </div>
106
+ </BaseAlert>
107
+
108
+ <BaseAlert
109
+ v-else-if="reactivationSuccessful"
110
+ size="xs"
111
+ status="success"
112
+ :text="t('reactivationSuccessful')"
113
+ />
114
+
115
+ <div class="flex flex-col gap-4">
116
+ <AuthSocialConnect
117
+ v-if="!isAndroid"
118
+ :apple-config="appleConfig"
119
+ :loading="authenticating.apple"
120
+ provider="apple"
121
+ @error="onSocialConnectError"
122
+ @success="onSocialConnectSuccess"
123
+ />
124
+
125
+ <AuthSocialConnect
126
+ :google-config="googleConfig"
127
+ :loading="authenticating.google"
128
+ provider="google"
129
+ @error="onSocialConnectError"
130
+ @success="onSocialConnectSuccess"
131
+ />
132
+ </div>
133
+
134
+ <AuthEmailConnect
135
+ :action="action"
136
+ :on-forgot-password="onForgotPassword"
137
+ :on-login="onLogin"
138
+ @account-closed="onAccountClosed"
139
+ />
140
+ </div>
141
+ </div>
142
+ </template>
143
+
144
+ <i18n lang="json">
145
+ {
146
+ "de": {
147
+ "authUserAccountClosed": "Dein Konto ist geschlossen",
148
+ "reactivateAccount": "Klicke hier, um es zu reaktivieren",
149
+ "reactivatingAccount": "Dein Konto wird reaktiviert...",
150
+ "reactivationSuccessful": "Dein Konto wurde reaktiviert. Du kannst dich jetzt wieder anmelden."
151
+ },
152
+ "en": {
153
+ "authUserAccountClosed": "Your account is closed",
154
+ "reactivateAccount": "Click here to reactivate it",
155
+ "reactivatingAccount": "Reactivating your account...",
156
+ "reactivationSuccessful": "Your account has been reactivated. You can now sign in again."
157
+ },
158
+ "es": {
159
+ "authUserAccountClosed": "Tu cuenta está cerrada",
160
+ "reactivateAccount": "Haz clic aquí para reactivarla",
161
+ "reactivatingAccount": "Reactivando tu cuenta...",
162
+ "reactivationSuccessful": "Tu cuenta ha sido reactivada. Ya puedes iniciar sesión de nuevo."
163
+ },
164
+ "fr": {
165
+ "authUserAccountClosed": "Votre compte est fermé",
166
+ "reactivateAccount": "Cliquez ici pour le réactiver",
167
+ "reactivatingAccount": "Réactivation de votre compte...",
168
+ "reactivationSuccessful": "Votre compte a été réactivé. Vous pouvez désormais vous reconnecter."
169
+ },
170
+ "id": {
171
+ "authUserAccountClosed": "Akun Anda ditutup",
172
+ "reactivateAccount": "Klik di sini untuk mengaktifkannya kembali",
173
+ "reactivatingAccount": "Mengaktifkan kembali akun Anda...",
174
+ "reactivationSuccessful": "Akun Anda telah diaktifkan kembali. Anda sekarang dapat masuk kembali."
175
+ },
176
+ "it": {
177
+ "authUserAccountClosed": "Il tuo account è chiuso",
178
+ "reactivateAccount": "Clicca qui per riattivarlo",
179
+ "reactivatingAccount": "Riattivazione dell'account...",
180
+ "reactivationSuccessful": "Il tuo account è stato riattivato. Ora puoi accedere di nuovo."
181
+ },
182
+ "ja": {
183
+ "authUserAccountClosed": "あなたのアカウントは閉じられています",
184
+ "reactivateAccount": "ここをクリックして再活性化してください",
185
+ "reactivatingAccount": "アカウントを再活性化しています...",
186
+ "reactivationSuccessful": "アカウントが再活性化されました。再度ログインできます。"
187
+ },
188
+ "ko": {
189
+ "authUserAccountClosed": "계정이 닫혀 있습니다",
190
+ "reactivateAccount": "여기를 눌러 다시 활성화하세요",
191
+ "reactivatingAccount": "계정을 다시 활성화하는 중...",
192
+ "reactivationSuccessful": "계정이 다시 활성화되었습니다. 이제 다시 로그인할 수 있습니다."
193
+ },
194
+ "nl": {
195
+ "authUserAccountClosed": "Je account is gesloten",
196
+ "reactivateAccount": "Klik hier om het te reactiveren",
197
+ "reactivatingAccount": "Je account wordt gereactiveerd...",
198
+ "reactivationSuccessful": "Je account is gereactiveerd. Je kunt je nu opnieuw aanmelden."
199
+ },
200
+ "pl": {
201
+ "authUserAccountClosed": "Twoje konto jest zamknięte",
202
+ "reactivateAccount": "Kliknij tutaj, aby je reaktywować",
203
+ "reactivatingAccount": "Reaktywacja Twojego konta...",
204
+ "reactivationSuccessful": "Twoje konto zostało reaktywowane. Możesz się teraz ponownie zalogować."
205
+ },
206
+ "pt": {
207
+ "authUserAccountClosed": "A tua conta está encerrada",
208
+ "reactivateAccount": "Clica aqui para reativar",
209
+ "reactivatingAccount": "A reativar a tua conta...",
210
+ "reactivationSuccessful": "A tua conta foi reativada. Já podes iniciar sessão novamente."
211
+ },
212
+ "pt-BR": {
213
+ "authUserAccountClosed": "Sua conta está encerrada",
214
+ "reactivateAccount": "Clique aqui para reativar",
215
+ "reactivatingAccount": "Reativando sua conta...",
216
+ "reactivationSuccessful": "Sua conta foi reativada. Agora você pode entrar novamente."
217
+ },
218
+ "vi": {
219
+ "authUserAccountClosed": "Tài khoản của bạn đã đóng",
220
+ "reactivateAccount": "Nhấn vào đây để kích hoạt lại",
221
+ "reactivatingAccount": "Đang kích hoạt lại tài khoản của bạn...",
222
+ "reactivationSuccessful": "Tài khoản của bạn đã được kích hoạt lại. Bạn có thể đăng nhập lại ngay bây giờ."
223
+ }
224
+ }
225
+ </i18n>
@@ -0,0 +1,486 @@
1
+ <script lang="ts" setup>
2
+ import useVuelidate from '@vuelidate/core'
3
+ import { email, maxLength, minLength, required, requiredIf } from '@vuelidate/validators'
4
+
5
+ const props = withDefaults(defineProps<AuthEmailConnect>(), {
6
+ action: 'login',
7
+ size: 'base',
8
+ })
9
+
10
+ const emit = defineEmits<{
11
+ accountClosed: [email: string]
12
+ }>()
13
+
14
+ const currentWindow = ref<AuthEmailConnectCurrentWindow>('login')
15
+ const forgettingPassword = ref(false)
16
+ const loggingWithEmail = ref(false)
17
+ const resettingTurnstile = ref(true)
18
+
19
+ const turnstile = ref<{
20
+ reset: () => void
21
+ }>()
22
+
23
+ const { t } = useI18n()
24
+
25
+ const form = reactive({
26
+ captchaToken: '',
27
+ email: '',
28
+ password: '',
29
+ })
30
+
31
+ const v$ = useVuelidate({
32
+ email: {
33
+ email,
34
+ required,
35
+ },
36
+ password: {
37
+ maxLength: maxLength(255),
38
+ minLength: minLength(6),
39
+ required: requiredIf(() => currentWindow.value === 'login'),
40
+ },
41
+ }, form)
42
+
43
+ watch(
44
+ () => form.captchaToken,
45
+ (captchaToken) => {
46
+ resettingTurnstile.value = !captchaToken
47
+ },
48
+ { immediate: true },
49
+ )
50
+
51
+ async function onForgotPassword() {
52
+ try {
53
+ v$.value.$touch()
54
+
55
+ if (!v$.value.$invalid && !forgettingPassword.value) {
56
+ forgettingPassword.value = true
57
+
58
+ const result = await props.onForgotPassword({ email: form.email })
59
+
60
+ if (result.isClosed) {
61
+ emit('accountClosed', result.email ?? '')
62
+ }
63
+ else {
64
+ v$.value.$reset()
65
+ }
66
+ }
67
+ }
68
+ catch (error) {
69
+ console.error(error)
70
+ }
71
+
72
+ forgettingPassword.value = false
73
+ }
74
+
75
+ async function onLogin() {
76
+ try {
77
+ v$.value.$touch()
78
+
79
+ if (!v$.value.$invalid && !loggingWithEmail.value && !resettingTurnstile.value) {
80
+ loggingWithEmail.value = true
81
+
82
+ const result = await props.onLogin({
83
+ captchaToken: form.captchaToken,
84
+ email: form.email,
85
+ password: form.password,
86
+ })
87
+
88
+ if (result.isClosed) {
89
+ emit('accountClosed', result.email ?? '')
90
+ }
91
+ else {
92
+ v$.value.$reset()
93
+ }
94
+ }
95
+ }
96
+ catch (error) {
97
+ console.error(error)
98
+ }
99
+ finally {
100
+ form.captchaToken = ''
101
+
102
+ turnstile.value?.reset()
103
+
104
+ loggingWithEmail.value = false
105
+ }
106
+ }
107
+
108
+ function onUpdateCurrentWindow(newCurrentWindow: AuthEmailConnectCurrentWindow) {
109
+ currentWindow.value = newCurrentWindow
110
+
111
+ v$.value.$reset()
112
+ }
113
+ </script>
114
+
115
+ <template>
116
+ <form :class="{ 'opacity-50 pointer-events-none': resettingTurnstile }">
117
+ <div
118
+ v-if="currentWindow === 'login'"
119
+ key="login"
120
+ >
121
+ <FieldInput
122
+ v-model="form.email"
123
+ background="white"
124
+ class="mb-4"
125
+ :label="t('email')"
126
+ type="email"
127
+ :validation="v$.email"
128
+ @submit="onLogin"
129
+ />
130
+
131
+ <FieldInput
132
+ v-model="form.password"
133
+ background="white"
134
+ class="mb-6"
135
+ :label="t('password')"
136
+ type="password"
137
+ :validation="v$.password"
138
+ @submit="onLogin"
139
+ >
140
+ <template #label>
141
+ <BaseText
142
+ v-if="action === 'login'"
143
+ bold
144
+ class="mb-3 cursor-pointer text-indigo-700 sm:mb-0 dark:text-indigo-300 hover:text-gray-800 dark:hover:text-gray-200"
145
+ size="xs"
146
+ :text="t('reset')"
147
+ @click="onUpdateCurrentWindow('forgotPassword')"
148
+ />
149
+ </template>
150
+ </FieldInput>
151
+
152
+ <BaseButton
153
+ color="indigo"
154
+ full-width
155
+ :loading="loggingWithEmail"
156
+ reverse
157
+ :size="size"
158
+ :text="{
159
+ sm: resettingTurnstile ? t('loading') : t(`buttons.${action}.sm`),
160
+ base: resettingTurnstile ? t('loading') : t(`buttons.${action}.base`),
161
+ }"
162
+ @click="onLogin"
163
+ />
164
+
165
+ <NuxtTurnstile
166
+ ref="turnstile"
167
+ v-model="form.captchaToken"
168
+ />
169
+ </div>
170
+
171
+ <div
172
+ v-else-if="currentWindow === 'forgotPassword'"
173
+ key="forgotPassword"
174
+ >
175
+ <FieldInput
176
+ v-model="form.email"
177
+ background="white"
178
+ class="mb-6"
179
+ :label="t('email')"
180
+ type="email"
181
+ :validation="v$.email"
182
+ @submit="onForgotPassword"
183
+ >
184
+ <template #label>
185
+ <BaseText
186
+ bold
187
+ class="mb-3 cursor-pointer text-indigo-700 sm:mb-0 dark:text-indigo-300 hover:text-gray-800 dark:hover:text-gray-200"
188
+ size="xs"
189
+ :text="t('login')"
190
+ @click="onUpdateCurrentWindow('login')"
191
+ />
192
+ </template>
193
+ </FieldInput>
194
+
195
+ <BaseButton
196
+ color="indigo"
197
+ full-width
198
+ :loading="forgettingPassword"
199
+ reverse
200
+ :text="{
201
+ sm: t('buttons.forgotPassword.sm'),
202
+ base: t('buttons.forgotPassword.base'),
203
+ }"
204
+ @click="onForgotPassword"
205
+ />
206
+ </div>
207
+ </form>
208
+ </template>
209
+
210
+ <i18n lang="json">
211
+ {
212
+ "de": {
213
+ "buttons": {
214
+ "forgotPassword": {
215
+ "base": "Passwort zurücksetzen",
216
+ "sm": "Zurücksetzen"
217
+ },
218
+ "login": {
219
+ "base": "Mit E-Mail fortfahren",
220
+ "sm": "Weiter"
221
+ },
222
+ "register": {
223
+ "base": "Mit E-Mail registrieren",
224
+ "sm": "Registrieren"
225
+ }
226
+ },
227
+ "email": "E-Mail-Adresse",
228
+ "loading": "Laden…",
229
+ "login": "Anmelden?",
230
+ "password": "Passwort",
231
+ "reset": "Passwort zurücksetzen?"
232
+ },
233
+ "en": {
234
+ "buttons": {
235
+ "forgotPassword": {
236
+ "base": "Reset the password",
237
+ "sm": "Reset"
238
+ },
239
+ "login": {
240
+ "base": "Continue with Email",
241
+ "sm": "Continue"
242
+ },
243
+ "register": {
244
+ "base": "Register with Email",
245
+ "sm": "Register"
246
+ }
247
+ },
248
+ "email": "Email address",
249
+ "loading": "Loading…",
250
+ "login": "Login?",
251
+ "password": "Password",
252
+ "reset": "Reset password?"
253
+ },
254
+ "es": {
255
+ "buttons": {
256
+ "forgotPassword": {
257
+ "base": "Restablecer la contraseña",
258
+ "sm": "Restablecer"
259
+ },
260
+ "login": {
261
+ "base": "Continuar con correo electrónico",
262
+ "sm": "Continuar"
263
+ },
264
+ "register": {
265
+ "base": "Registrarse con correo electrónico",
266
+ "sm": "Registrarse"
267
+ }
268
+ },
269
+ "email": "Correo electrónico",
270
+ "loading": "Cargando…",
271
+ "login": "¿Iniciar sesión?",
272
+ "password": "Contraseña",
273
+ "reset": "¿Restablecer contraseña?"
274
+ },
275
+ "fr": {
276
+ "buttons": {
277
+ "forgotPassword": {
278
+ "base": "Réinitialiser le mot de passe",
279
+ "sm": "Réinitialiser"
280
+ },
281
+ "login": {
282
+ "base": "Se connecter avec Email",
283
+ "sm": "Continuer"
284
+ },
285
+ "register": {
286
+ "base": "S'inscrire avec Email",
287
+ "sm": "S'inscrire"
288
+ }
289
+ },
290
+ "email": "Adresse e-mail",
291
+ "loading": "Chargement…",
292
+ "login": "Se connecter ?",
293
+ "password": "Mot de passe",
294
+ "reset": "Réinitialiser ?"
295
+ },
296
+ "id": {
297
+ "buttons": {
298
+ "forgotPassword": {
299
+ "base": "Atur ulang kata sandi",
300
+ "sm": "Atur ulang"
301
+ },
302
+ "login": {
303
+ "base": "Lanjutkan dengan Email",
304
+ "sm": "Lanjutkan"
305
+ },
306
+ "register": {
307
+ "base": "Daftar dengan Email",
308
+ "sm": "Daftar"
309
+ }
310
+ },
311
+ "email": "Alamat email",
312
+ "loading": "Memuat…",
313
+ "login": "Masuk?",
314
+ "password": "Kata sandi",
315
+ "reset": "Atur ulang kata sandi?"
316
+ },
317
+ "it": {
318
+ "buttons": {
319
+ "forgotPassword": {
320
+ "base": "Reimposta la password",
321
+ "sm": "Reimposta"
322
+ },
323
+ "login": {
324
+ "base": "Continua con email",
325
+ "sm": "Continua"
326
+ },
327
+ "register": {
328
+ "base": "Registrati con email",
329
+ "sm": "Registrati"
330
+ }
331
+ },
332
+ "email": "Email",
333
+ "loading": "Caricamento…",
334
+ "login": "Accedere?",
335
+ "password": "Password",
336
+ "reset": "Reimpostare la password?"
337
+ },
338
+ "ja": {
339
+ "buttons": {
340
+ "forgotPassword": {
341
+ "base": "パスワードをリセット",
342
+ "sm": "リセット"
343
+ },
344
+ "login": {
345
+ "base": "メールアドレスで続ける",
346
+ "sm": "続ける"
347
+ },
348
+ "register": {
349
+ "base": "メールアドレスで登録",
350
+ "sm": "登録"
351
+ }
352
+ },
353
+ "email": "メールアドレス",
354
+ "loading": "読み込み中…",
355
+ "login": "ログイン?",
356
+ "password": "パスワード",
357
+ "reset": "パスワードをリセット?"
358
+ },
359
+ "ko": {
360
+ "buttons": {
361
+ "forgotPassword": {
362
+ "base": "비밀번호 재설정",
363
+ "sm": "재설정"
364
+ },
365
+ "login": {
366
+ "base": "이메일로 계속하기",
367
+ "sm": "계속"
368
+ },
369
+ "register": {
370
+ "base": "이메일로 가입하기",
371
+ "sm": "가입"
372
+ }
373
+ },
374
+ "email": "이메일 주소",
375
+ "loading": "로딩 중…",
376
+ "login": "로그인?",
377
+ "password": "비밀번호",
378
+ "reset": "비밀번호 재설정?"
379
+ },
380
+ "nl": {
381
+ "buttons": {
382
+ "forgotPassword": {
383
+ "base": "Het wachtwoord resetten",
384
+ "sm": "Resetten"
385
+ },
386
+ "login": {
387
+ "base": "Doorgaan met e-mail",
388
+ "sm": "Doorgaan"
389
+ },
390
+ "register": {
391
+ "base": "Registreren met e-mail",
392
+ "sm": "Registreren"
393
+ }
394
+ },
395
+ "email": "E-mailadres",
396
+ "loading": "Laden…",
397
+ "login": "Inloggen?",
398
+ "password": "Wachtwoord",
399
+ "reset": "Wachtwoord resetten?"
400
+ },
401
+ "pl": {
402
+ "buttons": {
403
+ "forgotPassword": {
404
+ "base": "Zresetuj hasło",
405
+ "sm": "Resetuj"
406
+ },
407
+ "login": {
408
+ "base": "Kontynuuj przez e-mail",
409
+ "sm": "Kontynuuj"
410
+ },
411
+ "register": {
412
+ "base": "Zarejestruj się przez e-mail",
413
+ "sm": "Zarejestruj się"
414
+ }
415
+ },
416
+ "email": "Adres e-mail",
417
+ "loading": "Ładowanie…",
418
+ "login": "Zalogować się?",
419
+ "password": "Hasło",
420
+ "reset": "Zresetować hasło?"
421
+ },
422
+ "pt": {
423
+ "buttons": {
424
+ "forgotPassword": {
425
+ "base": "Repor a palavra-passe",
426
+ "sm": "Repor"
427
+ },
428
+ "login": {
429
+ "base": "Continuar com e-mail",
430
+ "sm": "Continuar"
431
+ },
432
+ "register": {
433
+ "base": "Registar com e-mail",
434
+ "sm": "Registar"
435
+ }
436
+ },
437
+ "email": "Endereço de e-mail",
438
+ "loading": "A carregar…",
439
+ "login": "Iniciar sessão?",
440
+ "password": "Palavra-passe",
441
+ "reset": "Repor palavra-passe?"
442
+ },
443
+ "pt-BR": {
444
+ "buttons": {
445
+ "forgotPassword": {
446
+ "base": "Redefinir a senha",
447
+ "sm": "Redefinir"
448
+ },
449
+ "login": {
450
+ "base": "Continuar com e-mail",
451
+ "sm": "Continuar"
452
+ },
453
+ "register": {
454
+ "base": "Cadastrar com e-mail",
455
+ "sm": "Cadastrar"
456
+ }
457
+ },
458
+ "email": "Endereço de e-mail",
459
+ "loading": "Carregando…",
460
+ "login": "Entrar?",
461
+ "password": "Senha",
462
+ "reset": "Redefinir senha?"
463
+ },
464
+ "vi": {
465
+ "buttons": {
466
+ "forgotPassword": {
467
+ "base": "Đặt lại mật khẩu",
468
+ "sm": "Đặt lại"
469
+ },
470
+ "login": {
471
+ "base": "Tiếp tục bằng Email",
472
+ "sm": "Tiếp tục"
473
+ },
474
+ "register": {
475
+ "base": "Đăng ký bằng Email",
476
+ "sm": "Đăng ký"
477
+ }
478
+ },
479
+ "email": "Địa chỉ email",
480
+ "loading": "Đang tải…",
481
+ "login": "Đăng nhập?",
482
+ "password": "Mật khẩu",
483
+ "reset": "Đặt lại mật khẩu?"
484
+ }
485
+ }
486
+ </i18n>
@@ -94,6 +94,7 @@ async function onStartAuthentication() {
94
94
  }
95
95
 
96
96
  emit('error', error)
97
+
97
98
  console.error(error)
98
99
  }
99
100
  finally {
@@ -1,3 +1,41 @@
1
+ export type AuthAction = 'login' | 'register'
2
+
3
+ export interface AuthBox {
4
+ action?: AuthAction
5
+ appleConfig?: AuthSocialConnectAppleConfig
6
+ googleConfig?: AuthSocialConnectGoogleConfig
7
+ hasBox?: boolean
8
+ onForgotPassword: AuthEmailConnect['onForgotPassword']
9
+ onLogin: AuthEmailConnect['onLogin']
10
+ onReactivate: (params: {
11
+ email: string
12
+ }) => Promise<void>
13
+ onSocialLogin: (payload: AuthSocialConnectSuccess) => Promise<AuthConnectResult>
14
+ }
15
+
16
+ export interface AuthConnectResult {
17
+ email?: string
18
+ isClosed: boolean
19
+ isNew?: boolean
20
+ }
21
+
22
+ export interface AuthEmailConnect {
23
+ action?: AuthAction
24
+ onForgotPassword: (params: {
25
+ email: string
26
+ }) => Promise<AuthConnectResult>
27
+ onLogin: (params: AuthEmailConnectPayload) => Promise<AuthConnectResult>
28
+ size?: BaseButtonSize
29
+ }
30
+
31
+ export type AuthEmailConnectCurrentWindow = 'forgotPassword' | 'login'
32
+
33
+ export interface AuthEmailConnectPayload {
34
+ captchaToken: string
35
+ email: string
36
+ password: string
37
+ }
38
+
1
39
  export interface AuthSocialConnect {
2
40
  appleConfig?: AuthSocialConnectAppleConfig
3
41
  googleConfig?: AuthSocialConnectGoogleConfig
@@ -2,6 +2,12 @@ import type { Directive } from 'vue'
2
2
 
3
3
  declare global {
4
4
  // Auth
5
+ type AuthAction = import('./auth').AuthAction
6
+ type AuthBox = import('./auth').AuthBox
7
+ type AuthConnectResult = import('./auth').AuthConnectResult
8
+ type AuthEmailConnect = import('./auth').AuthEmailConnect
9
+ type AuthEmailConnectCurrentWindow = import('./auth').AuthEmailConnectCurrentWindow
10
+ type AuthEmailConnectPayload = import('./auth').AuthEmailConnectPayload
5
11
  type AuthSocialConnect = import('./auth').AuthSocialConnect
6
12
  type AuthSocialConnectAppleConfig = import('./auth').AuthSocialConnectAppleConfig
7
13
  type AuthSocialConnectGoogleConfig = import('./auth').AuthSocialConnectGoogleConfig
@@ -135,6 +141,12 @@ declare global {
135
141
  }
136
142
 
137
143
  declare module 'vue' {
144
+ interface GlobalComponents {
145
+ NuxtTurnstile: new () => {
146
+ reset: () => void
147
+ }
148
+ }
149
+
138
150
  interface GlobalDirectives {
139
151
  vTooltip: Directive<HTMLElement, string | undefined | {
140
152
  content?: string
package/app/utils/auth.ts CHANGED
@@ -3,7 +3,9 @@ export function isSocialLoginCancellation(error: unknown): boolean {
3
3
  return false
4
4
  }
5
5
 
6
- const candidate = error as { code?: string }
6
+ const candidate = error as {
7
+ code?: string
8
+ }
7
9
 
8
10
  // @capgo/capacitor-social-login rejects user-dismissed sheets with this code on iOS and Android.
9
11
  // The message is localized, so never match on it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasmakers/ui",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "private": false,
5
5
  "description": "Reusable Nuxt UI components for SaaS Makers projects",
6
6
  "license": "MIT",