@adminforth/email-invite 1.3.1 → 2.0.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/build.log +2 -4
- package/custom/SetPassword.vue +58 -38
- package/dist/custom/SetPassword.vue +58 -38
- package/package.json +3 -3
- package/custom/AuthCard.vue +0 -37
- package/custom/PasswordField.vue +0 -55
- package/dist/custom/AuthCard.vue +0 -37
- package/dist/custom/PasswordField.vue +0 -55
package/build.log
CHANGED
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
sending incremental file list
|
|
6
6
|
custom/
|
|
7
|
-
custom/AuthCard.vue
|
|
8
|
-
custom/PasswordField.vue
|
|
9
7
|
custom/SetPassword.vue
|
|
10
8
|
custom/tsconfig.json
|
|
11
9
|
|
|
12
|
-
sent
|
|
13
|
-
total size is
|
|
10
|
+
sent 10,444 bytes received 58 bytes 21,004.00 bytes/sec
|
|
11
|
+
total size is 10,232 speedup is 0.97
|
package/custom/SetPassword.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="relative flex items-center justify-center min-h-screen bg-
|
|
2
|
+
<div class="relative flex items-center justify-center min-h-screen bg-lightHtml dark:bg-darkHtml w-screen h-screen"
|
|
3
3
|
:style="coreStore.config?.loginBackgroundImage && backgroundPosition === 'over' ? {
|
|
4
4
|
'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
|
|
5
5
|
'background-size': 'cover',
|
|
@@ -26,55 +26,67 @@
|
|
|
26
26
|
class="af-set-password-modal overflow-y-auto flex flex-grow
|
|
27
27
|
overflow-x-hidden z-50 min-w-[350px] justify-center items-center md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
|
28
28
|
<div class="relative flex w-full max-h-full justify-center p-4">
|
|
29
|
-
<
|
|
30
|
-
class="af-login-popup"
|
|
29
|
+
<DialogPanel
|
|
30
|
+
class="af-login-popup af-auth-card"
|
|
31
31
|
:title="header.title"
|
|
32
32
|
:subtitle="header.subtitle"
|
|
33
33
|
:error="tokenValid && !passwordSet ? validationError || error : null"
|
|
34
|
+
:classes="AUTH_CARD_CLASSES"
|
|
34
35
|
>
|
|
35
|
-
<template #icon><
|
|
36
|
+
<template #icon><IconUserPlus /></template>
|
|
36
37
|
|
|
37
38
|
<div v-if="loading" class="flex justify-center py-6">
|
|
38
39
|
<Spinner class="w-8 h-8" />
|
|
39
40
|
</div>
|
|
40
41
|
|
|
41
|
-
<p v-else-if="!tokenValid" role="alert" class="af-alert-error flex items-start gap-2.5 rounded-lg border border-
|
|
42
|
-
<
|
|
42
|
+
<p v-else-if="!tokenValid" role="alert" class="af-alert-error flex items-start gap-2.5 rounded-lg border border-lightDangerBorder bg-lightDangerSoft px-3.5 py-3 text-sm leading-5 text-lightDanger dark:border-darkDangerBorder dark:bg-darkDangerSoft dark:text-darkDanger">
|
|
43
|
+
<IconCircleAlert class="w-5 h-5 shrink-0" />
|
|
43
44
|
{{ $t('This invitation link is invalid or has expired. Ask your administrator to send a new one.') }}
|
|
44
45
|
</p>
|
|
45
46
|
|
|
46
47
|
<template v-else-if="passwordSet">
|
|
47
|
-
<p role="status" class="af-alert-success flex items-start gap-2.5 rounded-lg border border-
|
|
48
|
-
<
|
|
48
|
+
<p role="status" class="af-alert-success flex items-start gap-2.5 rounded-lg border border-lightSuccessBorder bg-lightSuccessSoft px-3.5 py-3 text-sm leading-5 text-lightSuccess dark:border-darkSuccessBorder dark:bg-darkSuccessSoft dark:text-darkSuccess">
|
|
49
|
+
<IconCircleCheck class="w-5 h-5 shrink-0" />
|
|
49
50
|
{{ isUserLoggedIn ? $t('Password set successfully to your new account.') : $t('Password set successfully! Log in with your email and the new password.') }}
|
|
50
51
|
</p>
|
|
51
|
-
<p v-if="isUserLoggedIn" class="text-sm text-
|
|
52
|
+
<p v-if="isUserLoggedIn" class="text-sm text-lightLoginViewTextColor dark:text-darkLoginViewTextColor">
|
|
52
53
|
{{ $t('You are still logged in to another account. Stay in it, or log out to log in to the new one.') }}
|
|
53
54
|
</p>
|
|
54
55
|
</template>
|
|
55
56
|
|
|
56
57
|
<template v-else>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
58
|
+
<!-- enter is handled on the wrapper: Input spreads attrs on both its root and the input -->
|
|
59
|
+
<div class="af-password-field" @keydown.enter="passwordConfirmationInput!.focus()">
|
|
60
|
+
<label for="password" class="block mb-2 text-sm font-medium text-lightLoginViewTextColor dark:text-darkLoginViewTextColor">{{ $t('Password') }}</label>
|
|
61
|
+
<Input
|
|
62
|
+
v-model="password"
|
|
63
|
+
id="password"
|
|
64
|
+
name="password"
|
|
65
|
+
type="password"
|
|
66
|
+
passwordToggle
|
|
67
|
+
autocomplete="new-password"
|
|
68
|
+
:placeholder="$t('Enter your password')"
|
|
69
|
+
:invalid="Boolean(validationError)"
|
|
70
|
+
fullWidth
|
|
71
|
+
required
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="af-password-field" @keydown.enter="setPassword">
|
|
75
|
+
<label for="password_confirmation" class="block mb-2 text-sm font-medium text-lightLoginViewTextColor dark:text-darkLoginViewTextColor">{{ $t('Confirm password') }}</label>
|
|
76
|
+
<Input
|
|
77
|
+
ref="passwordConfirmationInput"
|
|
78
|
+
v-model="passwordConfirmation"
|
|
79
|
+
id="password_confirmation"
|
|
80
|
+
name="password_confirmation"
|
|
81
|
+
type="password"
|
|
82
|
+
passwordToggle
|
|
83
|
+
autocomplete="new-password"
|
|
84
|
+
:placeholder="$t('Confirm your password')"
|
|
85
|
+
:invalid="Boolean(validationError)"
|
|
86
|
+
fullWidth
|
|
87
|
+
required
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
78
90
|
</template>
|
|
79
91
|
|
|
80
92
|
<template v-if="!loading" #footer>
|
|
@@ -94,7 +106,7 @@
|
|
|
94
106
|
{{ $t('Set password') }}
|
|
95
107
|
</Button>
|
|
96
108
|
</template>
|
|
97
|
-
</
|
|
109
|
+
</DialogPanel>
|
|
98
110
|
</div>
|
|
99
111
|
</div>
|
|
100
112
|
|
|
@@ -108,10 +120,8 @@ import { useCoreStore } from '@/stores/core';
|
|
|
108
120
|
import { useUserStore } from '@/stores/user';
|
|
109
121
|
import { callAdminForthApi, loadFile, applyRegexValidation } from '@/utils';
|
|
110
122
|
import { useRoute, useRouter } from 'vue-router';
|
|
111
|
-
import {
|
|
112
|
-
import { Button, LinkButton, Spinner } from '@/afcl';
|
|
113
|
-
import AuthCard from './AuthCard.vue';
|
|
114
|
-
import PasswordField from './PasswordField.vue';
|
|
123
|
+
import { IconCircleAlert, IconCircleCheck, IconUserPlus } from '@iconify-prerendered/vue-lucide';
|
|
124
|
+
import { Button, DialogPanel, Input, LinkButton, Spinner } from '@/afcl';
|
|
115
125
|
|
|
116
126
|
const { t } = useI18n();
|
|
117
127
|
|
|
@@ -123,10 +133,20 @@ const passwordSet = ref(false);
|
|
|
123
133
|
const userStore = useUserStore();
|
|
124
134
|
const coreStore = useCoreStore();
|
|
125
135
|
|
|
126
|
-
|
|
136
|
+
// class names apps restyle the card by, kept from the former AuthCard
|
|
137
|
+
const AUTH_CARD_CLASSES = {
|
|
138
|
+
header: 'af-auth-card-header',
|
|
139
|
+
icon: 'af-auth-card-icon',
|
|
140
|
+
titleWrap: 'af-auth-card-title-wrap',
|
|
141
|
+
title: 'af-auth-card-title',
|
|
142
|
+
subtitle: 'af-auth-card-subtitle',
|
|
143
|
+
body: 'af-auth-card-body',
|
|
144
|
+
error: 'af-auth-card-error',
|
|
145
|
+
footer: 'af-auth-card-footer',
|
|
146
|
+
};
|
|
147
|
+
const passwordConfirmationInput = ref<InstanceType<typeof Input> | null>(null);
|
|
127
148
|
const password = ref("");
|
|
128
149
|
const passwordConfirmation = ref("");
|
|
129
|
-
const unmasked = ref(false);
|
|
130
150
|
|
|
131
151
|
const route = useRoute();
|
|
132
152
|
const router = useRouter();
|
|
@@ -192,7 +212,7 @@ const validationError = computed(() => {
|
|
|
192
212
|
|
|
193
213
|
onMounted(async () => {
|
|
194
214
|
loading.value = true;
|
|
195
|
-
await coreStore.
|
|
215
|
+
await coreStore.fetchConfig({ redirectToLoginIfNotLoggedIn: false });
|
|
196
216
|
|
|
197
217
|
// Check if token is present and valid
|
|
198
218
|
const token = route.query.token;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="relative flex items-center justify-center min-h-screen bg-
|
|
2
|
+
<div class="relative flex items-center justify-center min-h-screen bg-lightHtml dark:bg-darkHtml w-screen h-screen"
|
|
3
3
|
:style="coreStore.config?.loginBackgroundImage && backgroundPosition === 'over' ? {
|
|
4
4
|
'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
|
|
5
5
|
'background-size': 'cover',
|
|
@@ -26,55 +26,67 @@
|
|
|
26
26
|
class="af-set-password-modal overflow-y-auto flex flex-grow
|
|
27
27
|
overflow-x-hidden z-50 min-w-[350px] justify-center items-center md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
|
28
28
|
<div class="relative flex w-full max-h-full justify-center p-4">
|
|
29
|
-
<
|
|
30
|
-
class="af-login-popup"
|
|
29
|
+
<DialogPanel
|
|
30
|
+
class="af-login-popup af-auth-card"
|
|
31
31
|
:title="header.title"
|
|
32
32
|
:subtitle="header.subtitle"
|
|
33
33
|
:error="tokenValid && !passwordSet ? validationError || error : null"
|
|
34
|
+
:classes="AUTH_CARD_CLASSES"
|
|
34
35
|
>
|
|
35
|
-
<template #icon><
|
|
36
|
+
<template #icon><IconUserPlus /></template>
|
|
36
37
|
|
|
37
38
|
<div v-if="loading" class="flex justify-center py-6">
|
|
38
39
|
<Spinner class="w-8 h-8" />
|
|
39
40
|
</div>
|
|
40
41
|
|
|
41
|
-
<p v-else-if="!tokenValid" role="alert" class="af-alert-error flex items-start gap-2.5 rounded-lg border border-
|
|
42
|
-
<
|
|
42
|
+
<p v-else-if="!tokenValid" role="alert" class="af-alert-error flex items-start gap-2.5 rounded-lg border border-lightDangerBorder bg-lightDangerSoft px-3.5 py-3 text-sm leading-5 text-lightDanger dark:border-darkDangerBorder dark:bg-darkDangerSoft dark:text-darkDanger">
|
|
43
|
+
<IconCircleAlert class="w-5 h-5 shrink-0" />
|
|
43
44
|
{{ $t('This invitation link is invalid or has expired. Ask your administrator to send a new one.') }}
|
|
44
45
|
</p>
|
|
45
46
|
|
|
46
47
|
<template v-else-if="passwordSet">
|
|
47
|
-
<p role="status" class="af-alert-success flex items-start gap-2.5 rounded-lg border border-
|
|
48
|
-
<
|
|
48
|
+
<p role="status" class="af-alert-success flex items-start gap-2.5 rounded-lg border border-lightSuccessBorder bg-lightSuccessSoft px-3.5 py-3 text-sm leading-5 text-lightSuccess dark:border-darkSuccessBorder dark:bg-darkSuccessSoft dark:text-darkSuccess">
|
|
49
|
+
<IconCircleCheck class="w-5 h-5 shrink-0" />
|
|
49
50
|
{{ isUserLoggedIn ? $t('Password set successfully to your new account.') : $t('Password set successfully! Log in with your email and the new password.') }}
|
|
50
51
|
</p>
|
|
51
|
-
<p v-if="isUserLoggedIn" class="text-sm text-
|
|
52
|
+
<p v-if="isUserLoggedIn" class="text-sm text-lightLoginViewTextColor dark:text-darkLoginViewTextColor">
|
|
52
53
|
{{ $t('You are still logged in to another account. Stay in it, or log out to log in to the new one.') }}
|
|
53
54
|
</p>
|
|
54
55
|
</template>
|
|
55
56
|
|
|
56
57
|
<template v-else>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
58
|
+
<!-- enter is handled on the wrapper: Input spreads attrs on both its root and the input -->
|
|
59
|
+
<div class="af-password-field" @keydown.enter="passwordConfirmationInput!.focus()">
|
|
60
|
+
<label for="password" class="block mb-2 text-sm font-medium text-lightLoginViewTextColor dark:text-darkLoginViewTextColor">{{ $t('Password') }}</label>
|
|
61
|
+
<Input
|
|
62
|
+
v-model="password"
|
|
63
|
+
id="password"
|
|
64
|
+
name="password"
|
|
65
|
+
type="password"
|
|
66
|
+
passwordToggle
|
|
67
|
+
autocomplete="new-password"
|
|
68
|
+
:placeholder="$t('Enter your password')"
|
|
69
|
+
:invalid="Boolean(validationError)"
|
|
70
|
+
fullWidth
|
|
71
|
+
required
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="af-password-field" @keydown.enter="setPassword">
|
|
75
|
+
<label for="password_confirmation" class="block mb-2 text-sm font-medium text-lightLoginViewTextColor dark:text-darkLoginViewTextColor">{{ $t('Confirm password') }}</label>
|
|
76
|
+
<Input
|
|
77
|
+
ref="passwordConfirmationInput"
|
|
78
|
+
v-model="passwordConfirmation"
|
|
79
|
+
id="password_confirmation"
|
|
80
|
+
name="password_confirmation"
|
|
81
|
+
type="password"
|
|
82
|
+
passwordToggle
|
|
83
|
+
autocomplete="new-password"
|
|
84
|
+
:placeholder="$t('Confirm your password')"
|
|
85
|
+
:invalid="Boolean(validationError)"
|
|
86
|
+
fullWidth
|
|
87
|
+
required
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
78
90
|
</template>
|
|
79
91
|
|
|
80
92
|
<template v-if="!loading" #footer>
|
|
@@ -94,7 +106,7 @@
|
|
|
94
106
|
{{ $t('Set password') }}
|
|
95
107
|
</Button>
|
|
96
108
|
</template>
|
|
97
|
-
</
|
|
109
|
+
</DialogPanel>
|
|
98
110
|
</div>
|
|
99
111
|
</div>
|
|
100
112
|
|
|
@@ -108,10 +120,8 @@ import { useCoreStore } from '@/stores/core';
|
|
|
108
120
|
import { useUserStore } from '@/stores/user';
|
|
109
121
|
import { callAdminForthApi, loadFile, applyRegexValidation } from '@/utils';
|
|
110
122
|
import { useRoute, useRouter } from 'vue-router';
|
|
111
|
-
import {
|
|
112
|
-
import { Button, LinkButton, Spinner } from '@/afcl';
|
|
113
|
-
import AuthCard from './AuthCard.vue';
|
|
114
|
-
import PasswordField from './PasswordField.vue';
|
|
123
|
+
import { IconCircleAlert, IconCircleCheck, IconUserPlus } from '@iconify-prerendered/vue-lucide';
|
|
124
|
+
import { Button, DialogPanel, Input, LinkButton, Spinner } from '@/afcl';
|
|
115
125
|
|
|
116
126
|
const { t } = useI18n();
|
|
117
127
|
|
|
@@ -123,10 +133,20 @@ const passwordSet = ref(false);
|
|
|
123
133
|
const userStore = useUserStore();
|
|
124
134
|
const coreStore = useCoreStore();
|
|
125
135
|
|
|
126
|
-
|
|
136
|
+
// class names apps restyle the card by, kept from the former AuthCard
|
|
137
|
+
const AUTH_CARD_CLASSES = {
|
|
138
|
+
header: 'af-auth-card-header',
|
|
139
|
+
icon: 'af-auth-card-icon',
|
|
140
|
+
titleWrap: 'af-auth-card-title-wrap',
|
|
141
|
+
title: 'af-auth-card-title',
|
|
142
|
+
subtitle: 'af-auth-card-subtitle',
|
|
143
|
+
body: 'af-auth-card-body',
|
|
144
|
+
error: 'af-auth-card-error',
|
|
145
|
+
footer: 'af-auth-card-footer',
|
|
146
|
+
};
|
|
147
|
+
const passwordConfirmationInput = ref<InstanceType<typeof Input> | null>(null);
|
|
127
148
|
const password = ref("");
|
|
128
149
|
const passwordConfirmation = ref("");
|
|
129
|
-
const unmasked = ref(false);
|
|
130
150
|
|
|
131
151
|
const route = useRoute();
|
|
132
152
|
const router = useRouter();
|
|
@@ -192,7 +212,7 @@ const validationError = computed(() => {
|
|
|
192
212
|
|
|
193
213
|
onMounted(async () => {
|
|
194
214
|
loading.value = true;
|
|
195
|
-
await coreStore.
|
|
215
|
+
await coreStore.fetchConfig({ redirectToLoginIfNotLoggedIn: false });
|
|
196
216
|
|
|
197
217
|
// Check if token is present and valid
|
|
198
218
|
const token = route.query.token;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/email-invite",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^22.10.7",
|
|
28
|
-
"adminforth": "^
|
|
28
|
+
"adminforth": "^4.7.3",
|
|
29
29
|
"semantic-release": "^24.2.1",
|
|
30
30
|
"semantic-release-slack-bot": "^4.0.2",
|
|
31
31
|
"typescript": "^5.7.3"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"adminforth": "^
|
|
34
|
+
"adminforth": "^4.6.0"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
package/custom/AuthCard.vue
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="af-auth-card relative flex flex-col w-full max-w-md overflow-hidden rounded-xl border border-lightDialogBreakLine bg-lightDialogBackgorund shadow-2xl dark:border-darkDialogBreakLine dark:bg-darkDialogBackgorund">
|
|
3
|
-
<div class="af-auth-card-header flex items-start gap-3.5 border-b border-lightDialogBreakLine px-6 py-5 dark:border-darkDialogBreakLine">
|
|
4
|
-
<div class="af-auth-card-icon flex w-10 h-10 shrink-0 items-center justify-center rounded-lg bg-lightPrimary/10 text-lightPrimary dark:bg-darkPrimary/20 dark:text-darkPrimary">
|
|
5
|
-
<slot name="icon" />
|
|
6
|
-
</div>
|
|
7
|
-
<div class="af-auth-card-title-wrap flex-1 min-w-0">
|
|
8
|
-
<slot name="title">
|
|
9
|
-
<p class="af-auth-card-title text-lg leading-6 font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText">{{ title }}</p>
|
|
10
|
-
<p class="af-auth-card-subtitle mt-0.5 text-sm leading-5 text-gray-500 dark:text-gray-400">{{ subtitle }}</p>
|
|
11
|
-
</slot>
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<div class="af-auth-card-body flex flex-col gap-4 px-6 pt-5 pb-6">
|
|
16
|
-
<slot />
|
|
17
|
-
<p v-if="error" role="alert" class="af-auth-card-error -mt-1.5 flex items-center gap-1.5 text-sm text-red-600 dark:text-red-400">
|
|
18
|
-
<IconExclamationCircleOutline class="w-4 h-4 shrink-0" />
|
|
19
|
-
{{ error }}
|
|
20
|
-
</p>
|
|
21
|
-
</div>
|
|
22
|
-
|
|
23
|
-
<div v-if="$slots.footer" class="af-auth-card-footer flex flex-wrap items-center justify-end gap-x-3 gap-y-2 border-t border-lightDialogBreakLine bg-gray-50 py-3 pl-6 pr-5 dark:border-darkDialogBreakLine dark:bg-gray-800/50">
|
|
24
|
-
<slot name="footer" />
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
</template>
|
|
28
|
-
|
|
29
|
-
<script setup lang="ts">
|
|
30
|
-
import { IconExclamationCircleOutline } from '@iconify-prerendered/vue-flowbite';
|
|
31
|
-
|
|
32
|
-
defineProps<{
|
|
33
|
-
title: string;
|
|
34
|
-
subtitle: string;
|
|
35
|
-
error?: string | null;
|
|
36
|
-
}>();
|
|
37
|
-
</script>
|
package/custom/PasswordField.vue
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="af-password-field">
|
|
3
|
-
<label :for="id" class="mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300">{{ label }}</label>
|
|
4
|
-
<div class="relative">
|
|
5
|
-
<input
|
|
6
|
-
ref="input"
|
|
7
|
-
v-model="model"
|
|
8
|
-
:id="id"
|
|
9
|
-
:name="id"
|
|
10
|
-
:type="unmasked ? 'text' : 'password'"
|
|
11
|
-
:placeholder="placeholder"
|
|
12
|
-
autocomplete="new-password"
|
|
13
|
-
required
|
|
14
|
-
class="h-11 w-full rounded-lg border-2 bg-gray-50 pl-3.5 pr-12 text-base text-gray-900 placeholder-gray-400 outline-none focus:ring-4 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
|
|
15
|
-
:class="invalid
|
|
16
|
-
? 'border-red-500 focus:border-red-500 focus:ring-red-500/25 dark:border-red-400 dark:focus:border-red-400'
|
|
17
|
-
: 'border-gray-300 focus:border-lightPrimary focus:ring-lightPrimary/25 dark:border-gray-600 dark:focus:border-darkPrimary dark:focus:ring-darkPrimary/25'"
|
|
18
|
-
/>
|
|
19
|
-
<button
|
|
20
|
-
type="button"
|
|
21
|
-
:aria-label="unmasked ? $t('Hide password') : $t('Show password')"
|
|
22
|
-
class="absolute right-1 top-1 inline-flex w-9 h-9 items-center justify-center rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"
|
|
23
|
-
@click="emit('toggle')"
|
|
24
|
-
>
|
|
25
|
-
<IconEyeOutline v-if="!unmasked" class="w-5 h-5" />
|
|
26
|
-
<IconEyeSlashOutline v-else class="w-5 h-5" />
|
|
27
|
-
</button>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</template>
|
|
31
|
-
|
|
32
|
-
<script setup lang="ts">
|
|
33
|
-
import { ref } from 'vue';
|
|
34
|
-
import { IconEyeOutline, IconEyeSlashOutline } from '@iconify-prerendered/vue-flowbite';
|
|
35
|
-
|
|
36
|
-
const model = defineModel<string>({ required: true });
|
|
37
|
-
|
|
38
|
-
defineProps<{
|
|
39
|
-
id: string;
|
|
40
|
-
label: string;
|
|
41
|
-
placeholder: string;
|
|
42
|
-
unmasked: boolean;
|
|
43
|
-
invalid?: boolean;
|
|
44
|
-
}>();
|
|
45
|
-
|
|
46
|
-
const emit = defineEmits<{
|
|
47
|
-
(e: 'toggle'): void;
|
|
48
|
-
}>();
|
|
49
|
-
|
|
50
|
-
const input = ref<HTMLInputElement | null>(null);
|
|
51
|
-
|
|
52
|
-
defineExpose({
|
|
53
|
-
focus: () => input.value!.focus(),
|
|
54
|
-
});
|
|
55
|
-
</script>
|
package/dist/custom/AuthCard.vue
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="af-auth-card relative flex flex-col w-full max-w-md overflow-hidden rounded-xl border border-lightDialogBreakLine bg-lightDialogBackgorund shadow-2xl dark:border-darkDialogBreakLine dark:bg-darkDialogBackgorund">
|
|
3
|
-
<div class="af-auth-card-header flex items-start gap-3.5 border-b border-lightDialogBreakLine px-6 py-5 dark:border-darkDialogBreakLine">
|
|
4
|
-
<div class="af-auth-card-icon flex w-10 h-10 shrink-0 items-center justify-center rounded-lg bg-lightPrimary/10 text-lightPrimary dark:bg-darkPrimary/20 dark:text-darkPrimary">
|
|
5
|
-
<slot name="icon" />
|
|
6
|
-
</div>
|
|
7
|
-
<div class="af-auth-card-title-wrap flex-1 min-w-0">
|
|
8
|
-
<slot name="title">
|
|
9
|
-
<p class="af-auth-card-title text-lg leading-6 font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText">{{ title }}</p>
|
|
10
|
-
<p class="af-auth-card-subtitle mt-0.5 text-sm leading-5 text-gray-500 dark:text-gray-400">{{ subtitle }}</p>
|
|
11
|
-
</slot>
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<div class="af-auth-card-body flex flex-col gap-4 px-6 pt-5 pb-6">
|
|
16
|
-
<slot />
|
|
17
|
-
<p v-if="error" role="alert" class="af-auth-card-error -mt-1.5 flex items-center gap-1.5 text-sm text-red-600 dark:text-red-400">
|
|
18
|
-
<IconExclamationCircleOutline class="w-4 h-4 shrink-0" />
|
|
19
|
-
{{ error }}
|
|
20
|
-
</p>
|
|
21
|
-
</div>
|
|
22
|
-
|
|
23
|
-
<div v-if="$slots.footer" class="af-auth-card-footer flex flex-wrap items-center justify-end gap-x-3 gap-y-2 border-t border-lightDialogBreakLine bg-gray-50 py-3 pl-6 pr-5 dark:border-darkDialogBreakLine dark:bg-gray-800/50">
|
|
24
|
-
<slot name="footer" />
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
</template>
|
|
28
|
-
|
|
29
|
-
<script setup lang="ts">
|
|
30
|
-
import { IconExclamationCircleOutline } from '@iconify-prerendered/vue-flowbite';
|
|
31
|
-
|
|
32
|
-
defineProps<{
|
|
33
|
-
title: string;
|
|
34
|
-
subtitle: string;
|
|
35
|
-
error?: string | null;
|
|
36
|
-
}>();
|
|
37
|
-
</script>
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="af-password-field">
|
|
3
|
-
<label :for="id" class="mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300">{{ label }}</label>
|
|
4
|
-
<div class="relative">
|
|
5
|
-
<input
|
|
6
|
-
ref="input"
|
|
7
|
-
v-model="model"
|
|
8
|
-
:id="id"
|
|
9
|
-
:name="id"
|
|
10
|
-
:type="unmasked ? 'text' : 'password'"
|
|
11
|
-
:placeholder="placeholder"
|
|
12
|
-
autocomplete="new-password"
|
|
13
|
-
required
|
|
14
|
-
class="h-11 w-full rounded-lg border-2 bg-gray-50 pl-3.5 pr-12 text-base text-gray-900 placeholder-gray-400 outline-none focus:ring-4 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
|
|
15
|
-
:class="invalid
|
|
16
|
-
? 'border-red-500 focus:border-red-500 focus:ring-red-500/25 dark:border-red-400 dark:focus:border-red-400'
|
|
17
|
-
: 'border-gray-300 focus:border-lightPrimary focus:ring-lightPrimary/25 dark:border-gray-600 dark:focus:border-darkPrimary dark:focus:ring-darkPrimary/25'"
|
|
18
|
-
/>
|
|
19
|
-
<button
|
|
20
|
-
type="button"
|
|
21
|
-
:aria-label="unmasked ? $t('Hide password') : $t('Show password')"
|
|
22
|
-
class="absolute right-1 top-1 inline-flex w-9 h-9 items-center justify-center rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"
|
|
23
|
-
@click="emit('toggle')"
|
|
24
|
-
>
|
|
25
|
-
<IconEyeOutline v-if="!unmasked" class="w-5 h-5" />
|
|
26
|
-
<IconEyeSlashOutline v-else class="w-5 h-5" />
|
|
27
|
-
</button>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</template>
|
|
31
|
-
|
|
32
|
-
<script setup lang="ts">
|
|
33
|
-
import { ref } from 'vue';
|
|
34
|
-
import { IconEyeOutline, IconEyeSlashOutline } from '@iconify-prerendered/vue-flowbite';
|
|
35
|
-
|
|
36
|
-
const model = defineModel<string>({ required: true });
|
|
37
|
-
|
|
38
|
-
defineProps<{
|
|
39
|
-
id: string;
|
|
40
|
-
label: string;
|
|
41
|
-
placeholder: string;
|
|
42
|
-
unmasked: boolean;
|
|
43
|
-
invalid?: boolean;
|
|
44
|
-
}>();
|
|
45
|
-
|
|
46
|
-
const emit = defineEmits<{
|
|
47
|
-
(e: 'toggle'): void;
|
|
48
|
-
}>();
|
|
49
|
-
|
|
50
|
-
const input = ref<HTMLInputElement | null>(null);
|
|
51
|
-
|
|
52
|
-
defineExpose({
|
|
53
|
-
focus: () => input.value!.focus(),
|
|
54
|
-
});
|
|
55
|
-
</script>
|