@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,113 @@
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
+ sent: { type: Boolean, required: false, default: false },
7
+ error: { type: [String, null], required: false },
8
+ title: { type: String, required: false, default: "Reset your password" },
9
+ subtitle: { type: String, required: false, default: "Enter your username or email and we'll send you a reset link." },
10
+ showSignInLink: { type: Boolean, required: false, default: true }
11
+ });
12
+ const emit = defineEmits(["update:open", "submit", "signin"]);
13
+ const open = computed({
14
+ get: () => !!props.open,
15
+ set: (v) => emit("update:open", v)
16
+ });
17
+ const identifier = ref("");
18
+ watch(() => props.open, (v) => {
19
+ if (!v) return;
20
+ identifier.value = "";
21
+ });
22
+ const canSubmit = computed(
23
+ () => !!identifier.value.trim() && !props.loading && !props.sent
24
+ );
25
+ function submit() {
26
+ if (!canSubmit.value) return;
27
+ emit("submit", { identifier: identifier.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="sent"
41
+ color="success"
42
+ variant="soft"
43
+ icon="i-lucide-mail-check"
44
+ title="Check your inbox"
45
+ description="If an account matches that identifier, we've sent a password reset link. The link expires shortly — use it soon."
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)">Username or email</label>
63
+ <UInput
64
+ v-model="identifier"
65
+ size="md"
66
+ autofocus
67
+ autocomplete="username"
68
+ placeholder="your-handle or you@example.com"
69
+ icon="i-lucide-mail-question"
70
+ @keydown.enter="submit"
71
+ />
72
+ </div>
73
+
74
+ <div
75
+ v-if="showSignInLink"
76
+ class="-mt-1 text-xs"
77
+ >
78
+ <UButton
79
+ variant="link"
80
+ color="neutral"
81
+ size="xs"
82
+ label="Back to sign in"
83
+ @click="emit('signin')"
84
+ />
85
+ </div>
86
+ </template>
87
+ </div>
88
+ </template>
89
+
90
+ <template #footer>
91
+ <div class="flex items-center justify-end gap-2 w-full">
92
+ <UButton
93
+ variant="ghost"
94
+ color="neutral"
95
+ size="sm"
96
+ :label="sent ? 'Close' : 'Cancel'"
97
+ :disabled="loading"
98
+ @click="open = false"
99
+ />
100
+ <UButton
101
+ v-if="!sent"
102
+ color="primary"
103
+ size="sm"
104
+ icon="i-lucide-mail"
105
+ label="Send reset link"
106
+ :loading="loading"
107
+ :disabled="!canSubmit"
108
+ @click="submit"
109
+ />
110
+ </div>
111
+ </template>
112
+ </UModal>
113
+ </template>
@@ -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;
@@ -0,0 +1,26 @@
1
+ type __VLS_Props = {
2
+ loading?: boolean;
3
+ error?: string | null;
4
+ /** Flip to true after a successful set — card shows a success state. */
5
+ success?: boolean;
6
+ title?: string;
7
+ subtitle?: string;
8
+ minLength?: number;
9
+ };
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ submit: (payload: {
12
+ password: string;
13
+ }) => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onSubmit?: ((payload: {
16
+ password: string;
17
+ }) => any) | undefined;
18
+ }>, {
19
+ subtitle: string;
20
+ title: string;
21
+ success: boolean;
22
+ minLength: number;
23
+ loading: boolean;
24
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;
@@ -0,0 +1,139 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ const props = defineProps({
4
+ loading: { type: Boolean, required: false, default: false },
5
+ error: { type: [String, null], required: false },
6
+ success: { type: Boolean, required: false, default: false },
7
+ title: { type: String, required: false, default: "Add a password" },
8
+ subtitle: { type: String, required: false, default: "Your account currently relies on this device's passkey. Adding a password lets you sign in from a second device or recover access if this device is lost." },
9
+ minLength: { type: Number, required: false, default: 8 }
10
+ });
11
+ const emit = defineEmits(["submit"]);
12
+ const password = ref("");
13
+ const confirm = ref("");
14
+ const showPassword = ref(false);
15
+ watch(() => props.success, (v) => {
16
+ if (!v) return;
17
+ password.value = "";
18
+ confirm.value = "";
19
+ showPassword.value = false;
20
+ });
21
+ const passwordTooShort = computed(
22
+ () => password.value.length > 0 && password.value.length < props.minLength
23
+ );
24
+ const confirmMismatch = computed(
25
+ () => confirm.value.length > 0 && confirm.value !== password.value
26
+ );
27
+ const canSubmit = computed(
28
+ () => password.value.length >= props.minLength && confirm.value === password.value && !props.loading && !props.success
29
+ );
30
+ function submit() {
31
+ if (!canSubmit.value) return;
32
+ emit("submit", { password: password.value });
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <div class="set-pw-card">
38
+ <div class="set-pw-head">
39
+ <UIcon
40
+ name="i-lucide-key-square"
41
+ class="size-5 text-(--ui-primary) shrink-0"
42
+ />
43
+ <div class="flex-1">
44
+ <h4 class="set-pw-title">
45
+ {{ title }}
46
+ </h4>
47
+ <p class="set-pw-sub">
48
+ {{ subtitle }}
49
+ </p>
50
+ </div>
51
+ </div>
52
+
53
+ <UAlert
54
+ v-if="success"
55
+ color="success"
56
+ variant="soft"
57
+ icon="i-lucide-check"
58
+ title="Password set"
59
+ description="You can now sign in with your username and password from another device."
60
+ />
61
+
62
+ <UAlert
63
+ v-else-if="error"
64
+ color="error"
65
+ variant="soft"
66
+ icon="i-lucide-triangle-alert"
67
+ :description="error"
68
+ />
69
+
70
+ <template v-if="!success">
71
+ <div class="set-pw-field">
72
+ <label class="set-pw-label">New password</label>
73
+ <UInput
74
+ v-model="password"
75
+ :type="showPassword ? 'text' : 'password'"
76
+ size="md"
77
+ autocomplete="new-password"
78
+ :placeholder="`${minLength}+ characters`"
79
+ icon="i-lucide-lock"
80
+ :ui="{ trailing: 'pe-1' }"
81
+ @keydown.enter="submit"
82
+ >
83
+ <template #trailing>
84
+ <UButton
85
+ tabindex="-1"
86
+ variant="ghost"
87
+ color="neutral"
88
+ size="xs"
89
+ :icon="showPassword ? 'i-lucide-eye-off' : 'i-lucide-eye'"
90
+ :aria-label="showPassword ? 'Hide password' : 'Show password'"
91
+ @click="showPassword = !showPassword"
92
+ />
93
+ </template>
94
+ </UInput>
95
+ <p
96
+ v-if="passwordTooShort"
97
+ class="set-pw-err"
98
+ >
99
+ At least {{ minLength }} characters.
100
+ </p>
101
+ </div>
102
+
103
+ <div class="set-pw-field">
104
+ <label class="set-pw-label">Confirm</label>
105
+ <UInput
106
+ v-model="confirm"
107
+ :type="showPassword ? 'text' : 'password'"
108
+ size="md"
109
+ autocomplete="new-password"
110
+ placeholder="Type it again"
111
+ icon="i-lucide-shield-check"
112
+ @keydown.enter="submit"
113
+ />
114
+ <p
115
+ v-if="confirmMismatch"
116
+ class="set-pw-err"
117
+ >
118
+ Passwords don't match.
119
+ </p>
120
+ </div>
121
+
122
+ <div class="set-pw-actions">
123
+ <UButton
124
+ color="primary"
125
+ size="sm"
126
+ icon="i-lucide-key-round"
127
+ label="Set password"
128
+ :loading="loading"
129
+ :disabled="!canSubmit"
130
+ @click="submit"
131
+ />
132
+ </div>
133
+ </template>
134
+ </div>
135
+ </template>
136
+
137
+ <style scoped>
138
+ .set-pw-card{background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:.6rem;display:flex;flex-direction:column;gap:.75rem;padding:1rem}.set-pw-head{align-items:flex-start;display:flex;gap:.6rem}.set-pw-title{color:var(--ui-text-highlighted);font-size:.875rem;font-weight:600;margin:0}.set-pw-sub{color:var(--ui-text-muted);font-size:.8125rem;line-height:1.5;margin:.2rem 0 0}.set-pw-field{display:flex;flex-direction:column;gap:.25rem}.set-pw-label{color:var(--ui-text-muted);font-size:.7rem;font-weight:500}.set-pw-err{color:var(--ui-color-error-500);font-size:.7rem;margin:0}.set-pw-actions{display:flex;justify-content:flex-end;padding-top:.25rem}
139
+ </style>
@@ -0,0 +1,26 @@
1
+ type __VLS_Props = {
2
+ loading?: boolean;
3
+ error?: string | null;
4
+ /** Flip to true after a successful set — card shows a success state. */
5
+ success?: boolean;
6
+ title?: string;
7
+ subtitle?: string;
8
+ minLength?: number;
9
+ };
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ submit: (payload: {
12
+ password: string;
13
+ }) => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onSubmit?: ((payload: {
16
+ password: string;
17
+ }) => any) | undefined;
18
+ }>, {
19
+ subtitle: string;
20
+ title: string;
21
+ success: boolean;
22
+ minLength: number;
23
+ loading: boolean;
24
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  fieldKey: string;
3
3
  awareness?: boolean;
4
4
  live?: boolean;
5
+ followOnly?: boolean;
5
6
  total?: boolean;
6
7
  };
7
8
  declare var __VLS_9: string, __VLS_10: any, __VLS_27: string, __VLS_28: any;
@@ -13,6 +14,7 @@ type __VLS_Slots = {} & {
13
14
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
14
15
  awareness: boolean;
15
16
  live: boolean;
17
+ followOnly: boolean;
16
18
  total: boolean;
17
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
20
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -2,6 +2,7 @@
2
2
  import { computed, ref, useAttrs, watch } from "vue";
3
3
  import { useAAField } from "../../composables/useAAField";
4
4
  import { useAAUIState } from "../../composables/useAAUIState";
5
+ import { useAAFollowPeer } from "../../composables/useAAFollowPeer";
5
6
  import AHoverItem from "./AHoverItem.vue";
6
7
  function itemId(item) {
7
8
  if (item == null) return "";
@@ -18,10 +19,12 @@ const props = defineProps({
18
19
  fieldKey: { type: String, required: true },
19
20
  awareness: { type: Boolean, required: false, default: true },
20
21
  live: { type: Boolean, required: false, default: false },
22
+ followOnly: { type: Boolean, required: false, default: false },
21
23
  total: { type: Boolean, required: false, default: false }
22
24
  });
25
+ const { isFollowing } = useAAFollowPeer();
23
26
  const enableAwareness = computed(() => props.awareness || props.total);
24
- const enableLive = computed(() => props.live || props.total);
27
+ const enableLive = computed(() => props.live || props.total || props.followOnly && isFollowing.value);
25
28
  const attrs = useAttrs();
26
29
  const { hoverers, focusers, hoverHandlers } = useAAField(() => props.fieldKey);
27
30
  const liveExpanded = useAAUIState(() => `${props.fieldKey}:expanded`, { defaultValue: "" });
@@ -37,6 +40,13 @@ watch(local, (val) => {
37
40
  if (!enableLive.value) return;
38
41
  if (JSON.stringify(liveExpanded.value) !== JSON.stringify(val)) liveExpanded.value = val;
39
42
  });
43
+ watch(enableLive, (now, prev) => {
44
+ if (!now || prev) return;
45
+ const incoming = liveExpanded.value;
46
+ if (incoming != null && JSON.stringify(local.value) !== JSON.stringify(incoming)) {
47
+ local.value = incoming;
48
+ }
49
+ });
40
50
  const ringStyle = computed(() => {
41
51
  if (!enableAwareness.value) return void 0;
42
52
  const focusColor = focusers.value[0]?.user?.color;
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  fieldKey: string;
3
3
  awareness?: boolean;
4
4
  live?: boolean;
5
+ followOnly?: boolean;
5
6
  total?: boolean;
6
7
  };
7
8
  declare var __VLS_9: string, __VLS_10: any, __VLS_27: string, __VLS_28: any;
@@ -13,6 +14,7 @@ type __VLS_Slots = {} & {
13
14
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
14
15
  awareness: boolean;
15
16
  live: boolean;
17
+ followOnly: boolean;
16
18
  total: boolean;
17
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
20
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -7,7 +7,7 @@ const props = defineProps({
7
7
  fieldKey: { type: String, required: true },
8
8
  max: { type: Number, required: false, default: 3 }
9
9
  });
10
- const { hoverers, focusers, pressers, isPressed, handlers } = useAAField(() => props.fieldKey);
10
+ const { hoverers, focusers, pressers, isPressed, localPress, handlers } = useAAField(() => props.fieldKey);
11
11
  const ringStyle = computed(() => awareRingStyle({
12
12
  hover: hoverers.value[0]?.user?.color,
13
13
  focus: focusers.value[0]?.user?.color,
@@ -31,7 +31,7 @@ const overlayPeers = computed(() => {
31
31
  return out;
32
32
  });
33
33
  const pulseKey = ref(0);
34
- watch(isPressed, (val, prev) => {
34
+ watch(localPress, (val, prev) => {
35
35
  if (val && !prev) pulseKey.value++;
36
36
  });
37
37
  const pulseColor = computed(
@@ -72,5 +72,5 @@ const pulseColor = computed(
72
72
  </template>
73
73
 
74
74
  <style scoped>
75
- .aa-host{border-radius:var(--ui-radius,.375rem);position:relative;transition:filter .12s ease,box-shadow .1s ease}.aa-host--inline{display:inline-flex}.aa-host--pressed{filter:brightness(.88)}.aa-press-pulse{animation:aa-press-pulse .26s ease-out forwards;border-radius:inherit;inset:0;pointer-events:none;position:absolute}@keyframes aa-press-pulse{0%{box-shadow:0 0 0 0 var(--aa-pulse-color);opacity:.45}to{box-shadow:0 0 0 12px var(--aa-pulse-color);opacity:0}}.aa-overlay{display:flex;pointer-events:none;position:absolute;right:0;top:-.625rem;z-index:10}.aa-overlay>*+*{margin-left:-.25rem}.aa-peer-enter-active,.aa-peer-leave-active{transition:opacity .15s ease}.aa-peer-enter-from,.aa-peer-leave-to{opacity:0}
75
+ .aa-host{border-radius:var(--ui-radius,.375rem);position:relative;transition:filter var(--aa-state-fade-filter),box-shadow var(--aa-state-fade-shadow)}.aa-host--inline{display:inline-flex}.aa-host--pressed{filter:brightness(.88)}.aa-press-pulse{animation:aa-press-pulse var(--aa-pulse-duration) var(--aa-pulse-easing) forwards;border-radius:inherit;inset:0;pointer-events:none;position:absolute}@keyframes aa-press-pulse{0%{box-shadow:0 0 0 0 var(--aa-pulse-color);opacity:var(--aa-pulse-opacity-start-button)}to{box-shadow:0 0 0 var(--aa-pulse-radius-button) var(--aa-pulse-color);opacity:0}}.aa-overlay{display:flex;pointer-events:none;position:absolute;right:0;top:-.625rem;z-index:10}.aa-overlay>*+*{margin-left:-.25rem}.aa-peer-enter-active,.aa-peer-leave-active{transition:opacity var(--aa-peer-fade-duration) var(--aa-peer-fade-easing)}.aa-peer-enter-from,.aa-peer-leave-to{opacity:0}
76
76
  </style>
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  fieldKey: string;
3
3
  awareness?: boolean;
4
4
  live?: boolean;
5
+ followOnly?: boolean;
5
6
  total?: boolean;
6
7
  };
7
8
  declare var __VLS_10: string, __VLS_11: any, __VLS_22: string, __VLS_23: any;
@@ -13,6 +14,7 @@ type __VLS_Slots = {} & {
13
14
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
14
15
  awareness: boolean;
15
16
  live: boolean;
17
+ followOnly: boolean;
16
18
  total: boolean;
17
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
20
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,14 +1,17 @@
1
1
  <script setup>
2
2
  import { computed, ref, useAttrs, watch } from "vue";
3
3
  import { useAAUIState } from "../../composables/useAAUIState";
4
+ import { useAAFollowPeer } from "../../composables/useAAFollowPeer";
4
5
  defineOptions({ inheritAttrs: false });
5
6
  const props = defineProps({
6
7
  fieldKey: { type: String, required: true },
7
8
  awareness: { type: Boolean, required: false, default: true },
8
9
  live: { type: Boolean, required: false, default: false },
10
+ followOnly: { type: Boolean, required: false, default: false },
9
11
  total: { type: Boolean, required: false, default: false }
10
12
  });
11
- const enableLive = computed(() => props.live || props.total);
13
+ const { isFollowing } = useAAFollowPeer();
14
+ const enableLive = computed(() => props.live || props.total || props.followOnly && isFollowing.value);
12
15
  const attrs = useAttrs();
13
16
  const liveOpen = useAAUIState(() => `${props.fieldKey}:open`, { defaultValue: false });
14
17
  const hasExternalOpen = computed(() => "open" in attrs || "onUpdate:open" in attrs);
@@ -22,6 +25,11 @@ watch(local, (val) => {
22
25
  if (!enableLive.value) return;
23
26
  if (!!liveOpen.value !== val) liveOpen.value = val;
24
27
  });
28
+ watch(enableLive, (now, prev) => {
29
+ if (!now || prev) return;
30
+ const incoming = !!liveOpen.value;
31
+ if (local.value !== incoming) local.value = incoming;
32
+ });
25
33
  </script>
26
34
 
27
35
  <template>
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  fieldKey: string;
3
3
  awareness?: boolean;
4
4
  live?: boolean;
5
+ followOnly?: boolean;
5
6
  total?: boolean;
6
7
  };
7
8
  declare var __VLS_10: string, __VLS_11: any, __VLS_22: string, __VLS_23: any;
@@ -13,6 +14,7 @@ type __VLS_Slots = {} & {
13
14
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
14
15
  awareness: boolean;
15
16
  live: boolean;
17
+ followOnly: boolean;
16
18
  total: boolean;
17
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
20
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -73,7 +73,7 @@ function nameFor(p) {
73
73
  }"
74
74
  />
75
75
  <span
76
- v-if="p.rects.length"
76
+ v-if="p.rects[0]"
77
77
  class="aa-global-focus-layer__flag"
78
78
  :style="{
79
79
  top: p.rects[0].top + 'px',
@@ -8,7 +8,7 @@ const props = defineProps({
8
8
  showFlag: { type: Boolean, required: false, default: true },
9
9
  tinted: { type: Boolean, required: false, default: true }
10
10
  });
11
- const { hoverers, focusers, pressers, isPressed, onMouseenter, onMouseleave, onMousedown, onMouseup } = useAAField(() => props.fieldKey);
11
+ const { hoverers, focusers, pressers, localPress, onMouseenter, onMouseleave, onMousedown, onMouseup } = useAAField(() => props.fieldKey);
12
12
  const wrapperRef = ref(null);
13
13
  const rowEl = ref(null);
14
14
  const ROW_SELECTOR = [
@@ -23,6 +23,20 @@ const ROW_SELECTOR = [
23
23
  ".aa-row-target"
24
24
  ].join(", ");
25
25
  let savedStyle = { background: "", boxShadow: "", position: "" };
26
+ let kbHighlighted = false;
27
+ let kbObserver = null;
28
+ function isKeyboardHighlighted(row) {
29
+ return row.hasAttribute("data-highlighted") || row.getAttribute("data-state") === "checked" || row.getAttribute("aria-selected") === "true";
30
+ }
31
+ function syncKeyboardHighlight() {
32
+ const row = rowEl.value;
33
+ if (!row) return;
34
+ const next = isKeyboardHighlighted(row);
35
+ if (next === kbHighlighted) return;
36
+ kbHighlighted = next;
37
+ if (next) onMouseenter();
38
+ else onMouseleave();
39
+ }
26
40
  function attachToRow() {
27
41
  const wrapper = wrapperRef.value;
28
42
  if (!wrapper) return;
@@ -39,6 +53,13 @@ function attachToRow() {
39
53
  row.addEventListener("mouseleave", onMouseleave);
40
54
  row.addEventListener("mousedown", onMousedown);
41
55
  row.addEventListener("mouseup", onMouseup);
56
+ kbObserver?.disconnect();
57
+ kbObserver = new MutationObserver(syncKeyboardHighlight);
58
+ kbObserver.observe(row, {
59
+ attributes: true,
60
+ attributeFilter: ["data-highlighted", "data-state", "aria-selected"]
61
+ });
62
+ syncKeyboardHighlight();
42
63
  }
43
64
  function detachFromRow() {
44
65
  const row = rowEl.value;
@@ -49,6 +70,10 @@ function detachFromRow() {
49
70
  row.removeEventListener("mouseup", onMouseup);
50
71
  row.style.backgroundColor = savedStyle.background;
51
72
  row.style.boxShadow = savedStyle.boxShadow;
73
+ if (kbHighlighted) onMouseleave();
74
+ kbHighlighted = false;
75
+ kbObserver?.disconnect();
76
+ kbObserver = null;
52
77
  rowEl.value = null;
53
78
  }
54
79
  onMounted(attachToRow);
@@ -90,7 +115,7 @@ const flagPeer = computed(
90
115
  () => pressers.value[0] ?? focusers.value[0] ?? hoverers.value[0]
91
116
  );
92
117
  const pulseKey = ref(0);
93
- watch(isPressed, (val, prev) => {
118
+ watch(localPress, (val, prev) => {
94
119
  if (val && !prev) pulseKey.value++;
95
120
  });
96
121
  const pulseColor = computed(() => pressers.value[0]?.user?.color ?? "currentColor");
@@ -120,5 +145,5 @@ const pulseColor = computed(() => pressers.value[0]?.user?.color ?? "currentColo
120
145
  </template>
121
146
 
122
147
  <style scoped>
123
- .aa-item{border-radius:inherit;display:contents;position:relative}.aa-item--inline{align-items:center;display:inline-flex}.aa-item__pulse{animation:aa-item-pulse .35s ease-out forwards;border-radius:inherit;inset:0;pointer-events:none;position:absolute}@keyframes aa-item-pulse{0%{box-shadow:0 0 0 0 var(--aa-pulse-color);opacity:.5}to{box-shadow:0 0 0 14px var(--aa-pulse-color);opacity:0}}.aa-item__flag{border-radius:.25rem .25rem .25rem 0;box-shadow:0 1px 2px rgba(0,0,0,.18);color:#fff;font-size:.55rem;font-weight:500;line-height:1;padding:.18rem .35rem;pointer-events:none;position:absolute;right:.25rem;top:-.55rem;white-space:nowrap;z-index:5}.aa-flag-enter-active,.aa-flag-leave-active{transition:opacity .12s ease,transform .12s ease}.aa-flag-enter-from,.aa-flag-leave-to{opacity:0;transform:translateY(2px)}
148
+ .aa-item{border-radius:inherit;display:contents;position:relative}.aa-item--inline{align-items:center;display:inline-flex}.aa-item__pulse{animation:aa-item-pulse var(--aa-pulse-duration) var(--aa-pulse-easing) forwards;border-radius:inherit;inset:0;pointer-events:none;position:absolute}@keyframes aa-item-pulse{0%{box-shadow:0 0 0 0 var(--aa-pulse-color);opacity:var(--aa-pulse-opacity-start-item)}to{box-shadow:0 0 0 var(--aa-pulse-radius-item) var(--aa-pulse-color);opacity:0}}.aa-item__flag{border-radius:.25rem .25rem .25rem 0;box-shadow:0 1px 2px rgba(0,0,0,.18);color:#fff;font-size:.55rem;font-weight:500;line-height:1;padding:.18rem .35rem;pointer-events:none;position:absolute;right:.25rem;top:-.55rem;white-space:nowrap;z-index:5}.aa-flag-enter-active,.aa-flag-leave-active{transition:opacity var(--aa-flag-fade-duration) var(--aa-flag-fade-easing),transform var(--aa-flag-fade-duration) var(--aa-flag-fade-easing)}.aa-flag-enter-from,.aa-flag-leave-to{opacity:0;transform:translateY(2px)}
124
149
  </style>
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  fieldKey: string;
3
3
  awareness?: boolean;
4
4
  live?: boolean;
5
+ followOnly?: boolean;
5
6
  total?: boolean;
6
7
  };
7
8
  declare var __VLS_8: {}, __VLS_11: {}, __VLS_14: {}, __VLS_17: {}, __VLS_20: {}, __VLS_31: string, __VLS_32: any;
@@ -21,6 +22,7 @@ type __VLS_Slots = {} & {
21
22
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
22
23
  awareness: boolean;
23
24
  live: boolean;
25
+ followOnly: boolean;
24
26
  total: boolean;
25
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
28
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,15 +1,18 @@
1
1
  <script setup>
2
2
  import { computed, ref, useAttrs, watch } from "vue";
3
3
  import { useAAUIState, useAAUIStateAuthor } from "../../composables/useAAUIState";
4
+ import { useAAFollowPeer } from "../../composables/useAAFollowPeer";
4
5
  import { useAwareness } from "../../composables/useAwareness";
5
6
  defineOptions({ inheritAttrs: false });
6
7
  const props = defineProps({
7
8
  fieldKey: { type: String, required: true },
8
9
  awareness: { type: Boolean, required: false, default: true },
9
10
  live: { type: Boolean, required: false, default: false },
11
+ followOnly: { type: Boolean, required: false, default: false },
10
12
  total: { type: Boolean, required: false, default: false }
11
13
  });
12
- const enableLive = computed(() => props.live || props.total);
14
+ const { isFollowing } = useAAFollowPeer();
15
+ const enableLive = computed(() => props.live || props.total || props.followOnly && isFollowing.value);
13
16
  const attrs = useAttrs();
14
17
  const liveOpen = useAAUIState(() => `${props.fieldKey}:open`, { defaultValue: false });
15
18
  const author = useAAUIStateAuthor(() => `${props.fieldKey}:open`);
@@ -25,6 +28,11 @@ watch(local, (val) => {
25
28
  if (!enableLive.value) return;
26
29
  if (!!liveOpen.value !== val) liveOpen.value = val;
27
30
  });
31
+ watch(enableLive, (now, prev) => {
32
+ if (!now || prev) return;
33
+ const incoming = !!liveOpen.value;
34
+ if (local.value !== incoming) local.value = incoming;
35
+ });
28
36
  const openedByUser = computed(() => {
29
37
  if (!enableLive.value || !local.value || author.value == null) return null;
30
38
  const state = states.value.get(author.value);
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  fieldKey: string;
3
3
  awareness?: boolean;
4
4
  live?: boolean;
5
+ followOnly?: boolean;
5
6
  total?: boolean;
6
7
  };
7
8
  declare var __VLS_8: {}, __VLS_11: {}, __VLS_14: {}, __VLS_17: {}, __VLS_20: {}, __VLS_31: string, __VLS_32: any;
@@ -21,6 +22,7 @@ type __VLS_Slots = {} & {
21
22
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
22
23
  awareness: boolean;
23
24
  live: boolean;
25
+ followOnly: boolean;
24
26
  total: boolean;
25
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
28
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -65,5 +65,5 @@ onBeforeUnmount(() => {
65
65
  </template>
66
66
 
67
67
  <style scoped>
68
- .aa-presence-blobs{inset:0;isolation:isolate;mix-blend-mode:screen;pointer-events:none;position:fixed;z-index:0}.aa-presence-blobs__blob{border-radius:999px;filter:blur(60px);height:360px;opacity:.35;pointer-events:none;position:fixed;transform:translate(-50%,-50%);transition:left .2s ease-out,top .2s ease-out;width:360px}@media (prefers-color-scheme:light){.aa-presence-blobs{mix-blend-mode:multiply}.aa-presence-blobs__blob{opacity:.22}}
68
+ .aa-presence-blobs{inset:0;isolation:isolate;mix-blend-mode:screen;pointer-events:none;position:fixed;z-index:0}.aa-presence-blobs__blob{border-radius:999px;filter:blur(60px);height:360px;opacity:.35;pointer-events:none;position:fixed;transform:translate(-50%,-50%);transition:left var(--aa-track-blob-duration) var(--aa-track-blob-easing),top var(--aa-track-blob-duration) var(--aa-track-blob-easing);width:360px}@media (prefers-color-scheme:light){.aa-presence-blobs{mix-blend-mode:multiply}.aa-presence-blobs__blob{opacity:.22}}
69
69
  </style>