@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,65 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ const props = defineProps({
4
+ loading: { type: Boolean, required: false, default: false },
5
+ sent: { type: Boolean, required: false, default: false },
6
+ error: { type: [String, null], required: false },
7
+ email: { type: [String, null], required: false },
8
+ title: { type: String, required: false, default: "Verify your email" },
9
+ subtitle: { type: String, required: false, default: "Confirming your email address lets you reset your password and receive notifications." }
10
+ });
11
+ const emit = defineEmits(["request"]);
12
+ const showSentCopy = computed(() => props.sent && !props.loading && !props.error);
13
+ </script>
14
+
15
+ <template>
16
+ <div class="ev-card">
17
+ <div class="ev-head">
18
+ <UIcon
19
+ name="i-lucide-mail-check"
20
+ class="size-5 text-(--ui-primary) shrink-0"
21
+ />
22
+ <div class="flex-1">
23
+ <h4 class="ev-title">
24
+ {{ title }}
25
+ </h4>
26
+ <p class="ev-sub">
27
+ {{ subtitle }}
28
+ </p>
29
+ </div>
30
+ </div>
31
+
32
+ <UAlert
33
+ v-if="showSentCopy"
34
+ color="success"
35
+ variant="soft"
36
+ icon="i-lucide-mail-check"
37
+ title="Verification email sent"
38
+ :description="email ? `We sent a link to ${email}. The link expires shortly \u2014 use it soon.` : 'We sent a verification link to your registered email. The link expires shortly \u2014 use it soon.'"
39
+ />
40
+
41
+ <UAlert
42
+ v-else-if="error"
43
+ color="error"
44
+ variant="soft"
45
+ icon="i-lucide-triangle-alert"
46
+ :description="error"
47
+ />
48
+
49
+ <div class="ev-actions">
50
+ <UButton
51
+ color="primary"
52
+ size="sm"
53
+ icon="i-lucide-send"
54
+ :label="sent ? 'Resend verification email' : 'Send verification email'"
55
+ :loading="loading"
56
+ :disabled="loading"
57
+ @click="emit('request')"
58
+ />
59
+ </div>
60
+ </div>
61
+ </template>
62
+
63
+ <style scoped>
64
+ .ev-card{background:var(--ui-bg);border:1px solid var(--ui-border);border-radius:.6rem;display:flex;flex-direction:column;gap:.75rem;padding:1rem}.ev-head{align-items:flex-start;display:flex;gap:.6rem}.ev-title{color:var(--ui-text-highlighted);font-size:.875rem;font-weight:600;margin:0}.ev-sub{color:var(--ui-text-muted);font-size:.8125rem;line-height:1.5;margin:.2rem 0 0}.ev-actions{display:flex;justify-content:flex-end;padding-top:.25rem}
65
+ </style>
@@ -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;
@@ -28,8 +28,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
28
28
  }>, {
29
29
  subtitle: string;
30
30
  title: string;
31
- wordCount: 12 | 24;
32
31
  loading: boolean;
32
+ wordCount: 12 | 24;
33
33
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
34
  declare const _default: typeof __VLS_export;
35
35
  export default _default;
@@ -28,8 +28,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
28
28
  }>, {
29
29
  subtitle: string;
30
30
  title: string;
31
- wordCount: 12 | 24;
32
31
  loading: boolean;
32
+ wordCount: 12 | 24;
33
33
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
34
  declare const _default: typeof __VLS_export;
35
35
  export default _default;
@@ -359,6 +359,7 @@ const addFieldMenuItems = computed(
359
359
  <div class="space-y-1">
360
360
  <label class="text-xs font-medium text-muted">{{ locale.color }}</label>
361
361
  <AColorPicker
362
+ :field-key="`node-panel:meta:color:${props.nodeId}`"
362
363
  :model-value="meta.color"
363
364
  @update:model-value="patchMeta({ color: $event })"
364
365
  />
@@ -669,6 +670,7 @@ const addFieldMenuItems = computed(
669
670
  <!-- Color Preset / Color Picker -->
670
671
  <template v-else-if="['colorPreset', 'colorPicker'].includes(field.type)">
671
672
  <AColorPicker
673
+ :field-key="`node-panel:custom:${props.nodeId}:${field.key}`"
672
674
  :model-value="String(getCustomFieldValue(field) ?? '')"
673
675
  @update:model-value="setCustomFieldValue(field, $event)"
674
676
  />
@@ -3,7 +3,7 @@ type __VLS_Props = {
3
3
  count?: number;
4
4
  /** Tooltip text. Default: 'Notifications'. */
5
5
  tooltip?: string;
6
- size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg';
6
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
7
7
  variant?: 'ghost' | 'soft' | 'outline' | 'solid' | 'subtle' | 'link';
8
8
  color?: 'neutral' | 'primary' | 'secondary' | 'error' | 'warning' | 'success' | 'info';
9
9
  icon?: string;
@@ -17,7 +17,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
17
17
  }>, {
18
18
  color: "neutral" | "primary" | "secondary" | "error" | "warning" | "success" | "info";
19
19
  icon: string;
20
- size: "2xs" | "xs" | "sm" | "md" | "lg";
20
+ size: "xs" | "sm" | "md" | "lg" | "xl";
21
21
  variant: "ghost" | "soft" | "outline" | "solid" | "subtle" | "link";
22
22
  tooltip: string;
23
23
  chipColor: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
@@ -3,7 +3,7 @@ type __VLS_Props = {
3
3
  count?: number;
4
4
  /** Tooltip text. Default: 'Notifications'. */
5
5
  tooltip?: string;
6
- size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg';
6
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
7
7
  variant?: 'ghost' | 'soft' | 'outline' | 'solid' | 'subtle' | 'link';
8
8
  color?: 'neutral' | 'primary' | 'secondary' | 'error' | 'warning' | 'success' | 'info';
9
9
  icon?: string;
@@ -17,7 +17,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
17
17
  }>, {
18
18
  color: "neutral" | "primary" | "secondary" | "error" | "warning" | "success" | "info";
19
19
  icon: string;
20
- size: "2xs" | "xs" | "sm" | "md" | "lg";
20
+ size: "xs" | "sm" | "md" | "lg" | "xl";
21
21
  variant: "ghost" | "soft" | "outline" | "solid" | "subtle" | "link";
22
22
  tooltip: string;
23
23
  chipColor: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
@@ -0,0 +1,28 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ error?: string | null;
5
+ title?: string;
6
+ subtitle?: string;
7
+ minLength?: number;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ submit: (payload: {
11
+ currentPassword: string;
12
+ newPassword: string;
13
+ }) => any;
14
+ "update:open": (v: boolean) => any;
15
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
+ onSubmit?: ((payload: {
17
+ currentPassword: string;
18
+ newPassword: string;
19
+ }) => any) | undefined;
20
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
21
+ }>, {
22
+ subtitle: string;
23
+ title: string;
24
+ minLength: number;
25
+ loading: boolean;
26
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ declare const _default: typeof __VLS_export;
28
+ export default _default;
@@ -0,0 +1,178 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ const props = defineProps({
4
+ open: { type: Boolean, required: false },
5
+ loading: { type: Boolean, required: false, default: false },
6
+ error: { type: [String, null], required: false },
7
+ title: { type: String, required: false, default: "Change password" },
8
+ subtitle: { type: String, required: false, default: "Enter your current password, then choose a new one." },
9
+ minLength: { type: Number, required: false, default: 8 }
10
+ });
11
+ const emit = defineEmits(["update:open", "submit"]);
12
+ const open = computed({
13
+ get: () => !!props.open,
14
+ set: (v) => emit("update:open", v)
15
+ });
16
+ const currentPassword = ref("");
17
+ const newPassword = ref("");
18
+ const confirm = ref("");
19
+ const showCurrent = ref(false);
20
+ const showNew = ref(false);
21
+ watch(() => props.open, (v) => {
22
+ if (!v) return;
23
+ currentPassword.value = "";
24
+ newPassword.value = "";
25
+ confirm.value = "";
26
+ showCurrent.value = false;
27
+ showNew.value = false;
28
+ });
29
+ const passwordTooShort = computed(
30
+ () => newPassword.value.length > 0 && newPassword.value.length < props.minLength
31
+ );
32
+ const sameAsCurrent = computed(
33
+ () => newPassword.value.length > 0 && currentPassword.value.length > 0 && newPassword.value === currentPassword.value
34
+ );
35
+ const confirmMismatch = computed(
36
+ () => confirm.value.length > 0 && confirm.value !== newPassword.value
37
+ );
38
+ const canSubmit = computed(
39
+ () => !!currentPassword.value && newPassword.value.length >= props.minLength && confirm.value === newPassword.value && !sameAsCurrent.value && !props.loading
40
+ );
41
+ function submit() {
42
+ if (!canSubmit.value) return;
43
+ emit("submit", {
44
+ currentPassword: currentPassword.value,
45
+ newPassword: newPassword.value
46
+ });
47
+ }
48
+ </script>
49
+
50
+ <template>
51
+ <UModal
52
+ v-model:open="open"
53
+ :title="title"
54
+ :ui="{ content: 'sm:max-w-md' }"
55
+ >
56
+ <template #body>
57
+ <div class="flex flex-col gap-4">
58
+ <p class="text-sm text-(--ui-text-muted)">
59
+ {{ subtitle }}
60
+ </p>
61
+
62
+ <UAlert
63
+ v-if="error"
64
+ color="error"
65
+ variant="soft"
66
+ icon="i-lucide-triangle-alert"
67
+ :description="error"
68
+ />
69
+
70
+ <div class="flex flex-col gap-1">
71
+ <label class="text-xs font-medium text-(--ui-text-muted)">Current password</label>
72
+ <UInput
73
+ v-model="currentPassword"
74
+ :type="showCurrent ? 'text' : 'password'"
75
+ size="md"
76
+ autofocus
77
+ autocomplete="current-password"
78
+ placeholder="••••••••"
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="showCurrent ? 'i-lucide-eye-off' : 'i-lucide-eye'"
90
+ :aria-label="showCurrent ? 'Hide password' : 'Show password'"
91
+ @click="showCurrent = !showCurrent"
92
+ />
93
+ </template>
94
+ </UInput>
95
+ </div>
96
+
97
+ <div class="flex flex-col gap-1">
98
+ <label class="text-xs font-medium text-(--ui-text-muted)">New password</label>
99
+ <UInput
100
+ v-model="newPassword"
101
+ :type="showNew ? 'text' : 'password'"
102
+ size="md"
103
+ autocomplete="new-password"
104
+ :placeholder="`${minLength}+ characters`"
105
+ icon="i-lucide-key-round"
106
+ :ui="{ trailing: 'pe-1' }"
107
+ @keydown.enter="submit"
108
+ >
109
+ <template #trailing>
110
+ <UButton
111
+ tabindex="-1"
112
+ variant="ghost"
113
+ color="neutral"
114
+ size="xs"
115
+ :icon="showNew ? 'i-lucide-eye-off' : 'i-lucide-eye'"
116
+ :aria-label="showNew ? 'Hide password' : 'Show password'"
117
+ @click="showNew = !showNew"
118
+ />
119
+ </template>
120
+ </UInput>
121
+ <p
122
+ v-if="passwordTooShort"
123
+ class="text-xs text-(--ui-color-error-500)"
124
+ >
125
+ At least {{ minLength }} characters.
126
+ </p>
127
+ <p
128
+ v-if="sameAsCurrent"
129
+ class="text-xs text-(--ui-color-warning-500)"
130
+ >
131
+ New password matches the current one — pick a different one.
132
+ </p>
133
+ </div>
134
+
135
+ <div class="flex flex-col gap-1">
136
+ <label class="text-xs font-medium text-(--ui-text-muted)">Confirm new password</label>
137
+ <UInput
138
+ v-model="confirm"
139
+ :type="showNew ? 'text' : 'password'"
140
+ size="md"
141
+ autocomplete="new-password"
142
+ placeholder="Type it again"
143
+ icon="i-lucide-shield-check"
144
+ @keydown.enter="submit"
145
+ />
146
+ <p
147
+ v-if="confirmMismatch"
148
+ class="text-xs text-(--ui-color-error-500)"
149
+ >
150
+ Passwords don't match.
151
+ </p>
152
+ </div>
153
+ </div>
154
+ </template>
155
+
156
+ <template #footer>
157
+ <div class="flex items-center justify-end gap-2 w-full">
158
+ <UButton
159
+ variant="ghost"
160
+ color="neutral"
161
+ size="sm"
162
+ label="Cancel"
163
+ :disabled="loading"
164
+ @click="open = false"
165
+ />
166
+ <UButton
167
+ color="primary"
168
+ size="sm"
169
+ icon="i-lucide-key-round"
170
+ label="Update password"
171
+ :loading="loading"
172
+ :disabled="!canSubmit"
173
+ @click="submit"
174
+ />
175
+ </div>
176
+ </template>
177
+ </UModal>
178
+ </template>
@@ -0,0 +1,28 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ error?: string | null;
5
+ title?: string;
6
+ subtitle?: string;
7
+ minLength?: number;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ submit: (payload: {
11
+ currentPassword: string;
12
+ newPassword: string;
13
+ }) => any;
14
+ "update:open": (v: boolean) => any;
15
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
+ onSubmit?: ((payload: {
17
+ currentPassword: string;
18
+ newPassword: string;
19
+ }) => any) | undefined;
20
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
21
+ }>, {
22
+ subtitle: string;
23
+ title: string;
24
+ minLength: number;
25
+ loading: boolean;
26
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ declare const _default: typeof __VLS_export;
28
+ export default _default;
@@ -0,0 +1,42 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ /** Server / client error to display inline. */
5
+ error?: string | null;
6
+ title?: string;
7
+ subtitle?: string;
8
+ /** Show the "Don't have an account? Register" link. */
9
+ showRegisterLink?: boolean;
10
+ /** Show the "Forgot password?" link. */
11
+ showForgotLink?: boolean;
12
+ /** Show the optional invite-code field under Advanced. */
13
+ showInviteCode?: boolean;
14
+ };
15
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
16
+ submit: (payload: {
17
+ username: string;
18
+ password: string;
19
+ inviteCode?: string;
20
+ }) => any;
21
+ "update:open": (v: boolean) => any;
22
+ register: () => any;
23
+ forgot: () => any;
24
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
25
+ onSubmit?: ((payload: {
26
+ username: string;
27
+ password: string;
28
+ inviteCode?: string;
29
+ }) => any) | undefined;
30
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
31
+ onRegister?: (() => any) | undefined;
32
+ onForgot?: (() => any) | undefined;
33
+ }>, {
34
+ subtitle: string;
35
+ title: string;
36
+ loading: boolean;
37
+ showRegisterLink: boolean;
38
+ showForgotLink: boolean;
39
+ showInviteCode: boolean;
40
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: typeof __VLS_export;
42
+ export default _default;
@@ -0,0 +1,177 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ const props = defineProps({
4
+ open: { type: Boolean, required: false },
5
+ loading: { type: Boolean, required: false, default: false },
6
+ error: { type: [String, null], required: false },
7
+ title: { type: String, required: false, default: "Sign in" },
8
+ subtitle: { type: String, required: false, default: "Enter your username and password." },
9
+ showRegisterLink: { type: Boolean, required: false, default: true },
10
+ showForgotLink: { type: Boolean, required: false, default: true },
11
+ showInviteCode: { type: Boolean, required: false, default: false }
12
+ });
13
+ const emit = defineEmits(["update:open", "submit", "forgot", "register"]);
14
+ const open = computed({
15
+ get: () => !!props.open,
16
+ set: (v) => emit("update:open", v)
17
+ });
18
+ const username = ref("");
19
+ const password = ref("");
20
+ const inviteCode = ref("");
21
+ const showPassword = ref(false);
22
+ const showAdvanced = ref(false);
23
+ watch(() => props.open, (v) => {
24
+ if (!v) return;
25
+ username.value = "";
26
+ password.value = "";
27
+ inviteCode.value = "";
28
+ showPassword.value = false;
29
+ showAdvanced.value = props.showInviteCode;
30
+ });
31
+ const canSubmit = computed(
32
+ () => !!username.value.trim() && !!password.value && !props.loading
33
+ );
34
+ function submit() {
35
+ if (!canSubmit.value) return;
36
+ emit("submit", {
37
+ username: username.value.trim(),
38
+ password: password.value,
39
+ inviteCode: inviteCode.value.trim() || void 0
40
+ });
41
+ }
42
+ </script>
43
+
44
+ <template>
45
+ <UModal
46
+ v-model:open="open"
47
+ :title="title"
48
+ :ui="{ content: 'sm:max-w-md' }"
49
+ >
50
+ <template #body>
51
+ <div class="flex flex-col gap-4">
52
+ <p class="text-sm text-(--ui-text-muted)">
53
+ {{ subtitle }}
54
+ </p>
55
+
56
+ <UAlert
57
+ v-if="error"
58
+ color="error"
59
+ variant="soft"
60
+ icon="i-lucide-triangle-alert"
61
+ :description="error"
62
+ />
63
+
64
+ <div class="flex flex-col gap-1">
65
+ <label class="text-xs font-medium text-(--ui-text-muted)">Username</label>
66
+ <UInput
67
+ v-model="username"
68
+ size="md"
69
+ autofocus
70
+ autocomplete="username"
71
+ placeholder="your-handle"
72
+ icon="i-lucide-at-sign"
73
+ @keydown.enter="submit"
74
+ />
75
+ </div>
76
+
77
+ <div class="flex flex-col gap-1">
78
+ <label class="text-xs font-medium text-(--ui-text-muted)">Password</label>
79
+ <UInput
80
+ v-model="password"
81
+ :type="showPassword ? 'text' : 'password'"
82
+ size="md"
83
+ autocomplete="current-password"
84
+ placeholder="••••••••"
85
+ icon="i-lucide-lock"
86
+ :ui="{ trailing: 'pe-1' }"
87
+ @keydown.enter="submit"
88
+ >
89
+ <template #trailing>
90
+ <UButton
91
+ tabindex="-1"
92
+ variant="ghost"
93
+ color="neutral"
94
+ size="xs"
95
+ :icon="showPassword ? 'i-lucide-eye-off' : 'i-lucide-eye'"
96
+ :aria-label="showPassword ? 'Hide password' : 'Show password'"
97
+ @click="showPassword = !showPassword"
98
+ />
99
+ </template>
100
+ </UInput>
101
+ </div>
102
+
103
+ <div
104
+ v-if="showInviteCode"
105
+ class="flex items-center justify-between text-xs"
106
+ >
107
+ <UButton
108
+ variant="ghost"
109
+ color="neutral"
110
+ size="xs"
111
+ :icon="showAdvanced ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
112
+ :label="showAdvanced ? 'Hide advanced' : 'Advanced'"
113
+ @click="showAdvanced = !showAdvanced"
114
+ />
115
+ </div>
116
+
117
+ <div
118
+ v-if="showInviteCode && showAdvanced"
119
+ class="flex flex-col gap-1"
120
+ >
121
+ <label class="text-xs font-medium text-(--ui-text-muted)">Invite code (optional)</label>
122
+ <UInput
123
+ v-model="inviteCode"
124
+ size="sm"
125
+ placeholder="paste invite code"
126
+ icon="i-lucide-ticket"
127
+ @keydown.enter="submit"
128
+ />
129
+ </div>
130
+
131
+ <div
132
+ v-if="showForgotLink || showRegisterLink"
133
+ class="flex items-center justify-between gap-2 -mt-1 text-xs"
134
+ >
135
+ <UButton
136
+ v-if="showForgotLink"
137
+ variant="link"
138
+ color="neutral"
139
+ size="xs"
140
+ label="Forgot password?"
141
+ @click="emit('forgot')"
142
+ />
143
+ <UButton
144
+ v-if="showRegisterLink"
145
+ variant="link"
146
+ color="primary"
147
+ size="xs"
148
+ label="Create an account"
149
+ @click="emit('register')"
150
+ />
151
+ </div>
152
+ </div>
153
+ </template>
154
+
155
+ <template #footer>
156
+ <div class="flex items-center justify-end gap-2 w-full">
157
+ <UButton
158
+ variant="ghost"
159
+ color="neutral"
160
+ size="sm"
161
+ label="Cancel"
162
+ :disabled="loading"
163
+ @click="open = false"
164
+ />
165
+ <UButton
166
+ color="primary"
167
+ size="sm"
168
+ icon="i-lucide-log-in"
169
+ label="Sign in"
170
+ :loading="loading"
171
+ :disabled="!canSubmit"
172
+ @click="submit"
173
+ />
174
+ </div>
175
+ </template>
176
+ </UModal>
177
+ </template>
@@ -0,0 +1,42 @@
1
+ type __VLS_Props = {
2
+ open?: boolean;
3
+ loading?: boolean;
4
+ /** Server / client error to display inline. */
5
+ error?: string | null;
6
+ title?: string;
7
+ subtitle?: string;
8
+ /** Show the "Don't have an account? Register" link. */
9
+ showRegisterLink?: boolean;
10
+ /** Show the "Forgot password?" link. */
11
+ showForgotLink?: boolean;
12
+ /** Show the optional invite-code field under Advanced. */
13
+ showInviteCode?: boolean;
14
+ };
15
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
16
+ submit: (payload: {
17
+ username: string;
18
+ password: string;
19
+ inviteCode?: string;
20
+ }) => any;
21
+ "update:open": (v: boolean) => any;
22
+ register: () => any;
23
+ forgot: () => any;
24
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
25
+ onSubmit?: ((payload: {
26
+ username: string;
27
+ password: string;
28
+ inviteCode?: string;
29
+ }) => any) | undefined;
30
+ "onUpdate:open"?: ((v: boolean) => any) | undefined;
31
+ onRegister?: (() => any) | undefined;
32
+ onForgot?: (() => any) | undefined;
33
+ }>, {
34
+ subtitle: string;
35
+ title: string;
36
+ loading: boolean;
37
+ showRegisterLink: boolean;
38
+ showForgotLink: boolean;
39
+ showInviteCode: boolean;
40
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: typeof __VLS_export;
42
+ export default _default;