@abraca/nuxt 2.0.0 → 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.
- package/dist/module.d.mts +18 -7
- package/dist/module.json +1 -1
- package/dist/module.mjs +21 -5
- package/dist/runtime/assets/aware-tokens.css +1 -0
- package/dist/runtime/components/AAccountSwitcherModal.d.vue.ts +16 -1
- package/dist/runtime/components/AAccountSwitcherModal.vue +33 -4
- package/dist/runtime/components/AAccountSwitcherModal.vue.d.ts +16 -1
- package/dist/runtime/components/AAuthLinkLanding.d.vue.ts +3 -0
- package/dist/runtime/components/AAuthLinkLanding.vue +85 -0
- package/dist/runtime/components/AAuthLinkLanding.vue.d.ts +3 -0
- package/dist/runtime/components/AClaimAccountModal.d.vue.ts +7 -1
- package/dist/runtime/components/AClaimAccountModal.vue +28 -13
- package/dist/runtime/components/AClaimAccountModal.vue.d.ts +7 -1
- package/dist/runtime/components/AEditor.vue +5 -0
- package/dist/runtime/components/AEmailVerifyConfirmModal.d.vue.ts +30 -0
- package/dist/runtime/components/AEmailVerifyConfirmModal.vue +100 -0
- package/dist/runtime/components/AEmailVerifyConfirmModal.vue.d.ts +30 -0
- package/dist/runtime/components/AEmailVerifyRequestCard.d.vue.ts +22 -0
- package/dist/runtime/components/AEmailVerifyRequestCard.vue +65 -0
- package/dist/runtime/components/AEmailVerifyRequestCard.vue.d.ts +22 -0
- package/dist/runtime/components/AMnemonicLoginModal.d.vue.ts +1 -1
- package/dist/runtime/components/AMnemonicLoginModal.vue.d.ts +1 -1
- package/dist/runtime/components/ANodePanel.vue +2 -0
- package/dist/runtime/components/ANotificationBell.d.vue.ts +2 -2
- package/dist/runtime/components/ANotificationBell.vue.d.ts +2 -2
- package/dist/runtime/components/APasswordChangeModal.d.vue.ts +28 -0
- package/dist/runtime/components/APasswordChangeModal.vue +178 -0
- package/dist/runtime/components/APasswordChangeModal.vue.d.ts +28 -0
- package/dist/runtime/components/APasswordLoginModal.d.vue.ts +42 -0
- package/dist/runtime/components/APasswordLoginModal.vue +177 -0
- package/dist/runtime/components/APasswordLoginModal.vue.d.ts +42 -0
- package/dist/runtime/components/APasswordRegisterModal.d.vue.ts +49 -0
- package/dist/runtime/components/APasswordRegisterModal.vue +262 -0
- package/dist/runtime/components/APasswordRegisterModal.vue.d.ts +49 -0
- package/dist/runtime/components/APasswordResetConfirmModal.d.vue.ts +31 -0
- package/dist/runtime/components/APasswordResetConfirmModal.vue +154 -0
- package/dist/runtime/components/APasswordResetConfirmModal.vue.d.ts +31 -0
- package/dist/runtime/components/APasswordResetRequestModal.d.vue.ts +35 -0
- package/dist/runtime/components/APasswordResetRequestModal.vue +113 -0
- package/dist/runtime/components/APasswordResetRequestModal.vue.d.ts +35 -0
- package/dist/runtime/components/ASetPasswordCard.d.vue.ts +26 -0
- package/dist/runtime/components/ASetPasswordCard.vue +139 -0
- package/dist/runtime/components/ASetPasswordCard.vue.d.ts +26 -0
- package/dist/runtime/components/ASubPageList.d.vue.ts +66 -0
- package/dist/runtime/components/ASubPageList.vue +147 -0
- package/dist/runtime/components/ASubPageList.vue.d.ts +66 -0
- package/dist/runtime/components/aware/AAccordion.d.vue.ts +2 -0
- package/dist/runtime/components/aware/AAccordion.vue +11 -1
- package/dist/runtime/components/aware/AAccordion.vue.d.ts +2 -0
- package/dist/runtime/components/aware/AButton.vue +3 -3
- package/dist/runtime/components/aware/ACollapsible.d.vue.ts +2 -0
- package/dist/runtime/components/aware/ACollapsible.vue +9 -1
- package/dist/runtime/components/aware/ACollapsible.vue.d.ts +2 -0
- package/dist/runtime/components/aware/AGlobalFocusLayer.vue +1 -1
- package/dist/runtime/components/aware/AHoverItem.vue +28 -3
- package/dist/runtime/components/aware/AMedia.d.vue.ts +1 -1
- package/dist/runtime/components/aware/AMedia.vue.d.ts +1 -1
- package/dist/runtime/components/aware/AModal.d.vue.ts +2 -0
- package/dist/runtime/components/aware/AModal.vue +9 -1
- package/dist/runtime/components/aware/AModal.vue.d.ts +2 -0
- package/dist/runtime/components/aware/APresenceBlobs.vue +1 -1
- package/dist/runtime/components/aware/APresenceCursors.vue +1 -1
- package/dist/runtime/components/aware/AScroll.d.vue.ts +2 -0
- package/dist/runtime/components/aware/AScroll.vue +13 -3
- package/dist/runtime/components/aware/AScroll.vue.d.ts +2 -0
- package/dist/runtime/components/aware/ASlideover.d.vue.ts +2 -0
- package/dist/runtime/components/aware/ASlideover.vue +9 -1
- package/dist/runtime/components/aware/ASlideover.vue.d.ts +2 -0
- package/dist/runtime/components/aware/ASlider.vue +1 -0
- package/dist/runtime/components/aware/ATabs.d.vue.ts +2 -0
- package/dist/runtime/components/aware/ATabs.vue +9 -1
- package/dist/runtime/components/aware/ATabs.vue.d.ts +2 -0
- package/dist/runtime/components/chat/ANodeChatPanel.vue +1 -0
- package/dist/runtime/components/editor/AEditorRedoButton.d.vue.ts +2 -2
- package/dist/runtime/components/editor/AEditorRedoButton.vue.d.ts +2 -2
- package/dist/runtime/components/editor/AEditorUndoButton.d.vue.ts +2 -2
- package/dist/runtime/components/editor/AEditorUndoButton.vue.d.ts +2 -2
- package/dist/runtime/components/renderers/calendar/ACalendarToolbar.d.vue.ts +4 -4
- package/dist/runtime/components/renderers/calendar/ACalendarToolbar.vue.d.ts +4 -4
- package/dist/runtime/components/renderers/media/MediaTransportBar.d.vue.ts +2 -2
- package/dist/runtime/components/renderers/media/MediaTransportBar.vue.d.ts +2 -2
- package/dist/runtime/components/shell/AUserProfilePopover.d.vue.ts +1 -1
- package/dist/runtime/components/shell/AUserProfilePopover.vue.d.ts +1 -1
- package/dist/runtime/composables/useAAField.js +7 -4
- package/dist/runtime/composables/useAAFocus.js +10 -5
- package/dist/runtime/composables/useAAFollowAnchor.js +68 -34
- package/dist/runtime/composables/useAAFollowPeer.d.ts +7 -4
- package/dist/runtime/composables/useAAFollowPeer.js +60 -11
- package/dist/runtime/composables/useAAViewport.d.ts +1 -1
- package/dist/runtime/composables/useAbracadabraAuth.d.ts +2 -0
- package/dist/runtime/composables/useAbracadabraAuth.js +2 -0
- package/dist/runtime/composables/useEditorSuggestions.js +2 -1
- package/dist/runtime/composables/useEmailVerification.d.ts +40 -26
- package/dist/runtime/composables/useEmailVerification.js +95 -43
- package/dist/runtime/composables/usePasswordAuth.d.ts +64 -0
- package/dist/runtime/composables/usePasswordAuth.js +126 -0
- package/dist/runtime/composables/useTiptapHistory.d.ts +2 -2
- package/dist/runtime/composables/useTiptapHistory.js +5 -5
- package/dist/runtime/extensions/svg-embed.d.ts +23 -0
- package/dist/runtime/extensions/svg-embed.js +33 -0
- package/dist/runtime/extensions/views/MetaFieldView.vue +23 -6
- package/dist/runtime/extensions/views/SvgEmbedView.d.vue.ts +4 -0
- package/dist/runtime/extensions/views/SvgEmbedView.vue +120 -0
- package/dist/runtime/extensions/views/SvgEmbedView.vue.d.ts +4 -0
- package/dist/runtime/plugin-abracadabra.client.js +58 -9
- package/dist/runtime/plugin-abracadabra.server.js +2 -0
- package/dist/runtime/plugins/core.plugin.js +8 -4
- package/dist/runtime/server/plugins/abracadabra-service.js +102 -13
- package/dist/runtime/types.d.ts +11 -0
- package/dist/runtime/utils/awareRingStyle.js +1 -1
- package/dist/runtime/utils/sanitizeSvg.d.ts +19 -0
- package/dist/runtime/utils/sanitizeSvg.js +87 -0
- package/package.json +7 -8
- package/dist/runtime/components/renderers/ASpatialRenderer.d.vue.ts +0 -19
- package/dist/runtime/components/renderers/ASpatialRenderer.vue +0 -459
- package/dist/runtime/components/renderers/ASpatialRenderer.vue.d.ts +0 -19
- package/dist/runtime/components/renderers/spatial/SpatialGround.d.vue.ts +0 -20
- package/dist/runtime/components/renderers/spatial/SpatialGround.vue +0 -26
- package/dist/runtime/components/renderers/spatial/SpatialGround.vue.d.ts +0 -20
- package/dist/runtime/components/renderers/spatial/SpatialObject.d.vue.ts +0 -17
- package/dist/runtime/components/renderers/spatial/SpatialObject.vue +0 -257
- package/dist/runtime/components/renderers/spatial/SpatialObject.vue.d.ts +0 -17
- package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.d.vue.ts +0 -15
- package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue +0 -18
- package/dist/runtime/components/renderers/spatial/SpatialSceneBridge.vue.d.ts +0 -15
- package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.d.vue.ts +0 -16
- package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.vue +0 -66
- package/dist/runtime/components/renderers/spatial/SpatialTransformInputs.vue.d.ts +0 -16
- package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.d.vue.ts +0 -8
- package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue +0 -53
- package/dist/runtime/components/renderers/spatial/SpatialUserAvatar.vue.d.ts +0 -8
- package/dist/runtime/composables/useSpatialCamera.d.ts +0 -16
- package/dist/runtime/composables/useSpatialCamera.js +0 -175
- package/dist/runtime/composables/useSpatialDrag.d.ts +0 -14
- package/dist/runtime/composables/useSpatialDrag.js +0 -137
package/dist/module.d.mts
CHANGED
|
@@ -40,7 +40,6 @@ declare module '@nuxt/schema' {
|
|
|
40
40
|
broadcastSync?: boolean;
|
|
41
41
|
webrtc?: boolean;
|
|
42
42
|
chat?: boolean;
|
|
43
|
-
spatial?: boolean;
|
|
44
43
|
media?: boolean;
|
|
45
44
|
slides?: boolean;
|
|
46
45
|
};
|
|
@@ -69,6 +68,10 @@ declare module '@nuxt/schema' {
|
|
|
69
68
|
e2ee: boolean;
|
|
70
69
|
fileTransfer: boolean;
|
|
71
70
|
};
|
|
71
|
+
authQueryKeys: {
|
|
72
|
+
resetToken: string | null;
|
|
73
|
+
verifyToken: string | null;
|
|
74
|
+
};
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
77
|
interface RuntimeConfig {
|
|
@@ -152,12 +155,6 @@ interface ModuleOptions {
|
|
|
152
155
|
* Default: false.
|
|
153
156
|
*/
|
|
154
157
|
chat?: boolean;
|
|
155
|
-
/**
|
|
156
|
-
* Register 3D spatial renderer and composables.
|
|
157
|
-
* Requires @tresjs/core and @tresjs/cientos as optional peer dependencies.
|
|
158
|
-
* Default: false.
|
|
159
|
-
*/
|
|
160
|
-
spatial?: boolean;
|
|
161
158
|
/**
|
|
162
159
|
* Register media playlist renderer with synced listening sessions.
|
|
163
160
|
* Default: false.
|
|
@@ -237,6 +234,20 @@ interface ModuleOptions {
|
|
|
237
234
|
adjectives?: string[];
|
|
238
235
|
nouns?: string[];
|
|
239
236
|
};
|
|
237
|
+
/**
|
|
238
|
+
* Query-string keys read by `<AAuthLinkLanding>` to auto-open the matching
|
|
239
|
+
* confirm modal when an email link lands the user at an app route. Set
|
|
240
|
+
* any value to `null` to disable that landing (e.g. if your app handles
|
|
241
|
+
* the flow itself or never uses email links).
|
|
242
|
+
*
|
|
243
|
+
* Defaults: `{ resetToken: 'reset_token', verifyToken: 'verify_token' }`.
|
|
244
|
+
*/
|
|
245
|
+
authQueryKeys?: {
|
|
246
|
+
/** Query param holding the password-reset token. Default: 'reset_token'. */
|
|
247
|
+
resetToken?: string | null;
|
|
248
|
+
/** Query param holding the email-verification token. Default: 'verify_token'. */
|
|
249
|
+
verifyToken?: string | null;
|
|
250
|
+
};
|
|
240
251
|
/**
|
|
241
252
|
* WebRTC P2P configuration. Only used when features.webrtc is true.
|
|
242
253
|
*/
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -31,7 +31,6 @@ const module$1 = defineNuxtModule({
|
|
|
31
31
|
broadcastSync: true,
|
|
32
32
|
webrtc: false,
|
|
33
33
|
chat: false,
|
|
34
|
-
spatial: false,
|
|
35
34
|
media: false,
|
|
36
35
|
slides: true
|
|
37
36
|
},
|
|
@@ -55,6 +54,10 @@ const module$1 = defineNuxtModule({
|
|
|
55
54
|
e2ee: false,
|
|
56
55
|
fileTransfer: false
|
|
57
56
|
},
|
|
57
|
+
authQueryKeys: {
|
|
58
|
+
resetToken: "reset_token",
|
|
59
|
+
verifyToken: "verify_token"
|
|
60
|
+
},
|
|
58
61
|
service: {
|
|
59
62
|
disabled: false
|
|
60
63
|
}
|
|
@@ -85,6 +88,10 @@ const module$1 = defineNuxtModule({
|
|
|
85
88
|
iceServers: options.webrtc?.iceServers ?? [{ urls: "stun:stun.l.google.com:19302" }],
|
|
86
89
|
e2ee: options.webrtc?.e2ee ?? false,
|
|
87
90
|
fileTransfer: options.webrtc?.fileTransfer ?? false
|
|
91
|
+
},
|
|
92
|
+
authQueryKeys: {
|
|
93
|
+
resetToken: options.authQueryKeys?.resetToken ?? "reset_token",
|
|
94
|
+
verifyToken: options.authQueryKeys?.verifyToken ?? "verify_token"
|
|
88
95
|
}
|
|
89
96
|
}
|
|
90
97
|
}
|
|
@@ -209,8 +216,10 @@ const module$1 = defineNuxtModule({
|
|
|
209
216
|
// from internal modules (ChannelKeyResolver, decryptChatContent, foldRecords,
|
|
210
217
|
// recordFromYAny, isEncryptedContent) get dropped — useChat.ts then fails to
|
|
211
218
|
// import them. Excluding from optimizeDeps means Vite serves it native ESM.
|
|
212
|
-
|
|
213
|
-
|
|
219
|
+
// Also: `@noble/ed25519` v3 exposes the runtime hash hook via the named
|
|
220
|
+
// export `hashes` (a const object). esbuild's pre-bundling tree-shakes
|
|
221
|
+
// that export from the dynamic-import namespace, leaving `ed.hashes`
|
|
222
|
+
// undefined at runtime. Serve native ESM to preserve the live binding.
|
|
214
223
|
// Composable + util deps
|
|
215
224
|
"@vueuse/core",
|
|
216
225
|
"nanoevents"
|
|
@@ -225,8 +234,16 @@ const module$1 = defineNuxtModule({
|
|
|
225
234
|
];
|
|
226
235
|
const existingExclude = nuxt.options.vite.optimizeDeps.exclude ?? [];
|
|
227
236
|
nuxt.options.vite.optimizeDeps.exclude = [
|
|
228
|
-
.../* @__PURE__ */ new Set([
|
|
237
|
+
.../* @__PURE__ */ new Set([
|
|
238
|
+
...existingExclude,
|
|
239
|
+
"@abraca/dabra",
|
|
240
|
+
"@noble/ed25519",
|
|
241
|
+
"@noble/hashes/sha2.js",
|
|
242
|
+
"@noble/hashes/hkdf.js",
|
|
243
|
+
"@noble/curves/ed25519.js"
|
|
244
|
+
])
|
|
229
245
|
];
|
|
246
|
+
nuxt.options.css.push(resolver.resolve("./runtime/assets/aware-tokens.css"));
|
|
230
247
|
if (options.features?.editor !== false) {
|
|
231
248
|
nuxt.options.css.push(resolver.resolve("./runtime/assets/editor.css"));
|
|
232
249
|
}
|
|
@@ -290,7 +307,6 @@ const module$1 = defineNuxtModule({
|
|
|
290
307
|
"**/table/**",
|
|
291
308
|
"**/timeline/**",
|
|
292
309
|
"**/media/**",
|
|
293
|
-
"**/spatial/**",
|
|
294
310
|
"**/gallery/**",
|
|
295
311
|
"**/sheets/**",
|
|
296
312
|
"**/slides/**",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--aa-track-cursor-duration:60ms;--aa-track-cursor-easing:linear;--aa-track-blob-duration:200ms;--aa-track-blob-easing:ease-out;--aa-state-fade-shadow:100ms ease;--aa-state-fade-filter:120ms ease;--aa-pulse-duration:260ms;--aa-pulse-easing:ease-out;--aa-pulse-radius-button:12px;--aa-pulse-radius-item:14px;--aa-pulse-opacity-start-button:0.45;--aa-pulse-opacity-start-item:0.5;--aa-peer-fade-duration:150ms;--aa-peer-fade-easing:ease;--aa-flag-fade-duration:120ms;--aa-flag-fade-easing:ease}
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
open: boolean;
|
|
3
|
+
/** Show the "Sign in with password" link in the footer. */
|
|
4
|
+
showPasswordSignIn?: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Show the "Add a password to this account" CTA when the signed-in user has no
|
|
7
|
+
* password set. Drives the flow described in `gaps/14-password-auth.md`
|
|
8
|
+
* (key-only soft identity opting into a recovery credential).
|
|
9
|
+
*/
|
|
10
|
+
showAddPasswordCta?: boolean;
|
|
3
11
|
};
|
|
4
12
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
13
|
"update:open": (v: boolean) => any;
|
|
14
|
+
"password-signin": () => any;
|
|
15
|
+
"add-password": () => any;
|
|
6
16
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
17
|
"onUpdate:open"?: ((v: boolean) => any) | undefined;
|
|
8
|
-
|
|
18
|
+
"onPassword-signin"?: (() => any) | undefined;
|
|
19
|
+
"onAdd-password"?: (() => any) | undefined;
|
|
20
|
+
}>, {
|
|
21
|
+
showPasswordSignIn: boolean;
|
|
22
|
+
showAddPasswordCta: boolean;
|
|
23
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
24
|
declare const _default: typeof __VLS_export;
|
|
10
25
|
export default _default;
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, watch } from "vue";
|
|
2
|
+
import { computed, ref, watch } from "vue";
|
|
3
3
|
import { useAbracadabra } from "../composables/useAbracadabra";
|
|
4
4
|
import { usePasskeyAccounts } from "../composables/usePasskeyAccounts";
|
|
5
5
|
const props = defineProps({
|
|
6
|
-
open: { type: Boolean, required: true }
|
|
6
|
+
open: { type: Boolean, required: true },
|
|
7
|
+
showPasswordSignIn: { type: Boolean, required: false, default: true },
|
|
8
|
+
showAddPasswordCta: { type: Boolean, required: false, default: true }
|
|
7
9
|
});
|
|
8
|
-
const emit = defineEmits(["update:open"]);
|
|
9
|
-
const { loginWithHardware, publicKeyB64 } = useAbracadabra();
|
|
10
|
+
const emit = defineEmits(["update:open", "password-signin", "add-password"]);
|
|
11
|
+
const { loginWithHardware, publicKeyB64, hasPassword, isClaimed } = useAbracadabra();
|
|
10
12
|
const { accounts: passkeyAccounts } = usePasskeyAccounts();
|
|
13
|
+
const showAddPassword = computed(
|
|
14
|
+
() => props.showAddPasswordCta && isClaimed.value && !hasPassword.value
|
|
15
|
+
);
|
|
11
16
|
const isLoading = ref(null);
|
|
12
17
|
const error = ref(null);
|
|
13
18
|
watch(() => props.open, (open) => {
|
|
@@ -152,6 +157,30 @@ async function loginAny() {
|
|
|
152
157
|
>
|
|
153
158
|
Use Any Passkey
|
|
154
159
|
</UButton>
|
|
160
|
+
|
|
161
|
+
<UButton
|
|
162
|
+
v-if="showPasswordSignIn"
|
|
163
|
+
variant="ghost"
|
|
164
|
+
color="neutral"
|
|
165
|
+
icon="i-lucide-key-square"
|
|
166
|
+
class="w-full justify-start"
|
|
167
|
+
@click="emit('update:open', false);
|
|
168
|
+
emit('password-signin')"
|
|
169
|
+
>
|
|
170
|
+
Sign in with password
|
|
171
|
+
</UButton>
|
|
172
|
+
|
|
173
|
+
<UButton
|
|
174
|
+
v-if="showAddPassword"
|
|
175
|
+
variant="soft"
|
|
176
|
+
color="primary"
|
|
177
|
+
icon="i-lucide-shield-plus"
|
|
178
|
+
class="w-full justify-start"
|
|
179
|
+
@click="emit('update:open', false);
|
|
180
|
+
emit('add-password')"
|
|
181
|
+
>
|
|
182
|
+
Add a password to this account
|
|
183
|
+
</UButton>
|
|
155
184
|
</div>
|
|
156
185
|
</template>
|
|
157
186
|
</UModal>
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
open: boolean;
|
|
3
|
+
/** Show the "Sign in with password" link in the footer. */
|
|
4
|
+
showPasswordSignIn?: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Show the "Add a password to this account" CTA when the signed-in user has no
|
|
7
|
+
* password set. Drives the flow described in `gaps/14-password-auth.md`
|
|
8
|
+
* (key-only soft identity opting into a recovery credential).
|
|
9
|
+
*/
|
|
10
|
+
showAddPasswordCta?: boolean;
|
|
3
11
|
};
|
|
4
12
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
13
|
"update:open": (v: boolean) => any;
|
|
14
|
+
"password-signin": () => any;
|
|
15
|
+
"add-password": () => any;
|
|
6
16
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
17
|
"onUpdate:open"?: ((v: boolean) => any) | undefined;
|
|
8
|
-
|
|
18
|
+
"onPassword-signin"?: (() => any) | undefined;
|
|
19
|
+
"onAdd-password"?: (() => any) | undefined;
|
|
20
|
+
}>, {
|
|
21
|
+
showPasswordSignIn: boolean;
|
|
22
|
+
showAddPasswordCta: boolean;
|
|
23
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
24
|
declare const _default: typeof __VLS_export;
|
|
10
25
|
export default _default;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
3
|
+
export default _default;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed, ref, watch } from "vue";
|
|
3
|
+
import { useRoute, useRouter, useRuntimeConfig } from "#imports";
|
|
4
|
+
import { usePasswordAuth } from "../composables/usePasswordAuth";
|
|
5
|
+
import { useEmailVerification } from "../composables/useEmailVerification";
|
|
6
|
+
const config = useRuntimeConfig();
|
|
7
|
+
const keys = config.public.abracadabra.authQueryKeys;
|
|
8
|
+
const route = useRoute();
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const pw = usePasswordAuth();
|
|
11
|
+
const ev = useEmailVerification();
|
|
12
|
+
const resetOpen = ref(false);
|
|
13
|
+
const resetInitialToken = ref("");
|
|
14
|
+
const verifyOpen = ref(false);
|
|
15
|
+
const verifyInitialToken = ref("");
|
|
16
|
+
function readQuery(key) {
|
|
17
|
+
if (!key) return "";
|
|
18
|
+
const v = route.query[key];
|
|
19
|
+
if (typeof v === "string") return v.trim();
|
|
20
|
+
if (Array.isArray(v) && typeof v[0] === "string") return v[0].trim();
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
function stripQueryKey(key) {
|
|
24
|
+
if (!key) return;
|
|
25
|
+
if (typeof window === "undefined") return;
|
|
26
|
+
const url = new URL(window.location.href);
|
|
27
|
+
if (!url.searchParams.has(key)) return;
|
|
28
|
+
url.searchParams.delete(key);
|
|
29
|
+
const next = `${url.pathname}${url.search ? `?${url.searchParams}` : ""}${url.hash}`;
|
|
30
|
+
router.replace({ query: { ...route.query, [key]: void 0 } }).catch(() => {
|
|
31
|
+
window.history.replaceState(window.history.state, "", next);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const resetTokenSeen = computed(() => readQuery(keys.resetToken));
|
|
35
|
+
watch(resetTokenSeen, (token) => {
|
|
36
|
+
if (!token) return;
|
|
37
|
+
resetInitialToken.value = token;
|
|
38
|
+
resetOpen.value = true;
|
|
39
|
+
}, { immediate: true });
|
|
40
|
+
async function onResetSubmit(p) {
|
|
41
|
+
const res = await pw.confirmReset(p);
|
|
42
|
+
if (res.ok) {
|
|
43
|
+
resetOpen.value = false;
|
|
44
|
+
stripQueryKey(keys.resetToken);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
watch(resetOpen, (open) => {
|
|
48
|
+
if (!open) stripQueryKey(keys.resetToken);
|
|
49
|
+
});
|
|
50
|
+
const verifyTokenSeen = computed(() => readQuery(keys.verifyToken));
|
|
51
|
+
watch(verifyTokenSeen, (token) => {
|
|
52
|
+
if (!token) return;
|
|
53
|
+
verifyInitialToken.value = token;
|
|
54
|
+
verifyOpen.value = true;
|
|
55
|
+
}, { immediate: true });
|
|
56
|
+
async function onVerifySubmit(p) {
|
|
57
|
+
const res = await ev.confirm(p);
|
|
58
|
+
if (res.ok) {
|
|
59
|
+
stripQueryKey(keys.verifyToken);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
watch(verifyOpen, (open) => {
|
|
63
|
+
if (!open) stripQueryKey(keys.verifyToken);
|
|
64
|
+
});
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<APasswordResetConfirmModal
|
|
69
|
+
v-if="keys.resetToken"
|
|
70
|
+
v-model:open="resetOpen"
|
|
71
|
+
:loading="pw.busy.value === 'reset-confirm'"
|
|
72
|
+
:error="pw.busy.value === null && pw.error.value && pw.lastSuccess.value !== 'reset-confirm' ? pw.error.value.message : null"
|
|
73
|
+
:initial-token="resetInitialToken"
|
|
74
|
+
@submit="onResetSubmit"
|
|
75
|
+
/>
|
|
76
|
+
<AEmailVerifyConfirmModal
|
|
77
|
+
v-if="keys.verifyToken"
|
|
78
|
+
v-model:open="verifyOpen"
|
|
79
|
+
:loading="ev.busy.value === 'confirm'"
|
|
80
|
+
:success="ev.verified.value"
|
|
81
|
+
:error="ev.busy.value === null && ev.error.value && ev.lastSuccess.value !== 'confirm' ? ev.error.value.message : null"
|
|
82
|
+
:initial-token="verifyInitialToken"
|
|
83
|
+
@submit="onVerifySubmit"
|
|
84
|
+
/>
|
|
85
|
+
</template>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
3
|
+
export default _default;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
open: boolean;
|
|
3
|
+
/** Show the "Use a password instead" link in the identity step. */
|
|
4
|
+
showPasswordOption?: boolean;
|
|
3
5
|
};
|
|
4
6
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
7
|
"update:open": (v: boolean) => any;
|
|
8
|
+
"password-signup": () => any;
|
|
6
9
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
10
|
"onUpdate:open"?: ((v: boolean) => any) | undefined;
|
|
8
|
-
|
|
11
|
+
"onPassword-signup"?: (() => any) | undefined;
|
|
12
|
+
}>, {
|
|
13
|
+
showPasswordOption: boolean;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
15
|
declare const _default: typeof __VLS_export;
|
|
10
16
|
export default _default;
|
|
@@ -3,9 +3,10 @@ import { ref, watch } from "vue";
|
|
|
3
3
|
import { UI_COLORS } from "../types";
|
|
4
4
|
import { useAbracadabra } from "../composables/useAbracadabra";
|
|
5
5
|
const props = defineProps({
|
|
6
|
-
open: { type: Boolean, required: true }
|
|
6
|
+
open: { type: Boolean, required: true },
|
|
7
|
+
showPasswordOption: { type: Boolean, required: false, default: true }
|
|
7
8
|
});
|
|
8
|
-
const emit = defineEmits(["update:open"]);
|
|
9
|
+
const emit = defineEmits(["update:open", "password-signup"]);
|
|
9
10
|
const {
|
|
10
11
|
userName,
|
|
11
12
|
userColorName,
|
|
@@ -90,19 +91,19 @@ async function handleClaim() {
|
|
|
90
91
|
<p class="text-xs font-medium text-(--ui-text-muted) uppercase tracking-wide">
|
|
91
92
|
Identity Color
|
|
92
93
|
</p>
|
|
93
|
-
<div class="
|
|
94
|
-
<
|
|
94
|
+
<div class="claim-swatches">
|
|
95
|
+
<button
|
|
95
96
|
v-for="color in UI_COLORS"
|
|
96
97
|
:key="color"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
type="button"
|
|
99
|
+
:title="color"
|
|
100
|
+
:aria-label="color"
|
|
101
|
+
:aria-pressed="userColorName === color"
|
|
102
|
+
class="claim-swatch focus:outline-none"
|
|
103
|
+
:class="userColorName === color ? 'claim-swatch--selected' : ''"
|
|
104
|
+
:style="{ background: `var(--color-${color}-400)` }"
|
|
105
|
+
@click="setUserColor(color)"
|
|
106
|
+
/>
|
|
106
107
|
</div>
|
|
107
108
|
</div>
|
|
108
109
|
|
|
@@ -124,6 +125,16 @@ async function handleClaim() {
|
|
|
124
125
|
block
|
|
125
126
|
@click="emit('update:open', false)"
|
|
126
127
|
/>
|
|
128
|
+
|
|
129
|
+
<button
|
|
130
|
+
v-if="showPasswordOption"
|
|
131
|
+
type="button"
|
|
132
|
+
class="text-xs text-(--ui-text-muted) hover:text-(--ui-text-highlighted) underline underline-offset-4 mx-auto -mt-2"
|
|
133
|
+
@click="emit('update:open', false);
|
|
134
|
+
emit('password-signup')"
|
|
135
|
+
>
|
|
136
|
+
Use a password instead
|
|
137
|
+
</button>
|
|
127
138
|
</div>
|
|
128
139
|
|
|
129
140
|
<!-- Step 2: Passkey ceremony -->
|
|
@@ -228,3 +239,7 @@ async function handleClaim() {
|
|
|
228
239
|
</template>
|
|
229
240
|
</UModal>
|
|
230
241
|
</template>
|
|
242
|
+
|
|
243
|
+
<style scoped>
|
|
244
|
+
.claim-swatches{display:grid;gap:.45rem;grid-template-columns:repeat(auto-fit,1.25rem);justify-content:center;max-width:18rem}.claim-swatch{border:none;border-radius:999px;box-shadow:0 0 0 0 transparent;cursor:pointer;height:1.25rem;padding:0;transition:transform .15s ease,box-shadow .15s ease;width:1.25rem}.claim-swatch:hover{transform:scale(1.12)}.claim-swatch--selected{box-shadow:0 0 0 2px var(--ui-bg),0 0 0 4px var(--ui-text-highlighted);transform:scale(1.18)}
|
|
245
|
+
</style>
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
open: boolean;
|
|
3
|
+
/** Show the "Use a password instead" link in the identity step. */
|
|
4
|
+
showPasswordOption?: boolean;
|
|
3
5
|
};
|
|
4
6
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
7
|
"update:open": (v: boolean) => any;
|
|
8
|
+
"password-signup": () => any;
|
|
6
9
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
10
|
"onUpdate:open"?: ((v: boolean) => any) | undefined;
|
|
8
|
-
|
|
11
|
+
"onPassword-signup"?: (() => any) | undefined;
|
|
12
|
+
}>, {
|
|
13
|
+
showPasswordOption: boolean;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
15
|
declare const _default: typeof __VLS_export;
|
|
10
16
|
export default _default;
|
|
@@ -323,6 +323,11 @@ const editorHandlers = {
|
|
|
323
323
|
language: "js"
|
|
324
324
|
}),
|
|
325
325
|
isActive: (editor) => editor.isActive("diff")
|
|
326
|
+
},
|
|
327
|
+
svgEmbed: {
|
|
328
|
+
canExecute: () => true,
|
|
329
|
+
execute: (editor) => insertNode(editor, "svgEmbed", { svg: "", title: "", width: null, height: null }),
|
|
330
|
+
isActive: (editor) => editor.isActive("svgEmbed")
|
|
326
331
|
}
|
|
327
332
|
};
|
|
328
333
|
const _mentionItems = computed(
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open?: boolean;
|
|
3
|
+
loading?: boolean;
|
|
4
|
+
error?: string | null;
|
|
5
|
+
/** Flip to true after a successful confirm — modal pivots to a success body. */
|
|
6
|
+
success?: boolean;
|
|
7
|
+
/** Pre-fill the token (e.g. from a query param). */
|
|
8
|
+
initialToken?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
subtitle?: string;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
submit: (payload: {
|
|
14
|
+
token: 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
|
+
}) => any) | undefined;
|
|
21
|
+
"onUpdate:open"?: ((v: boolean) => any) | undefined;
|
|
22
|
+
}>, {
|
|
23
|
+
subtitle: string;
|
|
24
|
+
title: string;
|
|
25
|
+
success: boolean;
|
|
26
|
+
loading: boolean;
|
|
27
|
+
initialToken: string;
|
|
28
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
30
|
+
export default _default;
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
success: { type: Boolean, required: false, default: false },
|
|
8
|
+
initialToken: { type: String, required: false, default: "" },
|
|
9
|
+
title: { type: String, required: false, default: "Verify your email" },
|
|
10
|
+
subtitle: { type: String, required: false, default: "Paste the token from your verification email to confirm your address." }
|
|
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
|
+
watch(() => props.open, (v) => {
|
|
19
|
+
if (!v) return;
|
|
20
|
+
token.value = props.initialToken || "";
|
|
21
|
+
});
|
|
22
|
+
const canSubmit = computed(
|
|
23
|
+
() => !!token.value.trim() && !props.loading && !props.success
|
|
24
|
+
);
|
|
25
|
+
function submit() {
|
|
26
|
+
if (!canSubmit.value) return;
|
|
27
|
+
emit("submit", { token: token.value.trim() });
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<UModal
|
|
33
|
+
v-model:open="open"
|
|
34
|
+
:title="title"
|
|
35
|
+
:ui="{ content: 'sm:max-w-md' }"
|
|
36
|
+
>
|
|
37
|
+
<template #body>
|
|
38
|
+
<div class="flex flex-col gap-4">
|
|
39
|
+
<UAlert
|
|
40
|
+
v-if="success"
|
|
41
|
+
color="success"
|
|
42
|
+
variant="soft"
|
|
43
|
+
icon="i-lucide-shield-check"
|
|
44
|
+
title="Email verified"
|
|
45
|
+
description="Your email address is now confirmed. You can close this dialog."
|
|
46
|
+
/>
|
|
47
|
+
|
|
48
|
+
<template v-else>
|
|
49
|
+
<p class="text-sm text-(--ui-text-muted)">
|
|
50
|
+
{{ subtitle }}
|
|
51
|
+
</p>
|
|
52
|
+
|
|
53
|
+
<UAlert
|
|
54
|
+
v-if="error"
|
|
55
|
+
color="error"
|
|
56
|
+
variant="soft"
|
|
57
|
+
icon="i-lucide-triangle-alert"
|
|
58
|
+
:description="error"
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
<div class="flex flex-col gap-1">
|
|
62
|
+
<label class="text-xs font-medium text-(--ui-text-muted)">Verification token</label>
|
|
63
|
+
<UInput
|
|
64
|
+
v-model="token"
|
|
65
|
+
size="md"
|
|
66
|
+
autofocus
|
|
67
|
+
placeholder="paste from email"
|
|
68
|
+
icon="i-lucide-key"
|
|
69
|
+
:ui="{ base: 'font-mono' }"
|
|
70
|
+
@keydown.enter="submit"
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
</template>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
|
|
77
|
+
<template #footer>
|
|
78
|
+
<div class="flex items-center justify-end gap-2 w-full">
|
|
79
|
+
<UButton
|
|
80
|
+
variant="ghost"
|
|
81
|
+
color="neutral"
|
|
82
|
+
size="sm"
|
|
83
|
+
:label="success ? 'Close' : 'Cancel'"
|
|
84
|
+
:disabled="loading"
|
|
85
|
+
@click="open = false"
|
|
86
|
+
/>
|
|
87
|
+
<UButton
|
|
88
|
+
v-if="!success"
|
|
89
|
+
color="primary"
|
|
90
|
+
size="sm"
|
|
91
|
+
icon="i-lucide-check"
|
|
92
|
+
label="Confirm email"
|
|
93
|
+
:loading="loading"
|
|
94
|
+
:disabled="!canSubmit"
|
|
95
|
+
@click="submit"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
</template>
|
|
99
|
+
</UModal>
|
|
100
|
+
</template>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open?: boolean;
|
|
3
|
+
loading?: boolean;
|
|
4
|
+
error?: string | null;
|
|
5
|
+
/** Flip to true after a successful confirm — modal pivots to a success body. */
|
|
6
|
+
success?: boolean;
|
|
7
|
+
/** Pre-fill the token (e.g. from a query param). */
|
|
8
|
+
initialToken?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
subtitle?: string;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
|
+
submit: (payload: {
|
|
14
|
+
token: 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
|
+
}) => any) | undefined;
|
|
21
|
+
"onUpdate:open"?: ((v: boolean) => any) | undefined;
|
|
22
|
+
}>, {
|
|
23
|
+
subtitle: string;
|
|
24
|
+
title: string;
|
|
25
|
+
success: boolean;
|
|
26
|
+
loading: boolean;
|
|
27
|
+
initialToken: string;
|
|
28
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
30
|
+
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
loading?: boolean;
|
|
3
|
+
/** Flip to true after the consumer's request handler resolves. */
|
|
4
|
+
sent?: boolean;
|
|
5
|
+
error?: string | null;
|
|
6
|
+
/** Address shown in the cooldown copy ("we sent a link to <email>"). Optional. */
|
|
7
|
+
email?: string | null;
|
|
8
|
+
title?: string;
|
|
9
|
+
subtitle?: string;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
|
+
request: () => any;
|
|
13
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onRequest?: (() => any) | undefined;
|
|
15
|
+
}>, {
|
|
16
|
+
subtitle: string;
|
|
17
|
+
title: string;
|
|
18
|
+
loading: boolean;
|
|
19
|
+
sent: boolean;
|
|
20
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|