@abraca/nuxt 2.0.1 → 2.0.3

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.
Files changed (116) hide show
  1. package/dist/module.d.mts +18 -7
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +21 -5
  4. package/dist/runtime/assets/aware-tokens.css +1 -0
  5. package/dist/runtime/components/AAccountSwitcherModal.d.vue.ts +16 -1
  6. package/dist/runtime/components/AAccountSwitcherModal.vue +33 -4
  7. package/dist/runtime/components/AAccountSwitcherModal.vue.d.ts +16 -1
  8. package/dist/runtime/components/AAuthLinkLanding.d.vue.ts +3 -0
  9. package/dist/runtime/components/AAuthLinkLanding.vue +85 -0
  10. package/dist/runtime/components/AAuthLinkLanding.vue.d.ts +3 -0
  11. package/dist/runtime/components/AClaimAccountModal.d.vue.ts +7 -1
  12. package/dist/runtime/components/AClaimAccountModal.vue +28 -13
  13. package/dist/runtime/components/AClaimAccountModal.vue.d.ts +7 -1
  14. package/dist/runtime/components/AEmailVerifyConfirmModal.d.vue.ts +30 -0
  15. package/dist/runtime/components/AEmailVerifyConfirmModal.vue +100 -0
  16. package/dist/runtime/components/AEmailVerifyConfirmModal.vue.d.ts +30 -0
  17. package/dist/runtime/components/AEmailVerifyRequestCard.d.vue.ts +22 -0
  18. package/dist/runtime/components/AEmailVerifyRequestCard.vue +65 -0
  19. package/dist/runtime/components/AEmailVerifyRequestCard.vue.d.ts +22 -0
  20. package/dist/runtime/components/AMnemonicLoginModal.d.vue.ts +1 -1
  21. package/dist/runtime/components/AMnemonicLoginModal.vue.d.ts +1 -1
  22. package/dist/runtime/components/ANodePanel.vue +2 -0
  23. package/dist/runtime/components/ANotificationBell.d.vue.ts +2 -2
  24. package/dist/runtime/components/ANotificationBell.vue.d.ts +2 -2
  25. package/dist/runtime/components/APasswordChangeModal.d.vue.ts +28 -0
  26. package/dist/runtime/components/APasswordChangeModal.vue +178 -0
  27. package/dist/runtime/components/APasswordChangeModal.vue.d.ts +28 -0
  28. package/dist/runtime/components/APasswordLoginModal.d.vue.ts +42 -0
  29. package/dist/runtime/components/APasswordLoginModal.vue +177 -0
  30. package/dist/runtime/components/APasswordLoginModal.vue.d.ts +42 -0
  31. package/dist/runtime/components/APasswordRegisterModal.d.vue.ts +49 -0
  32. package/dist/runtime/components/APasswordRegisterModal.vue +262 -0
  33. package/dist/runtime/components/APasswordRegisterModal.vue.d.ts +49 -0
  34. package/dist/runtime/components/APasswordResetConfirmModal.d.vue.ts +31 -0
  35. package/dist/runtime/components/APasswordResetConfirmModal.vue +154 -0
  36. package/dist/runtime/components/APasswordResetConfirmModal.vue.d.ts +31 -0
  37. package/dist/runtime/components/APasswordResetRequestModal.d.vue.ts +35 -0
  38. package/dist/runtime/components/APasswordResetRequestModal.vue +113 -0
  39. package/dist/runtime/components/APasswordResetRequestModal.vue.d.ts +35 -0
  40. package/dist/runtime/components/ASetPasswordCard.d.vue.ts +26 -0
  41. package/dist/runtime/components/ASetPasswordCard.vue +139 -0
  42. package/dist/runtime/components/ASetPasswordCard.vue.d.ts +26 -0
  43. package/dist/runtime/components/aware/AAccordion.d.vue.ts +2 -0
  44. package/dist/runtime/components/aware/AAccordion.vue +11 -1
  45. package/dist/runtime/components/aware/AAccordion.vue.d.ts +2 -0
  46. package/dist/runtime/components/aware/AButton.vue +3 -3
  47. package/dist/runtime/components/aware/ACollapsible.d.vue.ts +2 -0
  48. package/dist/runtime/components/aware/ACollapsible.vue +9 -1
  49. package/dist/runtime/components/aware/ACollapsible.vue.d.ts +2 -0
  50. package/dist/runtime/components/aware/AGlobalFocusLayer.vue +1 -1
  51. package/dist/runtime/components/aware/AHoverItem.vue +28 -3
  52. package/dist/runtime/components/aware/AModal.d.vue.ts +2 -0
  53. package/dist/runtime/components/aware/AModal.vue +9 -1
  54. package/dist/runtime/components/aware/AModal.vue.d.ts +2 -0
  55. package/dist/runtime/components/aware/APresenceBlobs.vue +1 -1
  56. package/dist/runtime/components/aware/APresenceCursors.vue +1 -1
  57. package/dist/runtime/components/aware/AScroll.d.vue.ts +2 -0
  58. package/dist/runtime/components/aware/AScroll.vue +13 -3
  59. package/dist/runtime/components/aware/AScroll.vue.d.ts +2 -0
  60. package/dist/runtime/components/aware/ASlideover.d.vue.ts +2 -0
  61. package/dist/runtime/components/aware/ASlideover.vue +9 -1
  62. package/dist/runtime/components/aware/ASlideover.vue.d.ts +2 -0
  63. package/dist/runtime/components/aware/ASlider.vue +1 -0
  64. package/dist/runtime/components/aware/ATabs.d.vue.ts +2 -0
  65. package/dist/runtime/components/aware/ATabs.vue +9 -1
  66. package/dist/runtime/components/aware/ATabs.vue.d.ts +2 -0
  67. package/dist/runtime/components/chat/ANodeChatPanel.vue +1 -0
  68. package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +2 -2
  69. package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +2 -2
  70. package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +2 -2
  71. package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +2 -2
  72. package/dist/runtime/components/shell/AUserProfilePopover.d.vue.ts +1 -1
  73. package/dist/runtime/components/shell/AUserProfilePopover.vue.d.ts +1 -1
  74. package/dist/runtime/composables/useAAField.js +7 -4
  75. package/dist/runtime/composables/useAAFocus.js +10 -5
  76. package/dist/runtime/composables/useAAFollowAnchor.js +68 -34
  77. package/dist/runtime/composables/useAAFollowPeer.d.ts +7 -4
  78. package/dist/runtime/composables/useAAFollowPeer.js +60 -11
  79. package/dist/runtime/composables/useAAViewport.d.ts +1 -1
  80. package/dist/runtime/composables/useAbracadabraAuth.d.ts +2 -0
  81. package/dist/runtime/composables/useAbracadabraAuth.js +2 -0
  82. package/dist/runtime/composables/useEmailVerification.d.ts +40 -26
  83. package/dist/runtime/composables/useEmailVerification.js +95 -43
  84. package/dist/runtime/composables/usePasswordAuth.d.ts +64 -0
  85. package/dist/runtime/composables/usePasswordAuth.js +126 -0
  86. package/dist/runtime/composables/useTiptapHistory.d.ts +2 -2
  87. package/dist/runtime/composables/useTiptapHistory.js +5 -5
  88. package/dist/runtime/extensions/views/MetaFieldView.vue +23 -6
  89. package/dist/runtime/plugin-abracadabra.client.js +57 -8
  90. package/dist/runtime/plugin-abracadabra.server.js +2 -0
  91. package/dist/runtime/server/plugins/abracadabra-service.js +20 -9
  92. package/dist/runtime/types.d.ts +11 -0
  93. package/dist/runtime/utils/awareRingStyle.js +1 -1
  94. package/package.json +7 -7
  95. package/dist/runtime/components/renderers/ASpatialRenderer.d.vue.ts +0 -19
  96. package/dist/runtime/components/renderers/ASpatialRenderer.vue +0 -459
  97. package/dist/runtime/components/renderers/ASpatialRenderer.vue.d.ts +0 -19
  98. package/dist/runtime/components/renderers/spatial/SpatialGround.d.vue.ts +0 -20
  99. package/dist/runtime/components/renderers/spatial/SpatialGround.vue +0 -26
  100. package/dist/runtime/components/renderers/spatial/SpatialGround.vue.d.ts +0 -20
  101. package/dist/runtime/components/renderers/spatial/SpatialObject.d.vue.ts +0 -17
  102. package/dist/runtime/components/renderers/spatial/SpatialObject.vue +0 -257
  103. package/dist/runtime/components/renderers/spatial/SpatialObject.vue.d.ts +0 -17
  104. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.d.vue.ts +0 -15
  105. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue +0 -18
  106. package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue.d.ts +0 -15
  107. package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.d.vue.ts +0 -16
  108. package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.vue +0 -66
  109. package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.vue.d.ts +0 -16
  110. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.d.vue.ts +0 -8
  111. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue +0 -53
  112. package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue.d.ts +0 -8
  113. package/dist/runtime/composables/useSpatialCamera.d.ts +0 -16
  114. package/dist/runtime/composables/useSpatialCamera.js +0 -175
  115. package/dist/runtime/composables/useSpatialDrag.d.ts +0 -14
  116. package/dist/runtime/composables/useSpatialDrag.js +0 -137
@@ -0,0 +1,49 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ error?: string | null;
5
+ title?: string;
6
+ subtitle?: string;
7
+ /** Server-enforced minimum password length (mirrored client-side). */
8
+ minLength?: number;
9
+ /** Show optional email field. */
10
+ showEmail?: boolean;
11
+ /** Show optional display-name field. */
12
+ showDisplayName?: boolean;
13
+ /** Show optional invite-code field. */
14
+ showInviteCode?: boolean;
15
+ /** Show "Already have an account? Sign in" link. */
16
+ showSignInLink?: boolean;
17
+ };
18
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
+ submit: (payload: {
20
+ username: string;
21
+ password: string;
22
+ email?: string;
23
+ displayName?: string;
24
+ inviteCode?: string;
25
+ }) => any;
26
+ "update:open": (v: boolean) => any;
27
+ signin: () => any;
28
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
29
+ onSubmit?: ((payload: {
30
+ username: string;
31
+ password: string;
32
+ email?: string;
33
+ displayName?: string;
34
+ inviteCode?: string;
35
+ }) => any) | undefined;
36
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
37
+ onSignin?: (() => any) | undefined;
38
+ }>, {
39
+ subtitle: string;
40
+ title: string;
41
+ minLength: number;
42
+ loading: boolean;
43
+ showInviteCode: boolean;
44
+ showEmail: boolean;
45
+ showDisplayName: boolean;
46
+ showSignInLink: boolean;
47
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
48
+ declare const _default: typeof __VLS_export;
49
+ export default _default;
@@ -0,0 +1,262 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ const props = defineProps({
4
+ open: { type: Boolean, required: false },
5
+ loading: { type: Boolean, required: false, default: false },
6
+ error: { type: [String, null], required: false },
7
+ title: { type: String, required: false, default: "Create your account" },
8
+ subtitle: { type: String, required: false, default: "Pick a username and a password. You can change either later." },
9
+ minLength: { type: Number, required: false, default: 8 },
10
+ showEmail: { type: Boolean, required: false, default: true },
11
+ showDisplayName: { type: Boolean, required: false, default: false },
12
+ showInviteCode: { type: Boolean, required: false, default: true },
13
+ showSignInLink: { type: Boolean, required: false, default: true }
14
+ });
15
+ const emit = defineEmits(["update:open", "submit", "signin"]);
16
+ const open = computed({
17
+ get: () => !!props.open,
18
+ set: (v) => emit("update:open", v)
19
+ });
20
+ const username = ref("");
21
+ const password = ref("");
22
+ const confirm = ref("");
23
+ const email = ref("");
24
+ const displayName = ref("");
25
+ const inviteCode = ref("");
26
+ const showPassword = ref(false);
27
+ watch(() => props.open, (v) => {
28
+ if (!v) return;
29
+ username.value = "";
30
+ password.value = "";
31
+ confirm.value = "";
32
+ email.value = "";
33
+ displayName.value = "";
34
+ inviteCode.value = "";
35
+ showPassword.value = false;
36
+ });
37
+ const passwordTooShort = computed(
38
+ () => password.value.length > 0 && password.value.length < props.minLength
39
+ );
40
+ const confirmMismatch = computed(
41
+ () => confirm.value.length > 0 && confirm.value !== password.value
42
+ );
43
+ const emailLooksValid = computed(
44
+ () => !email.value || /^[^\s@]+@[^\s@]+\.[^\s.@]+$/.test(email.value.trim())
45
+ );
46
+ const strength = computed(() => {
47
+ const p = password.value;
48
+ if (!p) return { score: 0, label: "" };
49
+ let score = 0;
50
+ if (p.length >= props.minLength) score++;
51
+ if (p.length >= props.minLength + 4) score++;
52
+ if (/[A-Z]/.test(p) && /[a-z]/.test(p)) score++;
53
+ if (/\d/.test(p)) score++;
54
+ if (/[^a-z0-9]/i.test(p)) score++;
55
+ const labels = ["Too short", "Weak", "Fair", "Good", "Strong", "Strong"];
56
+ return { score, label: labels[Math.min(score, 5)] };
57
+ });
58
+ const canSubmit = computed(
59
+ () => !!username.value.trim() && password.value.length >= props.minLength && confirm.value === password.value && emailLooksValid.value && !props.loading
60
+ );
61
+ function submit() {
62
+ if (!canSubmit.value) return;
63
+ emit("submit", {
64
+ username: username.value.trim(),
65
+ password: password.value,
66
+ email: email.value.trim() || void 0,
67
+ displayName: displayName.value.trim() || void 0,
68
+ inviteCode: inviteCode.value.trim() || void 0
69
+ });
70
+ }
71
+ </script>
72
+
73
+ <template>
74
+ <UModal
75
+ v-model:open="open"
76
+ :title="title"
77
+ :ui="{ content: 'sm:max-w-md' }"
78
+ >
79
+ <template #body>
80
+ <div class="flex flex-col gap-4">
81
+ <p class="text-sm text-(--ui-text-muted)">
82
+ {{ subtitle }}
83
+ </p>
84
+
85
+ <UAlert
86
+ v-if="error"
87
+ color="error"
88
+ variant="soft"
89
+ icon="i-lucide-triangle-alert"
90
+ :description="error"
91
+ />
92
+
93
+ <div class="flex flex-col gap-1">
94
+ <label class="text-xs font-medium text-(--ui-text-muted)">Username</label>
95
+ <UInput
96
+ v-model="username"
97
+ size="md"
98
+ autofocus
99
+ autocomplete="username"
100
+ placeholder="your-handle"
101
+ icon="i-lucide-at-sign"
102
+ @keydown.enter="submit"
103
+ />
104
+ </div>
105
+
106
+ <div
107
+ v-if="showDisplayName"
108
+ class="flex flex-col gap-1"
109
+ >
110
+ <label class="text-xs font-medium text-(--ui-text-muted)">Display name (optional)</label>
111
+ <UInput
112
+ v-model="displayName"
113
+ size="md"
114
+ autocomplete="name"
115
+ placeholder="Visible to other people"
116
+ icon="i-lucide-user"
117
+ @keydown.enter="submit"
118
+ />
119
+ </div>
120
+
121
+ <div
122
+ v-if="showEmail"
123
+ class="flex flex-col gap-1"
124
+ >
125
+ <label class="text-xs font-medium text-(--ui-text-muted)">Email (optional)</label>
126
+ <UInput
127
+ v-model="email"
128
+ type="email"
129
+ size="md"
130
+ autocomplete="email"
131
+ placeholder="you@example.com"
132
+ icon="i-lucide-mail"
133
+ @keydown.enter="submit"
134
+ />
135
+ <p
136
+ v-if="email && !emailLooksValid"
137
+ class="text-xs text-(--ui-color-error-500)"
138
+ >
139
+ That doesn't look like an email address.
140
+ </p>
141
+ </div>
142
+
143
+ <div class="flex flex-col gap-1">
144
+ <label class="text-xs font-medium text-(--ui-text-muted)">Password</label>
145
+ <UInput
146
+ v-model="password"
147
+ :type="showPassword ? 'text' : 'password'"
148
+ size="md"
149
+ autocomplete="new-password"
150
+ :placeholder="`${minLength}+ characters`"
151
+ icon="i-lucide-lock"
152
+ :ui="{ trailing: 'pe-1' }"
153
+ @keydown.enter="submit"
154
+ >
155
+ <template #trailing>
156
+ <UButton
157
+ tabindex="-1"
158
+ variant="ghost"
159
+ color="neutral"
160
+ size="xs"
161
+ :icon="showPassword ? 'i-lucide-eye-off' : 'i-lucide-eye'"
162
+ :aria-label="showPassword ? 'Hide password' : 'Show password'"
163
+ @click="showPassword = !showPassword"
164
+ />
165
+ </template>
166
+ </UInput>
167
+ <div
168
+ v-if="password.length > 0"
169
+ class="flex items-center gap-1.5 mt-1"
170
+ >
171
+ <div class="flex-1 grid grid-cols-5 gap-0.5 h-1">
172
+ <div
173
+ v-for="i in 5"
174
+ :key="i"
175
+ class="rounded-full transition-colors"
176
+ :class="i <= strength.score ? strength.score >= 4 ? 'bg-(--ui-color-success-500)' : strength.score >= 2 ? 'bg-(--ui-color-warning-500)' : 'bg-(--ui-color-error-500)' : 'bg-(--ui-border)'"
177
+ />
178
+ </div>
179
+ <span
180
+ class="text-xs font-mono w-12 text-right"
181
+ :class="strength.score >= 4 ? 'text-(--ui-color-success-500)' : strength.score >= 2 ? 'text-(--ui-color-warning-500)' : 'text-(--ui-color-error-500)'"
182
+ >{{ strength.label }}</span>
183
+ </div>
184
+ <p
185
+ v-if="passwordTooShort"
186
+ class="text-xs text-(--ui-color-error-500)"
187
+ >
188
+ At least {{ minLength }} characters.
189
+ </p>
190
+ </div>
191
+
192
+ <div class="flex flex-col gap-1">
193
+ <label class="text-xs font-medium text-(--ui-text-muted)">Confirm password</label>
194
+ <UInput
195
+ v-model="confirm"
196
+ :type="showPassword ? 'text' : 'password'"
197
+ size="md"
198
+ autocomplete="new-password"
199
+ placeholder="Type it again"
200
+ icon="i-lucide-shield-check"
201
+ @keydown.enter="submit"
202
+ />
203
+ <p
204
+ v-if="confirmMismatch"
205
+ class="text-xs text-(--ui-color-error-500)"
206
+ >
207
+ Passwords don't match.
208
+ </p>
209
+ </div>
210
+
211
+ <div
212
+ v-if="showInviteCode"
213
+ class="flex flex-col gap-1"
214
+ >
215
+ <label class="text-xs font-medium text-(--ui-text-muted)">Invite code (optional)</label>
216
+ <UInput
217
+ v-model="inviteCode"
218
+ size="sm"
219
+ placeholder="paste invite code"
220
+ icon="i-lucide-ticket"
221
+ @keydown.enter="submit"
222
+ />
223
+ </div>
224
+
225
+ <div
226
+ v-if="showSignInLink"
227
+ class="-mt-1 text-xs"
228
+ >
229
+ <UButton
230
+ variant="link"
231
+ color="neutral"
232
+ size="xs"
233
+ label="Already have an account? Sign in"
234
+ @click="emit('signin')"
235
+ />
236
+ </div>
237
+ </div>
238
+ </template>
239
+
240
+ <template #footer>
241
+ <div class="flex items-center justify-end gap-2 w-full">
242
+ <UButton
243
+ variant="ghost"
244
+ color="neutral"
245
+ size="sm"
246
+ label="Cancel"
247
+ :disabled="loading"
248
+ @click="open = false"
249
+ />
250
+ <UButton
251
+ color="primary"
252
+ size="sm"
253
+ icon="i-lucide-user-plus"
254
+ label="Create account"
255
+ :loading="loading"
256
+ :disabled="!canSubmit"
257
+ @click="submit"
258
+ />
259
+ </div>
260
+ </template>
261
+ </UModal>
262
+ </template>
@@ -0,0 +1,49 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ error?: string | null;
5
+ title?: string;
6
+ subtitle?: string;
7
+ /** Server-enforced minimum password length (mirrored client-side). */
8
+ minLength?: number;
9
+ /** Show optional email field. */
10
+ showEmail?: boolean;
11
+ /** Show optional display-name field. */
12
+ showDisplayName?: boolean;
13
+ /** Show optional invite-code field. */
14
+ showInviteCode?: boolean;
15
+ /** Show "Already have an account? Sign in" link. */
16
+ showSignInLink?: boolean;
17
+ };
18
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
+ submit: (payload: {
20
+ username: string;
21
+ password: string;
22
+ email?: string;
23
+ displayName?: string;
24
+ inviteCode?: string;
25
+ }) => any;
26
+ "update:open": (v: boolean) => any;
27
+ signin: () => any;
28
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
29
+ onSubmit?: ((payload: {
30
+ username: string;
31
+ password: string;
32
+ email?: string;
33
+ displayName?: string;
34
+ inviteCode?: string;
35
+ }) => any) | undefined;
36
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
37
+ onSignin?: (() => any) | undefined;
38
+ }>, {
39
+ subtitle: string;
40
+ title: string;
41
+ minLength: number;
42
+ loading: boolean;
43
+ showInviteCode: boolean;
44
+ showEmail: boolean;
45
+ showDisplayName: boolean;
46
+ showSignInLink: boolean;
47
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
48
+ declare const _default: typeof __VLS_export;
49
+ export default _default;
@@ -0,0 +1,31 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ error?: string | null;
5
+ /** Pre-fill the token (e.g. from a query param when the email link lands here). */
6
+ initialToken?: string;
7
+ title?: string;
8
+ subtitle?: string;
9
+ minLength?: number;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ submit: (payload: {
13
+ token: string;
14
+ newPassword: string;
15
+ }) => any;
16
+ "update:open": (v: boolean) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
+ onSubmit?: ((payload: {
19
+ token: string;
20
+ newPassword: string;
21
+ }) => any) | undefined;
22
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
23
+ }>, {
24
+ subtitle: string;
25
+ title: string;
26
+ minLength: number;
27
+ loading: boolean;
28
+ initialToken: string;
29
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
+ declare const _default: typeof __VLS_export;
31
+ export default _default;
@@ -0,0 +1,154 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ const props = defineProps({
4
+ open: { type: Boolean, required: false },
5
+ loading: { type: Boolean, required: false, default: false },
6
+ error: { type: [String, null], required: false },
7
+ initialToken: { type: String, required: false, default: "" },
8
+ title: { type: String, required: false, default: "Choose a new password" },
9
+ subtitle: { type: String, required: false, default: "Paste the token from your reset email, then set a new password." },
10
+ minLength: { type: Number, required: false, default: 8 }
11
+ });
12
+ const emit = defineEmits(["update:open", "submit"]);
13
+ const open = computed({
14
+ get: () => !!props.open,
15
+ set: (v) => emit("update:open", v)
16
+ });
17
+ const token = ref("");
18
+ const newPassword = ref("");
19
+ const confirm = ref("");
20
+ const showPassword = ref(false);
21
+ watch(() => props.open, (v) => {
22
+ if (!v) return;
23
+ token.value = props.initialToken || "";
24
+ newPassword.value = "";
25
+ confirm.value = "";
26
+ showPassword.value = false;
27
+ });
28
+ const passwordTooShort = computed(
29
+ () => newPassword.value.length > 0 && newPassword.value.length < props.minLength
30
+ );
31
+ const confirmMismatch = computed(
32
+ () => confirm.value.length > 0 && confirm.value !== newPassword.value
33
+ );
34
+ const canSubmit = computed(
35
+ () => !!token.value.trim() && newPassword.value.length >= props.minLength && confirm.value === newPassword.value && !props.loading
36
+ );
37
+ function submit() {
38
+ if (!canSubmit.value) return;
39
+ emit("submit", {
40
+ token: token.value.trim(),
41
+ newPassword: newPassword.value
42
+ });
43
+ }
44
+ </script>
45
+
46
+ <template>
47
+ <UModal
48
+ v-model:open="open"
49
+ :title="title"
50
+ :ui="{ content: 'sm:max-w-md' }"
51
+ >
52
+ <template #body>
53
+ <div class="flex flex-col gap-4">
54
+ <p class="text-sm text-(--ui-text-muted)">
55
+ {{ subtitle }}
56
+ </p>
57
+
58
+ <UAlert
59
+ v-if="error"
60
+ color="error"
61
+ variant="soft"
62
+ icon="i-lucide-triangle-alert"
63
+ :description="error"
64
+ />
65
+
66
+ <div class="flex flex-col gap-1">
67
+ <label class="text-xs font-medium text-(--ui-text-muted)">Reset token</label>
68
+ <UInput
69
+ v-model="token"
70
+ size="md"
71
+ autofocus
72
+ placeholder="paste from email"
73
+ icon="i-lucide-key"
74
+ :ui="{ base: 'font-mono' }"
75
+ @keydown.enter="submit"
76
+ />
77
+ </div>
78
+
79
+ <div class="flex flex-col gap-1">
80
+ <label class="text-xs font-medium text-(--ui-text-muted)">New password</label>
81
+ <UInput
82
+ v-model="newPassword"
83
+ :type="showPassword ? 'text' : 'password'"
84
+ size="md"
85
+ autocomplete="new-password"
86
+ :placeholder="`${minLength}+ characters`"
87
+ icon="i-lucide-lock"
88
+ :ui="{ trailing: 'pe-1' }"
89
+ @keydown.enter="submit"
90
+ >
91
+ <template #trailing>
92
+ <UButton
93
+ tabindex="-1"
94
+ variant="ghost"
95
+ color="neutral"
96
+ size="xs"
97
+ :icon="showPassword ? 'i-lucide-eye-off' : 'i-lucide-eye'"
98
+ :aria-label="showPassword ? 'Hide password' : 'Show password'"
99
+ @click="showPassword = !showPassword"
100
+ />
101
+ </template>
102
+ </UInput>
103
+ <p
104
+ v-if="passwordTooShort"
105
+ class="text-xs text-(--ui-color-error-500)"
106
+ >
107
+ At least {{ minLength }} characters.
108
+ </p>
109
+ </div>
110
+
111
+ <div class="flex flex-col gap-1">
112
+ <label class="text-xs font-medium text-(--ui-text-muted)">Confirm new password</label>
113
+ <UInput
114
+ v-model="confirm"
115
+ :type="showPassword ? 'text' : 'password'"
116
+ size="md"
117
+ autocomplete="new-password"
118
+ placeholder="Type it again"
119
+ icon="i-lucide-shield-check"
120
+ @keydown.enter="submit"
121
+ />
122
+ <p
123
+ v-if="confirmMismatch"
124
+ class="text-xs text-(--ui-color-error-500)"
125
+ >
126
+ Passwords don't match.
127
+ </p>
128
+ </div>
129
+ </div>
130
+ </template>
131
+
132
+ <template #footer>
133
+ <div class="flex items-center justify-end gap-2 w-full">
134
+ <UButton
135
+ variant="ghost"
136
+ color="neutral"
137
+ size="sm"
138
+ label="Cancel"
139
+ :disabled="loading"
140
+ @click="open = false"
141
+ />
142
+ <UButton
143
+ color="primary"
144
+ size="sm"
145
+ icon="i-lucide-rotate-ccw-key"
146
+ label="Set new password"
147
+ :loading="loading"
148
+ :disabled="!canSubmit"
149
+ @click="submit"
150
+ />
151
+ </div>
152
+ </template>
153
+ </UModal>
154
+ </template>
@@ -0,0 +1,31 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ error?: string | null;
5
+ /** Pre-fill the token (e.g. from a query param when the email link lands here). */
6
+ initialToken?: string;
7
+ title?: string;
8
+ subtitle?: string;
9
+ minLength?: number;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ submit: (payload: {
13
+ token: string;
14
+ newPassword: string;
15
+ }) => any;
16
+ "update:open": (v: boolean) => any;
17
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
+ onSubmit?: ((payload: {
19
+ token: string;
20
+ newPassword: string;
21
+ }) => any) | undefined;
22
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
23
+ }>, {
24
+ subtitle: string;
25
+ title: string;
26
+ minLength: number;
27
+ loading: boolean;
28
+ initialToken: string;
29
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
+ declare const _default: typeof __VLS_export;
31
+ export default _default;
@@ -0,0 +1,35 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ /**
5
+ * Flip to true after the consumer's submit handler resolves; flips the modal to the
6
+ * "we sent an email if that account exists" confirmation copy.
7
+ */
8
+ sent?: boolean;
9
+ error?: string | null;
10
+ title?: string;
11
+ subtitle?: string;
12
+ /** Show the "Back to sign in" link in the footer. */
13
+ showSignInLink?: boolean;
14
+ };
15
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
16
+ submit: (payload: {
17
+ identifier: string;
18
+ }) => any;
19
+ "update:open": (v: boolean) => any;
20
+ signin: () => any;
21
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
22
+ onSubmit?: ((payload: {
23
+ identifier: string;
24
+ }) => any) | undefined;
25
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
26
+ onSignin?: (() => any) | undefined;
27
+ }>, {
28
+ subtitle: string;
29
+ title: string;
30
+ loading: boolean;
31
+ sent: boolean;
32
+ showSignInLink: boolean;
33
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
+ declare const _default: typeof __VLS_export;
35
+ export default _default;