@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
|
@@ -20,16 +20,16 @@ type __VLS_Props = {
|
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
23
|
-
next: () => any;
|
|
24
|
-
prev: () => any;
|
|
25
23
|
"update:viewMode": (mode: CalendarViewMode) => any;
|
|
24
|
+
prev: () => any;
|
|
25
|
+
next: () => any;
|
|
26
26
|
today: () => any;
|
|
27
27
|
"add-event": () => any;
|
|
28
28
|
"navigate-to-month": (year: number, month: number) => any;
|
|
29
29
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
30
|
-
onNext?: (() => any) | undefined;
|
|
31
|
-
onPrev?: (() => any) | undefined;
|
|
32
30
|
"onUpdate:viewMode"?: ((mode: CalendarViewMode) => any) | undefined;
|
|
31
|
+
onPrev?: (() => any) | undefined;
|
|
32
|
+
onNext?: (() => any) | undefined;
|
|
33
33
|
onToday?: (() => any) | undefined;
|
|
34
34
|
"onAdd-event"?: (() => any) | undefined;
|
|
35
35
|
"onNavigate-to-month"?: ((year: number, month: number) => any) | undefined;
|
|
@@ -8,13 +8,13 @@ type __VLS_Props = {
|
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
};
|
|
10
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
-
next: () => any;
|
|
12
11
|
prev: () => any;
|
|
12
|
+
next: () => any;
|
|
13
13
|
togglePlay: () => any;
|
|
14
14
|
seek: (position: number) => any;
|
|
15
15
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
|
-
onNext?: (() => any) | undefined;
|
|
17
16
|
onPrev?: (() => any) | undefined;
|
|
17
|
+
onNext?: (() => any) | undefined;
|
|
18
18
|
onTogglePlay?: (() => any) | undefined;
|
|
19
19
|
onSeek?: ((position: number) => any) | undefined;
|
|
20
20
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -8,13 +8,13 @@ type __VLS_Props = {
|
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
};
|
|
10
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
-
next: () => any;
|
|
12
11
|
prev: () => any;
|
|
12
|
+
next: () => any;
|
|
13
13
|
togglePlay: () => any;
|
|
14
14
|
seek: (position: number) => any;
|
|
15
15
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
|
-
onNext?: (() => any) | undefined;
|
|
17
16
|
onPrev?: (() => any) | undefined;
|
|
17
|
+
onNext?: (() => any) | undefined;
|
|
18
18
|
onTogglePlay?: (() => any) | undefined;
|
|
19
19
|
onSeek?: ((position: number) => any) | undefined;
|
|
20
20
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -39,8 +39,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
39
39
|
currentDocId: string | null;
|
|
40
40
|
avatarStyle: string;
|
|
41
41
|
isSelf: boolean;
|
|
42
|
-
showFollow: boolean;
|
|
43
42
|
isFollowing: boolean;
|
|
43
|
+
showFollow: boolean;
|
|
44
44
|
currentDocLabel: string | null;
|
|
45
45
|
currentDocIcon: string;
|
|
46
46
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -39,8 +39,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
39
39
|
currentDocId: string | null;
|
|
40
40
|
avatarStyle: string;
|
|
41
41
|
isSelf: boolean;
|
|
42
|
-
showFollow: boolean;
|
|
43
42
|
isFollowing: boolean;
|
|
43
|
+
showFollow: boolean;
|
|
44
44
|
currentDocLabel: string | null;
|
|
45
45
|
currentDocIcon: string;
|
|
46
46
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -2,7 +2,7 @@ import { computed, isRef, onScopeDispose, ref } from "vue";
|
|
|
2
2
|
import { useAwareness } from "./useAwareness.js";
|
|
3
3
|
import { useAwarenessPeers } from "./useAwarenessPeers.js";
|
|
4
4
|
export function useAAField(key) {
|
|
5
|
-
const { setField } = useAwareness();
|
|
5
|
+
const { setField, localState } = useAwareness();
|
|
6
6
|
const { peers } = useAwarenessPeers();
|
|
7
7
|
const fieldKey = computed(
|
|
8
8
|
() => typeof key === "function" ? key() : isRef(key) ? key.value : key
|
|
@@ -38,7 +38,8 @@ export function useAAField(key) {
|
|
|
38
38
|
setField("hover", fieldKey.value);
|
|
39
39
|
}
|
|
40
40
|
function onMouseleave() {
|
|
41
|
-
|
|
41
|
+
const current = localState.value?.hover;
|
|
42
|
+
if (current === fieldKey.value) setField("hover", null);
|
|
42
43
|
}
|
|
43
44
|
function onMousedown() {
|
|
44
45
|
localPress.value = true;
|
|
@@ -46,13 +47,15 @@ export function useAAField(key) {
|
|
|
46
47
|
}
|
|
47
48
|
function onMouseup() {
|
|
48
49
|
localPress.value = false;
|
|
49
|
-
|
|
50
|
+
const current = localState.value?.press;
|
|
51
|
+
if (current === fieldKey.value) setField("press", null);
|
|
50
52
|
}
|
|
51
53
|
function onFocus() {
|
|
52
54
|
setField("focus", fieldKey.value);
|
|
53
55
|
}
|
|
54
56
|
function onBlur() {
|
|
55
|
-
|
|
57
|
+
const current = localState.value?.focus;
|
|
58
|
+
if (current === fieldKey.value) setField("focus", null);
|
|
56
59
|
}
|
|
57
60
|
const isPressed = computed(() => localPress.value || pressers.value.length > 0);
|
|
58
61
|
const handlers = {
|
|
@@ -97,12 +97,17 @@ export function useAAFocus() {
|
|
|
97
97
|
const candidates = document.elementsFromPoint(clientX, clientY);
|
|
98
98
|
for (const el of candidates) {
|
|
99
99
|
if (!isAnchorable(el)) continue;
|
|
100
|
-
const
|
|
101
|
-
if (!
|
|
102
|
-
const
|
|
103
|
-
return { elementPath:
|
|
100
|
+
const path2 = pathFromElement(el);
|
|
101
|
+
if (!path2) continue;
|
|
102
|
+
const r2 = el.getBoundingClientRect();
|
|
103
|
+
return { elementPath: path2, dx: clientX - r2.left, dy: clientY - r2.top };
|
|
104
104
|
}
|
|
105
|
-
|
|
105
|
+
const picked = pickAnchorElement();
|
|
106
|
+
if (!picked) return null;
|
|
107
|
+
const path = pathFromElement(picked.el);
|
|
108
|
+
if (!path) return null;
|
|
109
|
+
const r = picked.el.getBoundingClientRect();
|
|
110
|
+
return { elementPath: path, dx: clientX - r.left, dy: clientY - r.top };
|
|
106
111
|
}
|
|
107
112
|
function snapshot() {
|
|
108
113
|
cancelAnimationFrame(raf);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, watch } from "vue";
|
|
1
|
+
import { computed, onScopeDispose, watch } from "vue";
|
|
2
2
|
import { useRoute, useRouter } from "#imports";
|
|
3
3
|
import { useAAEphemeral } from "./useAAEphemeral.js";
|
|
4
4
|
import { useAwarenessPeers } from "./useAwarenessPeers.js";
|
|
@@ -8,8 +8,11 @@ export function useAAFollowAnchor(leaderId) {
|
|
|
8
8
|
const { peers: allPeers } = useAwarenessPeers();
|
|
9
9
|
const route = useRoute();
|
|
10
10
|
const router = useRouter();
|
|
11
|
+
const scrollState = /* @__PURE__ */ new Map();
|
|
11
12
|
let scrollRaf = 0;
|
|
12
|
-
|
|
13
|
+
const LERP = 0.18;
|
|
14
|
+
const SETTLE_PX = 0.5;
|
|
15
|
+
const MIN_DELTA_PX = 4;
|
|
13
16
|
const leaderPayload = computed(() => {
|
|
14
17
|
const id = leaderId.value;
|
|
15
18
|
if (id == null) return null;
|
|
@@ -23,43 +26,74 @@ export function useAAFollowAnchor(leaderId) {
|
|
|
23
26
|
});
|
|
24
27
|
}
|
|
25
28
|
}, { immediate: true });
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
function ensureRaf() {
|
|
30
|
+
if (scrollRaf) return;
|
|
31
|
+
const tick = () => {
|
|
32
|
+
let stillMoving = false;
|
|
33
|
+
for (const [scroller, s] of scrollState) {
|
|
34
|
+
const delta = s.target - s.current;
|
|
35
|
+
if (Math.abs(delta) < SETTLE_PX) {
|
|
36
|
+
if (scroller === window) window.scrollTo({ top: s.target, behavior: "auto" });
|
|
37
|
+
else scroller.scrollTo({ top: s.target, behavior: "auto" });
|
|
38
|
+
scrollState.delete(scroller);
|
|
39
|
+
continue;
|
|
36
40
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
stillMoving = true;
|
|
42
|
+
s.current += delta * LERP;
|
|
43
|
+
if (scroller === window) window.scrollTo({ top: s.current, behavior: "auto" });
|
|
44
|
+
else scroller.scrollTo({ top: s.current, behavior: "auto" });
|
|
41
45
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (isWindow) window.scrollBy({ top: delta, behavior: "smooth" });
|
|
55
|
-
else scroller.scrollBy({ top: delta, behavior: "smooth" });
|
|
46
|
+
scrollRaf = stillMoving ? requestAnimationFrame(tick) : 0;
|
|
47
|
+
};
|
|
48
|
+
scrollRaf = requestAnimationFrame(tick);
|
|
49
|
+
}
|
|
50
|
+
function scrollToLeader() {
|
|
51
|
+
const payload = leaderPayload.value;
|
|
52
|
+
if (!payload) return;
|
|
53
|
+
if (payload.route !== route.path) return;
|
|
54
|
+
const instructions = [];
|
|
55
|
+
if (payload.scrollers && payload.scrollers.length) {
|
|
56
|
+
for (const s of payload.scrollers) {
|
|
57
|
+
instructions.push({ container: s.containerPath, element: s.elementPath, ratio: s.ratio });
|
|
56
58
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
} else if (payload.kind === "anchor" && payload.anchor) {
|
|
60
|
+
instructions.push({ element: payload.anchor.elementPath, ratio: payload.anchorRatio ?? 0.05 });
|
|
61
|
+
} else if (payload.kind === "selection" && payload.start) {
|
|
62
|
+
instructions.push({ element: payload.start.elementPath, ratio: 0.2 });
|
|
63
|
+
}
|
|
64
|
+
let targetsChanged = false;
|
|
65
|
+
for (const ins of instructions) {
|
|
66
|
+
const target = elementFromPath(ins.element);
|
|
67
|
+
if (!target || !target.isConnected) continue;
|
|
68
|
+
const scroller = ins.container ? elementFromPath(ins.container) ?? window : window;
|
|
69
|
+
const isWindow = scroller === window;
|
|
70
|
+
const scrollerRect = isWindow ? { top: 0, height: window.innerHeight || document.documentElement.clientHeight } : scroller.getBoundingClientRect();
|
|
71
|
+
const desiredTop = scrollerRect.top + scrollerRect.height * Math.max(0, Math.min(0.9, ins.ratio));
|
|
72
|
+
const rect = target.getBoundingClientRect();
|
|
73
|
+
const delta = rect.top - desiredTop;
|
|
74
|
+
if (Math.abs(delta) < MIN_DELTA_PX) continue;
|
|
75
|
+
const currentScroll = isWindow ? window.scrollY : scroller.scrollTop;
|
|
76
|
+
const targetScroll = currentScroll + delta;
|
|
77
|
+
const existing = scrollState.get(scroller);
|
|
78
|
+
if (existing) {
|
|
79
|
+
existing.current = currentScroll;
|
|
80
|
+
if (Math.abs(existing.target - targetScroll) >= 0.5) {
|
|
81
|
+
existing.target = targetScroll;
|
|
82
|
+
targetsChanged = true;
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
scrollState.set(scroller, { current: currentScroll, target: targetScroll });
|
|
86
|
+
targetsChanged = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (targetsChanged) ensureRaf();
|
|
61
90
|
}
|
|
62
91
|
watch(leaderPayload, scrollToLeader, { deep: true, flush: "post" });
|
|
92
|
+
onScopeDispose(() => {
|
|
93
|
+
if (scrollRaf) cancelAnimationFrame(scrollRaf);
|
|
94
|
+
scrollRaf = 0;
|
|
95
|
+
scrollState.clear();
|
|
96
|
+
});
|
|
63
97
|
const leader = computed(() => {
|
|
64
98
|
const id = leaderId.value;
|
|
65
99
|
if (id == null) return null;
|
|
@@ -19,11 +19,14 @@ export interface UseAAFollowPeerOptions {
|
|
|
19
19
|
onBreak?: () => void;
|
|
20
20
|
}
|
|
21
21
|
export declare function useAAFollowPeer(options?: UseAAFollowPeerOptions): {
|
|
22
|
-
follow: (
|
|
22
|
+
follow: (clientIdOrPublicKey: number | string) => void;
|
|
23
23
|
unfollow: () => void;
|
|
24
|
-
followingClientId: import("vue").
|
|
24
|
+
followingClientId: import("vue").ComputedRef<number | null>;
|
|
25
|
+
followingPublicKey: import("vue").ComputedRef<string | null>;
|
|
25
26
|
followingUser: import("vue").ComputedRef<{
|
|
26
|
-
name?: string;
|
|
27
|
-
color?: string;
|
|
27
|
+
name?: string | undefined;
|
|
28
|
+
color?: string | undefined;
|
|
29
|
+
publicKey?: string | undefined;
|
|
28
30
|
} | null>;
|
|
31
|
+
isFollowing: import("vue").ComputedRef<boolean>;
|
|
29
32
|
};
|
|
@@ -2,17 +2,42 @@ import { computed, onScopeDispose, ref, watch } from "vue";
|
|
|
2
2
|
import { useAbracadabra } from "./useAbracadabra.js";
|
|
3
3
|
import { useSyncedMap } from "./useYDoc.js";
|
|
4
4
|
import { useAwareness } from "./useAwareness.js";
|
|
5
|
-
const
|
|
5
|
+
const _followingPublicKey = ref(null);
|
|
6
|
+
const _followingClientIdFallback = ref(null);
|
|
6
7
|
export function useAAFollowPeer(options = {}) {
|
|
7
8
|
const { doc, provider } = useAbracadabra();
|
|
8
9
|
const { data, set } = useSyncedMap(doc, "aware-ui");
|
|
9
10
|
const { states } = useAwareness();
|
|
10
|
-
const followingClientId = _followingClientId;
|
|
11
11
|
let unsubInteraction = null;
|
|
12
|
+
const followingClientId = computed(() => {
|
|
13
|
+
const pk = _followingPublicKey.value;
|
|
14
|
+
if (pk) {
|
|
15
|
+
for (const [cid, st] of states.value.entries()) {
|
|
16
|
+
const peerPk = st?.user?.publicKey;
|
|
17
|
+
if (peerPk === pk) return cid;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return _followingClientIdFallback.value;
|
|
22
|
+
});
|
|
23
|
+
const isFollowing = computed(
|
|
24
|
+
() => _followingPublicKey.value != null || _followingClientIdFallback.value != null
|
|
25
|
+
);
|
|
26
|
+
const followingPublicKey = computed(() => _followingPublicKey.value);
|
|
27
|
+
const followingUserCache = ref(null);
|
|
12
28
|
const followingUser = computed(() => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
const cid = followingClientId.value;
|
|
30
|
+
if (cid != null) {
|
|
31
|
+
const state = states.value.get(cid);
|
|
32
|
+
if (state?.user) return state.user;
|
|
33
|
+
}
|
|
34
|
+
return followingUserCache.value;
|
|
35
|
+
});
|
|
36
|
+
watch(followingUser, (user) => {
|
|
37
|
+
if (user) followingUserCache.value = { ...user };
|
|
38
|
+
}, { flush: "post" });
|
|
39
|
+
watch(isFollowing, (active) => {
|
|
40
|
+
if (!active) followingUserCache.value = null;
|
|
16
41
|
});
|
|
17
42
|
function detachInteraction() {
|
|
18
43
|
unsubInteraction?.();
|
|
@@ -31,14 +56,31 @@ export function useAAFollowPeer(options = {}) {
|
|
|
31
56
|
window.removeEventListener("wheel", onBreak);
|
|
32
57
|
};
|
|
33
58
|
}
|
|
34
|
-
function follow(
|
|
35
|
-
if (
|
|
36
|
-
|
|
59
|
+
function follow(clientIdOrPublicKey) {
|
|
60
|
+
if (typeof clientIdOrPublicKey === "string") {
|
|
61
|
+
if (_followingPublicKey.value === clientIdOrPublicKey) return;
|
|
62
|
+
_followingPublicKey.value = clientIdOrPublicKey;
|
|
63
|
+
_followingClientIdFallback.value = null;
|
|
64
|
+
} else {
|
|
65
|
+
const cid = clientIdOrPublicKey;
|
|
66
|
+
const state = states.value.get(cid);
|
|
67
|
+
const pk = state?.user?.publicKey;
|
|
68
|
+
if (pk) {
|
|
69
|
+
if (_followingPublicKey.value === pk) return;
|
|
70
|
+
_followingPublicKey.value = pk;
|
|
71
|
+
_followingClientIdFallback.value = null;
|
|
72
|
+
} else {
|
|
73
|
+
if (_followingClientIdFallback.value === cid) return;
|
|
74
|
+
_followingPublicKey.value = null;
|
|
75
|
+
_followingClientIdFallback.value = cid;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
37
78
|
attachInteractionBreaker();
|
|
38
79
|
}
|
|
39
80
|
function unfollow() {
|
|
40
|
-
if (
|
|
41
|
-
|
|
81
|
+
if (_followingPublicKey.value == null && _followingClientIdFallback.value == null) return;
|
|
82
|
+
_followingPublicKey.value = null;
|
|
83
|
+
_followingClientIdFallback.value = null;
|
|
42
84
|
detachInteraction();
|
|
43
85
|
options.onBreak?.();
|
|
44
86
|
}
|
|
@@ -71,5 +113,12 @@ export function useAAFollowPeer(options = {}) {
|
|
|
71
113
|
}
|
|
72
114
|
});
|
|
73
115
|
onScopeDispose(detachInteraction);
|
|
74
|
-
return {
|
|
116
|
+
return {
|
|
117
|
+
follow,
|
|
118
|
+
unfollow,
|
|
119
|
+
followingClientId,
|
|
120
|
+
followingPublicKey,
|
|
121
|
+
followingUser,
|
|
122
|
+
isFollowing
|
|
123
|
+
};
|
|
75
124
|
}
|
|
@@ -6,7 +6,7 @@ import type { MaybeRefOrGetter } from 'vue';
|
|
|
6
6
|
* scoped container as `peer:viewport:<scope>` ephemeral state.
|
|
7
7
|
*
|
|
8
8
|
* Use case: render "Janis is reading the API section" overlays in long docs.
|
|
9
|
-
* Pair with `<APresenceCursors>` for a complete
|
|
9
|
+
* Pair with `<APresenceCursors>` for a complete presence layer.
|
|
10
10
|
*/
|
|
11
11
|
export interface PeerViewport {
|
|
12
12
|
clientId: number;
|
|
@@ -24,6 +24,8 @@ export function useAbracadabraAuth() {
|
|
|
24
24
|
confirmPasswordReset: abra.confirmPasswordReset,
|
|
25
25
|
changePassword: abra.changePassword,
|
|
26
26
|
setPassword: abra.setPassword,
|
|
27
|
+
hasPassword: abra.hasPassword,
|
|
28
|
+
refreshHasPassword: abra.refreshHasPassword,
|
|
27
29
|
recoverIdentity: abra.recoverIdentity,
|
|
28
30
|
unblockConnection: abra.unblockConnection,
|
|
29
31
|
setUserName: abra.setUserName,
|
|
@@ -72,7 +72,8 @@ export function useEditorSuggestions(options = {}) {
|
|
|
72
72
|
...extEnabled("colorSwatch") ? [{ kind: "colorSwatch", label: "Color Swatch", icon: "i-lucide-palette", description: "Inline color chip with picker", keywords: ["color", "swatch", "token", "palette"] }] : [],
|
|
73
73
|
...extEnabled("mathBlock") ? [{ kind: "mathBlock", label: "Math (block)", icon: "i-lucide-square-sigma", description: "Display-mode LaTeX equation", keywords: ["katex", "latex", "equation", "formula", "math"] }] : [],
|
|
74
74
|
...extEnabled("mathInline") ? [{ kind: "mathInline", label: "Math (inline)", icon: "i-lucide-sigma", description: "Inline LaTeX expression", keywords: ["katex", "latex", "inline math"] }] : [],
|
|
75
|
-
...extEnabled("diff") ? [{ kind: "diff", label: "Diff", icon: "i-lucide-git-compare", description: "Side-by-side text diff", keywords: ["compare", "changes", "git"] }] : []
|
|
75
|
+
...extEnabled("diff") ? [{ kind: "diff", label: "Diff", icon: "i-lucide-git-compare", description: "Side-by-side text diff", keywords: ["compare", "changes", "git"] }] : [],
|
|
76
|
+
...extEnabled("svgEmbed") ? [{ kind: "svgEmbed", label: "SVG embed", icon: "i-lucide-image", description: "Inline SVG (sanitized)", keywords: ["svg", "vector", "icon", "diagram"] }] : []
|
|
76
77
|
]
|
|
77
78
|
];
|
|
78
79
|
try {
|
|
@@ -1,33 +1,47 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
declare function request(): Promise<void>;
|
|
16
|
-
declare function confirm(token: string): Promise<void>;
|
|
1
|
+
/** Known error codes raised by `useEmailVerification()` actions. */
|
|
2
|
+
export type EmailVerificationErrorCode = 'rate_limited' | 'token_expired' | 'token_invalid' | 'verification_disabled' | 'already_verified' | 'email_not_set' | 'unauthorized' | 'forbidden' | 'network_error' | 'server_error' | 'unknown';
|
|
3
|
+
export interface EmailVerificationError {
|
|
4
|
+
code: EmailVerificationErrorCode;
|
|
5
|
+
message: string;
|
|
6
|
+
status?: number;
|
|
7
|
+
retryAfterSeconds?: number;
|
|
8
|
+
}
|
|
9
|
+
export type EmailVerificationAction = 'request' | 'confirm';
|
|
10
|
+
export interface EmailVerificationResult {
|
|
11
|
+
ok: boolean;
|
|
12
|
+
error?: EmailVerificationError;
|
|
13
|
+
}
|
|
14
|
+
declare function classifyError(err: unknown): EmailVerificationError;
|
|
17
15
|
export declare function useEmailVerification(): {
|
|
18
|
-
/** True after a successful `confirm()` in
|
|
16
|
+
/** True after a successful `confirm()` in this session. */
|
|
19
17
|
verified: import("vue").Ref<boolean, boolean>;
|
|
20
|
-
/** Whether a `request()` is in flight. */
|
|
21
|
-
isRequesting: import("vue").Ref<boolean, boolean>;
|
|
22
|
-
/** Whether a `confirm()` is in flight. */
|
|
23
|
-
isConfirming: import("vue").Ref<boolean, boolean>;
|
|
24
|
-
/** Last error message, or null. */
|
|
25
|
-
error: import("vue").Ref<string | null, string | null>;
|
|
26
18
|
/** Epoch ms of the last successful `request()`, or null. */
|
|
27
19
|
lastSentAt: import("vue").Ref<number | null, number | null>;
|
|
28
|
-
/**
|
|
29
|
-
|
|
20
|
+
/** Currently-running action, or null. */
|
|
21
|
+
busy: import("vue").Ref<EmailVerificationAction | null, EmailVerificationAction | null>;
|
|
22
|
+
/** Most recent typed error, or null. Cleared at the start of every action. */
|
|
23
|
+
error: import("vue").Ref<{
|
|
24
|
+
code: EmailVerificationErrorCode;
|
|
25
|
+
message: string;
|
|
26
|
+
status?: number | undefined;
|
|
27
|
+
retryAfterSeconds?: number | undefined;
|
|
28
|
+
} | null, EmailVerificationError | {
|
|
29
|
+
code: EmailVerificationErrorCode;
|
|
30
|
+
message: string;
|
|
31
|
+
status?: number | undefined;
|
|
32
|
+
retryAfterSeconds?: number | undefined;
|
|
33
|
+
} | null>;
|
|
34
|
+
/** Most recent successful action, or null. */
|
|
35
|
+
lastSuccess: import("vue").Ref<EmailVerificationAction | null, EmailVerificationAction | null>;
|
|
36
|
+
/** Wipe `error` without re-running anything. */
|
|
37
|
+
clearError: () => void;
|
|
38
|
+
/** Send a verification email to the current user. Auth required. */
|
|
39
|
+
request: () => Promise<EmailVerificationResult>;
|
|
30
40
|
/** Confirm a verification token from the email link. No auth required. */
|
|
31
|
-
confirm:
|
|
41
|
+
confirm: (opts: {
|
|
42
|
+
token: string;
|
|
43
|
+
}) => Promise<EmailVerificationResult>;
|
|
44
|
+
/** Internal helper exposed for testing. */
|
|
45
|
+
_classifyError: typeof classifyError;
|
|
32
46
|
};
|
|
33
47
|
export {};
|