@vue-skuilder/common-ui 0.2.35 → 0.2.37
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/_virtual/_@oxc-project_runtime@0.115.0/helpers/defineProperty.mjs +13 -0
- package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/toPrimitive.mjs +15 -0
- package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/toPropertyKey.mjs +10 -0
- package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/typeof.mjs +12 -0
- package/dist/_virtual/_plugin-vue_export-helper.mjs +9 -0
- package/dist/_virtual/_rolldown/runtime.mjs +7 -0
- package/dist/admin/common-ui-admin.es.js +259 -23774
- package/dist/admin/common-ui-admin.es.js.map +1 -1
- package/dist/assets/index.css +2 -1
- package/dist/components/CardBrowser.mjs +63 -0
- package/dist/components/CardBrowser.mjs.map +1 -0
- package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs +50 -0
- package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/CardHistoryViewer.mjs +70 -0
- package/dist/components/CardHistoryViewer.mjs.map +1 -0
- package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs +108 -0
- package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/CardSearch.mjs +26 -0
- package/dist/components/CardSearch.mjs.map +1 -0
- package/dist/components/CardSearch.vue_vue_type_script_lang.mjs +17 -0
- package/dist/components/CardSearch.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/CardSearchResults.mjs +32 -0
- package/dist/components/CardSearchResults.mjs.map +1 -0
- package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs +71 -0
- package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/CourseCardBrowser.mjs +175 -0
- package/dist/components/CourseCardBrowser.mjs.map +1 -0
- package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs +173 -0
- package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/CourseInformation.mjs +132 -0
- package/dist/components/CourseInformation.mjs.map +1 -0
- package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs +56 -0
- package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/CourseTagFilterWidget.mjs +114 -0
- package/dist/components/CourseTagFilterWidget.mjs.map +1 -0
- package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs +65 -0
- package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/HeatMap.mjs +40 -0
- package/dist/components/HeatMap.mjs.map +1 -0
- package/dist/components/HeatMap.vue_vue_type_script_lang.mjs +211 -0
- package/dist/components/HeatMap.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/PaginatingToolbar.mjs +94 -0
- package/dist/components/PaginatingToolbar.mjs.map +1 -0
- package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs +36 -0
- package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/SessionControllerDebug.mjs +130 -0
- package/dist/components/SessionControllerDebug.mjs.map +1 -0
- package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs +45 -0
- package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/SkMouseTrap.mjs +66 -0
- package/dist/components/SkMouseTrap.mjs.map +1 -0
- package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs +31 -0
- package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/SkMouseTrapToolTip.mjs +28 -0
- package/dist/components/SkMouseTrapToolTip.mjs.map +1 -0
- package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs +91 -0
- package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/SnackbarService.mjs +24 -0
- package/dist/components/SnackbarService.mjs.map +1 -0
- package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs +34 -0
- package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/SnackbarService2.mjs +40 -0
- package/dist/components/SnackbarService2.mjs.map +1 -0
- package/dist/components/StudySession.mjs +123 -0
- package/dist/components/StudySession.mjs.map +1 -0
- package/dist/components/StudySession.vue_vue_type_script_lang.mjs +280 -0
- package/dist/components/StudySession.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/StudySessionTimer.mjs +50 -0
- package/dist/components/StudySessionTimer.mjs.map +1 -0
- package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs +43 -0
- package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/TagsInput.mjs +45 -0
- package/dist/components/TagsInput.mjs.map +1 -0
- package/dist/components/TagsInput.vue_vue_type_script_lang.mjs +117 -0
- package/dist/components/TagsInput.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/UserTagPreferences.mjs +205 -0
- package/dist/components/UserTagPreferences.mjs.map +1 -0
- package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs +139 -0
- package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/auth/RequestPasswordReset.mjs +96 -0
- package/dist/components/auth/RequestPasswordReset.mjs.map +1 -0
- package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs +47 -0
- package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/auth/ResetPassword.mjs +129 -0
- package/dist/components/auth/ResetPassword.mjs.map +1 -0
- package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs +69 -0
- package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/auth/UserChip.mjs +9 -0
- package/dist/components/auth/UserChip.mjs.map +1 -0
- package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs +213 -0
- package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/components/auth/UserLogin.mjs +9 -0
- package/dist/components/auth/UserLogin.mjs.map +1 -0
- package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs +155 -0
- package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/components/auth/UserLoginAndRegistrationContainer.mjs +9 -0
- package/dist/components/auth/UserLoginAndRegistrationContainer.mjs.map +1 -0
- package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs +126 -0
- package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/components/auth/UserRegistration.mjs +147 -0
- package/dist/components/auth/UserRegistration.mjs.map +1 -0
- package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs +130 -0
- package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/auth/VerifyEmail.mjs +118 -0
- package/dist/components/auth/VerifyEmail.mjs.map +1 -0
- package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs +59 -0
- package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/cardRendering/AudioAutoPlayer.mjs +9 -0
- package/dist/components/cardRendering/AudioAutoPlayer.mjs.map +1 -0
- package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs +69 -0
- package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/components/cardRendering/CardLoader.mjs +31 -0
- package/dist/components/cardRendering/CardLoader.mjs.map +1 -0
- package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs +75 -0
- package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/cardRendering/CardViewer.mjs +39 -0
- package/dist/components/cardRendering/CardViewer.mjs.map +1 -0
- package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs +66 -0
- package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/cardRendering/CodeBlockRenderer.mjs +8 -0
- package/dist/components/cardRendering/CodeBlockRenderer.mjs.map +1 -0
- package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs +44 -0
- package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/components/cardRendering/MarkdownRenderer.mjs +21 -0
- package/dist/components/cardRendering/MarkdownRenderer.mjs.map +1 -0
- package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs +24 -0
- package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/cardRendering/MarkdownRendererHelpers.mjs +79 -0
- package/dist/components/cardRendering/MarkdownRendererHelpers.mjs.map +1 -0
- package/dist/components/cardRendering/MdTokenRenderer.mjs +9 -0
- package/dist/components/cardRendering/MdTokenRenderer.mjs.map +1 -0
- package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs +176 -0
- package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
- package/dist/components/studentInputs/BaseUserInput.mjs +54 -0
- package/dist/components/studentInputs/BaseUserInput.mjs.map +1 -0
- package/dist/components/studentInputs/MultipleChoiceOption.mjs +26 -0
- package/dist/components/studentInputs/MultipleChoiceOption.mjs.map +1 -0
- package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs +76 -0
- package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/studentInputs/RadioMultipleChoice.mjs +33 -0
- package/dist/components/studentInputs/RadioMultipleChoice.mjs.map +1 -0
- package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs +105 -0
- package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/studentInputs/TrueFalse.mjs +19 -0
- package/dist/components/studentInputs/TrueFalse.mjs.map +1 -0
- package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs +21 -0
- package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/studentInputs/UserInputNumber.mjs +33 -0
- package/dist/components/studentInputs/UserInputNumber.mjs.map +1 -0
- package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs +25 -0
- package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/studentInputs/UserInputString.mjs +22 -0
- package/dist/components/studentInputs/UserInputString.mjs.map +1 -0
- package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs +23 -0
- package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/components/studentInputs/fillInInput.mjs +25 -0
- package/dist/components/studentInputs/fillInInput.mjs.map +1 -0
- package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs +26 -0
- package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs.map +1 -0
- package/dist/composables/CompositionViewable.mjs +65 -0
- package/dist/composables/CompositionViewable.mjs.map +1 -0
- package/dist/composables/Displayable.mjs +36 -0
- package/dist/composables/Displayable.mjs.map +1 -0
- package/dist/composables/useAuthUI.mjs +38 -0
- package/dist/composables/useAuthUI.mjs.map +1 -0
- package/dist/composables/useEntitlements.mjs +58 -0
- package/dist/composables/useEntitlements.mjs.map +1 -0
- package/dist/index.mjs +49 -0
- package/dist/plugins/pinia.mjs +12 -0
- package/dist/plugins/pinia.mjs.map +1 -0
- package/dist/services/authAPI.mjs +159 -0
- package/dist/services/authAPI.mjs.map +1 -0
- package/dist/stores/useAuthStore.mjs +68 -0
- package/dist/stores/useAuthStore.mjs.map +1 -0
- package/dist/stores/useCardPreviewModeStore.mjs +20 -0
- package/dist/stores/useCardPreviewModeStore.mjs.map +1 -0
- package/dist/stores/useConfigStore.mjs +60 -0
- package/dist/stores/useConfigStore.mjs.map +1 -0
- package/dist/utils/SkldrMouseTrap.mjs +48 -0
- package/dist/utils/SkldrMouseTrap.mjs.map +1 -0
- package/dist/utils/passwordValidation.mjs +12 -0
- package/dist/utils/passwordValidation.mjs.map +1 -0
- package/package.json +7 -8
- package/dist/MarkdownRenderer-U_iPiA2x.mjs +0 -4966
- package/dist/MarkdownRenderer-U_iPiA2x.mjs.map +0 -1
- package/dist/assets/MarkdownRenderer.css +0 -1
- package/dist/common-ui.es.js +0 -5090
- package/dist/common-ui.es.js.map +0 -1
- package/dist/common-ui.umd.js +0 -77
- package/dist/common-ui.umd.js.map +0 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
//#region src/services/authAPI.ts
|
|
3
|
+
var getApiBase = () => {
|
|
4
|
+
let e = "fallback (empty string)", t = "";
|
|
5
|
+
if (!t && typeof window < "u" && window.__SKUILDER_CONFIG__?.apiBase) {
|
|
6
|
+
let n = window.__SKUILDER_CONFIG__.apiBase.replace(/\/$/, "");
|
|
7
|
+
t = n.startsWith("/") ? n : `/${n}`, e = "window.__SKUILDER_CONFIG__.apiBase";
|
|
8
|
+
}
|
|
9
|
+
return console.log("[authAPI] getApiBase() called"), console.log("[authAPI] source:", e), console.log("[authAPI] result:", t), t;
|
|
10
|
+
};
|
|
11
|
+
async function sendVerificationEmail(e, t, n) {
|
|
12
|
+
try {
|
|
13
|
+
let r = {
|
|
14
|
+
username: e,
|
|
15
|
+
email: t
|
|
16
|
+
};
|
|
17
|
+
n && (r.origin = n);
|
|
18
|
+
let i = await fetch(`${getApiBase()}/auth/send-verification`, {
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: { "Content-Type": "application/json" },
|
|
21
|
+
credentials: "include",
|
|
22
|
+
body: JSON.stringify(r)
|
|
23
|
+
});
|
|
24
|
+
if (!i.ok) {
|
|
25
|
+
let e = await i.text();
|
|
26
|
+
return console.error("Send verification email error:", e), {
|
|
27
|
+
ok: !1,
|
|
28
|
+
error: `HTTP ${i.status}: ${i.statusText}`
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return await i.json();
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return console.error("Send verification email fetch error:", e), {
|
|
34
|
+
ok: !1,
|
|
35
|
+
error: e instanceof Error ? e.message : "Network error"
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function verifyEmail(e) {
|
|
40
|
+
try {
|
|
41
|
+
let t = await fetch(`${getApiBase()}/auth/verify`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
credentials: "include",
|
|
45
|
+
body: JSON.stringify({ token: e })
|
|
46
|
+
});
|
|
47
|
+
if (!t.ok) {
|
|
48
|
+
let e;
|
|
49
|
+
try {
|
|
50
|
+
e = (await t.json())?.error;
|
|
51
|
+
} catch {}
|
|
52
|
+
return {
|
|
53
|
+
ok: !1,
|
|
54
|
+
error: e || `HTTP ${t.status}: ${t.statusText}`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return await t.json();
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return {
|
|
60
|
+
ok: !1,
|
|
61
|
+
error: e instanceof Error ? e.message : "Network error"
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function resolveLoginIdentifier(e, t) {
|
|
66
|
+
try {
|
|
67
|
+
let n = await fetch(`${getApiBase()}/auth/resolve-login`, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
headers: { "Content-Type": "application/json" },
|
|
70
|
+
credentials: "include",
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
identifier: e,
|
|
73
|
+
password: t
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
if (!n.ok) {
|
|
77
|
+
let e;
|
|
78
|
+
try {
|
|
79
|
+
e = (await n.json())?.error;
|
|
80
|
+
} catch {}
|
|
81
|
+
return {
|
|
82
|
+
ok: !1,
|
|
83
|
+
status: n.status,
|
|
84
|
+
error: e || `HTTP ${n.status}: ${n.statusText}`
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return await n.json();
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return {
|
|
90
|
+
ok: !1,
|
|
91
|
+
error: e instanceof Error ? e.message : "Network error"
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function getUserStatus() {
|
|
96
|
+
try {
|
|
97
|
+
let e = await fetch(`${getApiBase()}/auth/status`, {
|
|
98
|
+
method: "GET",
|
|
99
|
+
headers: { "Content-Type": "application/json" },
|
|
100
|
+
credentials: "include"
|
|
101
|
+
});
|
|
102
|
+
return e.ok ? await e.json() : {
|
|
103
|
+
ok: !1,
|
|
104
|
+
error: `HTTP ${e.status}: ${e.statusText}`
|
|
105
|
+
};
|
|
106
|
+
} catch (e) {
|
|
107
|
+
return {
|
|
108
|
+
ok: !1,
|
|
109
|
+
error: e instanceof Error ? e.message : "Network error"
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function requestPasswordReset(e, t) {
|
|
114
|
+
try {
|
|
115
|
+
let n = { email: e };
|
|
116
|
+
t && (n.origin = t);
|
|
117
|
+
let r = await fetch(`${getApiBase()}/auth/request-reset`, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers: { "Content-Type": "application/json" },
|
|
120
|
+
credentials: "include",
|
|
121
|
+
body: JSON.stringify(n)
|
|
122
|
+
});
|
|
123
|
+
return r.ok ? await r.json() : {
|
|
124
|
+
ok: !1,
|
|
125
|
+
error: `HTTP ${r.status}: ${r.statusText}`
|
|
126
|
+
};
|
|
127
|
+
} catch (e) {
|
|
128
|
+
return {
|
|
129
|
+
ok: !1,
|
|
130
|
+
error: e instanceof Error ? e.message : "Network error"
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function resetPassword(e, t) {
|
|
135
|
+
try {
|
|
136
|
+
let n = await fetch(`${getApiBase()}/auth/reset-password`, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
headers: { "Content-Type": "application/json" },
|
|
139
|
+
credentials: "include",
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
token: e,
|
|
142
|
+
newPassword: t
|
|
143
|
+
})
|
|
144
|
+
});
|
|
145
|
+
return n.ok ? await n.json() : {
|
|
146
|
+
ok: !1,
|
|
147
|
+
error: `HTTP ${n.status}: ${n.statusText}`
|
|
148
|
+
};
|
|
149
|
+
} catch (e) {
|
|
150
|
+
return {
|
|
151
|
+
ok: !1,
|
|
152
|
+
error: e instanceof Error ? e.message : "Network error"
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
export { getUserStatus, requestPasswordReset, resetPassword, resolveLoginIdentifier, sendVerificationEmail, verifyEmail };
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=authAPI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authAPI.mjs","names":[],"sources":["../../src/services/authAPI.ts"],"sourcesContent":["/**\n * Authentication API service for interacting with Express backend auth endpoints.\n * Uses configurable API base path from environment or runtime config.\n */\n\n// Global runtime configuration (set by consuming app)\ndeclare global {\n interface Window {\n __SKUILDER_CONFIG__?: {\n apiBase?: string;\n [key: string]: unknown;\n };\n }\n}\n\n// Get API base path: check env first, then runtime config, then fallback to empty\nconst getApiBase = (): string => {\n let source = 'fallback (empty string)';\n let result = '';\n\n // Try import.meta.env first (build-time, only works in consuming app builds)\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n const base = import.meta.env.VITE_API_BASE_URL;\n if (base) {\n const cleaned = base.replace(/\\/$/, '');\n result = cleaned.startsWith('/') ? cleaned : `/${cleaned}`;\n source = 'import.meta.env.VITE_API_BASE_URL';\n }\n }\n\n // Fallback to runtime config (works in library builds)\n if (!result && typeof window !== 'undefined' && window.__SKUILDER_CONFIG__?.apiBase) {\n const base = window.__SKUILDER_CONFIG__.apiBase;\n const cleaned = base.replace(/\\/$/, '');\n result = cleaned.startsWith('/') ? cleaned : `/${cleaned}`;\n source = 'window.__SKUILDER_CONFIG__.apiBase';\n }\n\n console.log('[authAPI] getApiBase() called');\n console.log('[authAPI] source:', source);\n console.log('[authAPI] result:', result);\n\n return result;\n};\n\nexport interface AuthResponse {\n ok: boolean;\n error?: string;\n}\n\nexport interface VerifyEmailResponse extends AuthResponse {\n username?: string;\n}\n\nexport interface Entitlement {\n status: 'trial' | 'paid';\n registrationDate: string;\n purchaseDate?: string;\n expires?: string;\n}\n\nexport type UserEntitlements = Record<string, Entitlement>;\n\nexport interface UserStatusResponse extends AuthResponse {\n username?: string;\n status?: 'pending_verification' | 'verified' | 'suspended';\n email?: string | null;\n entitlements?: UserEntitlements;\n}\n\nexport interface ResolveLoginResponse extends AuthResponse {\n username?: string;\n /**\n * HTTP status of the resolve call on failure, so callers can distinguish a\n * genuine credential rejection from a system/service failure. The server\n * returns a uniform 401 for every real auth failure (unknown identifier,\n * unverified email, wrong password — no enumeration leak); anything else\n * (404 = route not deployed, 5xx, or `undefined` for a network error) means\n * the resolver itself is unavailable, not that the credentials were wrong.\n * Undefined on success.\n */\n status?: number;\n}\n\n/**\n * Triggers verification email send for a newly created account.\n *\n * @param username - Username of the newly created account\n * @param email - User's email address (passed directly to avoid race conditions with DB sync)\n * @param origin - Optional frontend origin URL (e.g., window.location.origin)\n * Used to construct the correct verification link in the email.\n * If not provided, backend falls back to APP_URL env var.\n */\nexport async function sendVerificationEmail(\n username: string,\n email: string,\n origin?: string\n): Promise<AuthResponse> {\n try {\n const body: { username: string; email: string; origin?: string } = { username, email };\n if (origin) {\n body.origin = origin;\n }\n\n const response = await fetch(`${getApiBase()}/auth/send-verification`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('Send verification email error:', errorText);\n return {\n ok: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n console.error('Send verification email fetch error:', error);\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Network error',\n };\n }\n}\n\n/**\n * Verify user email using token from magic link.\n */\nexport async function verifyEmail(token: string): Promise<VerifyEmailResponse> {\n try {\n const response = await fetch(`${getApiBase()}/auth/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ token }),\n });\n\n if (!response.ok) {\n // Prefer the server's explanatory message (expired token, email already\n // verified on another account, …) over a bare HTTP status.\n let serverError: string | undefined;\n try {\n serverError = (await response.json())?.error;\n } catch {\n // non-JSON body — fall through to the generic message\n }\n return {\n ok: false,\n error: serverError || `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Network error',\n };\n }\n}\n\n/**\n * Resolve a login identifier (username OR email) to a couch username, gated on\n * the correct password. Returns the username only on success; every failure is\n * a uniform \"invalid credentials\" (no account-enumeration leak). Used by the\n * login form before calling user.login() when the identifier is an email.\n */\nexport async function resolveLoginIdentifier(\n identifier: string,\n password: string\n): Promise<ResolveLoginResponse> {\n try {\n const response = await fetch(`${getApiBase()}/auth/resolve-login`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ identifier, password }),\n });\n\n if (!response.ok) {\n let serverError: string | undefined;\n try {\n serverError = (await response.json())?.error;\n } catch {\n // non-JSON body — fall through to the generic message\n }\n return {\n ok: false,\n status: response.status,\n error: serverError || `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n // Network / fetch failure — no HTTP status. Left undefined so callers treat\n // it as a system failure, not a credential rejection.\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Network error',\n };\n }\n}\n\n/**\n * Get current user's account status (verification status, email).\n * Requires valid AuthSession cookie.\n */\nexport async function getUserStatus(): Promise<UserStatusResponse> {\n try {\n const response = await fetch(`${getApiBase()}/auth/status`, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n });\n\n if (!response.ok) {\n return {\n ok: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Network error',\n };\n }\n}\n\n/**\n * Request password reset email for user identified by email.\n *\n * @param email - User's email address\n * @param origin - Optional frontend origin URL (e.g., window.location.origin)\n * Used to construct the correct password reset link in the email.\n * If not provided, backend falls back to APP_URL env var.\n */\nexport async function requestPasswordReset(\n email: string,\n origin?: string\n): Promise<AuthResponse> {\n try {\n const body: { email: string; origin?: string } = { email };\n if (origin) {\n body.origin = origin;\n }\n\n const response = await fetch(`${getApiBase()}/auth/request-reset`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n return {\n ok: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Network error',\n };\n }\n}\n\n/**\n * Reset password using token from magic link.\n */\nexport async function resetPassword(\n token: string,\n newPassword: string\n): Promise<AuthResponse> {\n try {\n const response = await fetch(`${getApiBase()}/auth/reset-password`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ token, newPassword }),\n });\n\n if (!response.ok) {\n return {\n ok: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : 'Network error',\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { getPinia as e } from "../plugins/pinia.mjs";
|
|
3
|
+
import { getDataLayer as t } from "@vue-skuilder/db";
|
|
4
|
+
import { defineStore as n, setActivePinia as r } from "pinia";
|
|
5
|
+
//#region src/stores/useAuthStore.ts
|
|
6
|
+
async function getCurrentUser() {
|
|
7
|
+
let e = useAuthStore();
|
|
8
|
+
if (!e.onLoadComplete) {
|
|
9
|
+
let t = 200;
|
|
10
|
+
for (; !e.onLoadComplete && t > 0;) await new Promise((e) => setTimeout(e, 50)), t--;
|
|
11
|
+
if (!e.onLoadComplete) throw Error("User initialization timed out");
|
|
12
|
+
}
|
|
13
|
+
return t().getUserDB();
|
|
14
|
+
}
|
|
15
|
+
var useAuthStore = () => {
|
|
16
|
+
let i = e();
|
|
17
|
+
return i && r(i), n("auth", {
|
|
18
|
+
state: () => ({
|
|
19
|
+
_user: void 0,
|
|
20
|
+
loginAndRegistration: {
|
|
21
|
+
init: !1,
|
|
22
|
+
loggedIn: !1,
|
|
23
|
+
regDialogOpen: !1,
|
|
24
|
+
loginDialogOpen: !1
|
|
25
|
+
},
|
|
26
|
+
onLoadComplete: !1
|
|
27
|
+
}),
|
|
28
|
+
actions: {
|
|
29
|
+
async init() {
|
|
30
|
+
try {
|
|
31
|
+
this._user = t().getUserDB(), this.loginAndRegistration.loggedIn = this._user ? this._user.isLoggedIn() : !1, this.onLoadComplete = !0, this.loginAndRegistration.init = !0;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error("Failed to initialize auth store:", e), this.loginAndRegistration.loggedIn = !1, this.onLoadComplete = !0, this.loginAndRegistration.init = !0;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
setLoginDialog(e) {
|
|
37
|
+
this.loginAndRegistration.loginDialogOpen = e;
|
|
38
|
+
},
|
|
39
|
+
setRegDialog(e) {
|
|
40
|
+
this.loginAndRegistration.regDialogOpen = e;
|
|
41
|
+
},
|
|
42
|
+
async resetUserData() {
|
|
43
|
+
try {
|
|
44
|
+
if (!this._user) throw Error("No user available for data reset");
|
|
45
|
+
let e = await this._user.resetUserData();
|
|
46
|
+
if (e.status !== "ok") throw Error(e.error || "Reset failed");
|
|
47
|
+
return console.log("User data reset successfully"), e;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
throw console.error("Failed to reset user data:", e), e;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
getters: {
|
|
54
|
+
currentUser: async () => getCurrentUser(),
|
|
55
|
+
isLoggedIn: (e) => e.loginAndRegistration.loggedIn,
|
|
56
|
+
isInitialized: (e) => e.loginAndRegistration.init,
|
|
57
|
+
status: (e) => ({
|
|
58
|
+
loggedIn: e.loginAndRegistration.loggedIn,
|
|
59
|
+
init: e.loginAndRegistration.init,
|
|
60
|
+
user: e._user
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
export { getCurrentUser, useAuthStore };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=useAuthStore.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthStore.mjs","names":[],"sources":["../../src/stores/useAuthStore.ts"],"sourcesContent":["// stores/useAuthStore.ts\nimport { defineStore, setActivePinia } from 'pinia';\nimport { getDataLayer, UserDBInterface } from '@vue-skuilder/db';\nimport { getPinia } from '../plugins/pinia';\n\nexport interface AuthState {\n _user: UserDBInterface | undefined;\n loginAndRegistration: {\n init: boolean;\n loggedIn: boolean;\n regDialogOpen: boolean;\n loginDialogOpen: boolean;\n };\n onLoadComplete: boolean;\n}\n\nexport async function getCurrentUser(): Promise<UserDBInterface | undefined> {\n const store = useAuthStore();\n\n if (!store.onLoadComplete) {\n // Wait for initialization\n let retries = 200;\n const timeout = 50;\n while (!store.onLoadComplete && retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, timeout));\n retries--;\n }\n if (!store.onLoadComplete) {\n throw new Error('User initialization timed out');\n }\n }\n\n return getDataLayer().getUserDB();\n}\n\nexport const useAuthStore = () => {\n // Get the Pinia instance from the plugin\n const pinia = getPinia();\n if (pinia) {\n setActivePinia(pinia);\n }\n\n // Return the store\n return defineStore('auth', {\n state: (): AuthState => ({\n _user: undefined as UserDBInterface | undefined,\n loginAndRegistration: {\n init: false,\n loggedIn: false,\n regDialogOpen: false,\n loginDialogOpen: false,\n },\n onLoadComplete: false,\n }),\n\n actions: {\n async init() {\n try {\n this._user = getDataLayer().getUserDB();\n\n this.loginAndRegistration.loggedIn = this._user ? this._user.isLoggedIn() : false;\n\n this.onLoadComplete = true;\n this.loginAndRegistration.init = true;\n } catch (e) {\n console.error('Failed to initialize auth store:', e);\n // Set onLoadComplete even on error to prevent timeout\n this.loginAndRegistration.loggedIn = false;\n this.onLoadComplete = true;\n this.loginAndRegistration.init = true;\n }\n },\n\n setLoginDialog(open: boolean) {\n this.loginAndRegistration.loginDialogOpen = open;\n },\n\n setRegDialog(open: boolean) {\n this.loginAndRegistration.regDialogOpen = open;\n },\n\n async resetUserData() {\n try {\n if (!this._user) {\n throw new Error('No user available for data reset');\n }\n \n const result = await this._user.resetUserData();\n if (result.status !== 'ok') {\n throw new Error(result.error || 'Reset failed');\n }\n \n console.log('User data reset successfully');\n return result;\n } catch (error) {\n console.error('Failed to reset user data:', error);\n throw error;\n }\n },\n },\n\n getters: {\n currentUser: async () => getCurrentUser(),\n isLoggedIn: (state) => state.loginAndRegistration.loggedIn,\n isInitialized: (state) => state.loginAndRegistration.init,\n status: (state) => {\n return {\n loggedIn: state.loginAndRegistration.loggedIn,\n init: state.loginAndRegistration.init,\n user: state._user,\n };\n },\n },\n })();\n};\n"],"mappings":";;;;;AAgBA,eAAsB,iBAAuD;CAC3E,IAAM,IAAQ,cAAc;AAE5B,KAAI,CAAC,EAAM,gBAAgB;EAEzB,IAAI,IAAU;AAEd,SAAO,CAAC,EAAM,kBAAkB,IAAU,GAExC,CADA,MAAM,IAAI,SAAS,MAAY,WAAW,GAAS,GAAQ,CAAC,EAC5D;AAEF,MAAI,CAAC,EAAM,eACT,OAAU,MAAM,gCAAgC;;AAIpD,QAAO,GAAc,CAAC,WAAW;;AAGnC,IAAa,qBAAqB;CAEhC,IAAM,IAAQ,GAAU;AAMxB,QALI,KACF,EAAe,EAAM,EAIhB,EAAY,QAAQ;EACzB,cAAyB;GACvB,OAAO,KAAA;GACP,sBAAsB;IACpB,MAAM;IACN,UAAU;IACV,eAAe;IACf,iBAAiB;IAClB;GACD,gBAAgB;GACjB;EAED,SAAS;GACP,MAAM,OAAO;AACX,QAAI;AAMF,KALA,KAAK,QAAQ,GAAc,CAAC,WAAW,EAEvC,KAAK,qBAAqB,WAAW,KAAK,QAAQ,KAAK,MAAM,YAAY,GAAG,IAE5E,KAAK,iBAAiB,IACtB,KAAK,qBAAqB,OAAO;aAC1B,GAAG;AAKV,KAJA,QAAQ,MAAM,oCAAoC,EAAE,EAEpD,KAAK,qBAAqB,WAAW,IACrC,KAAK,iBAAiB,IACtB,KAAK,qBAAqB,OAAO;;;GAIrC,eAAe,GAAe;AAC5B,SAAK,qBAAqB,kBAAkB;;GAG9C,aAAa,GAAe;AAC1B,SAAK,qBAAqB,gBAAgB;;GAG5C,MAAM,gBAAgB;AACpB,QAAI;AACF,SAAI,CAAC,KAAK,MACR,OAAU,MAAM,mCAAmC;KAGrD,IAAM,IAAS,MAAM,KAAK,MAAM,eAAe;AAC/C,SAAI,EAAO,WAAW,KACpB,OAAU,MAAM,EAAO,SAAS,eAAe;AAIjD,YADA,QAAQ,IAAI,+BAA+B,EACpC;aACA,GAAO;AAEd,WADA,QAAQ,MAAM,8BAA8B,EAAM,EAC5C;;;GAGX;EAED,SAAS;GACP,aAAa,YAAY,gBAAgB;GACzC,aAAa,MAAU,EAAM,qBAAqB;GAClD,gBAAgB,MAAU,EAAM,qBAAqB;GACrD,SAAS,OACA;IACL,UAAU,EAAM,qBAAqB;IACrC,MAAM,EAAM,qBAAqB;IACjC,MAAM,EAAM;IACb;GAEJ;EACF,CAAC,EAAE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { getPinia as e } from "../plugins/pinia.mjs";
|
|
3
|
+
import { defineStore as t, setActivePinia as n } from "pinia";
|
|
4
|
+
//#region src/stores/useCardPreviewModeStore.ts
|
|
5
|
+
var useCardPreviewModeStore = () => {
|
|
6
|
+
let r = e();
|
|
7
|
+
return r && n(r), t("previewMode", {
|
|
8
|
+
state: () => ({ previewMode: !1 }),
|
|
9
|
+
actions: { setPreviewMode(e) {
|
|
10
|
+
this.previewMode = e;
|
|
11
|
+
} },
|
|
12
|
+
getters: { isPreviewMode() {
|
|
13
|
+
return this.previewMode;
|
|
14
|
+
} }
|
|
15
|
+
})();
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useCardPreviewModeStore };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=useCardPreviewModeStore.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCardPreviewModeStore.mjs","names":[],"sources":["../../src/stores/useCardPreviewModeStore.ts"],"sourcesContent":["// common-ui/src/stores/useCardPreviewModeStore.ts\nimport { defineStore, setActivePinia } from 'pinia';\nimport { getPinia } from '../plugins/pinia';\n\nexport interface PreviewModeState {\n previewMode: boolean;\n}\n\nexport const useCardPreviewModeStore = () => {\n // Get the Pinia instance from the plugin\n const pinia = getPinia();\n if (pinia) {\n setActivePinia(pinia);\n }\n\n // Return the store\n return defineStore('previewMode', {\n state: (): PreviewModeState => ({\n previewMode: false,\n }),\n actions: {\n setPreviewMode(mode: boolean) {\n this.previewMode = mode;\n },\n },\n getters: {\n isPreviewMode(): boolean {\n return this.previewMode;\n },\n },\n })();\n};\n"],"mappings":";;;;AAQA,IAAa,gCAAgC;CAE3C,IAAM,IAAQ,GAAU;AAMxB,QALI,KACF,EAAe,EAAM,EAIhB,EAAY,eAAe;EAChC,cAAgC,EAC9B,aAAa,IACd;EACD,SAAS,EACP,eAAe,GAAe;AAC5B,QAAK,cAAc;KAEtB;EACD,SAAS,EACP,gBAAyB;AACvB,UAAO,KAAK;KAEf;EACF,CAAC,EAAE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { getPinia as e } from "../plugins/pinia.mjs";
|
|
3
|
+
import { getCurrentUser as t } from "./useAuthStore.mjs";
|
|
4
|
+
import { defineStore as n, setActivePinia as r } from "pinia";
|
|
5
|
+
//#region src/stores/useConfigStore.ts
|
|
6
|
+
var useConfigStore = () => {
|
|
7
|
+
let i = e();
|
|
8
|
+
return i && r(i), n("config", {
|
|
9
|
+
state: () => ({ config: {
|
|
10
|
+
darkMode: !1,
|
|
11
|
+
likesConfetti: !1,
|
|
12
|
+
sessionTimeLimit: 5
|
|
13
|
+
} }),
|
|
14
|
+
actions: {
|
|
15
|
+
updateConfig(e) {
|
|
16
|
+
this.config = e;
|
|
17
|
+
},
|
|
18
|
+
async updateDarkMode(e) {
|
|
19
|
+
this.config.darkMode = e;
|
|
20
|
+
let n = await t();
|
|
21
|
+
n && await n.setConfig({ darkMode: e });
|
|
22
|
+
},
|
|
23
|
+
async updateLikesConfetti(e) {
|
|
24
|
+
this.config.likesConfetti = e;
|
|
25
|
+
let n = await t();
|
|
26
|
+
n && await n.setConfig({ likesConfetti: e });
|
|
27
|
+
},
|
|
28
|
+
async updateSessionTimeLimit(e) {
|
|
29
|
+
this.config.sessionTimeLimit = e;
|
|
30
|
+
let n = await t();
|
|
31
|
+
n && await n.setConfig({ sessionTimeLimit: e });
|
|
32
|
+
},
|
|
33
|
+
async hydrate() {
|
|
34
|
+
try {
|
|
35
|
+
let e = await t();
|
|
36
|
+
if (e) {
|
|
37
|
+
let t = await e.getConfig();
|
|
38
|
+
console.log(`user config: ${JSON.stringify(t)}`), this.updateConfig(t);
|
|
39
|
+
} else console.log("No user logged in, using default config");
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.warn("Failed to hydrate config store, using defaults:", e);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async init() {
|
|
45
|
+
await this.hydrate();
|
|
46
|
+
},
|
|
47
|
+
resetDefaults() {
|
|
48
|
+
this.config = {
|
|
49
|
+
darkMode: !1,
|
|
50
|
+
likesConfetti: !1,
|
|
51
|
+
sessionTimeLimit: 5
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { useConfigStore };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=useConfigStore.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConfigStore.mjs","names":[],"sources":["../../src/stores/useConfigStore.ts"],"sourcesContent":["// stores/useConfigStore.ts\nimport { defineStore, setActivePinia } from 'pinia';\nimport { getCurrentUser } from './useAuthStore';\nimport { UserConfig } from '@vue-skuilder/db';\nimport { getPinia } from '../plugins/pinia';\n\nexport const useConfigStore = () => {\n // Get the Pinia instance from the plugin\n const pinia = getPinia();\n if (pinia) {\n setActivePinia(pinia);\n }\n\n // Return the store\n return defineStore('config', {\n state: () => ({\n config: {\n darkMode: false,\n likesConfetti: false,\n sessionTimeLimit: 5, // Default 5 minutes\n } as UserConfig,\n }),\n\n actions: {\n updateConfig(newConfig: UserConfig) {\n this.config = newConfig;\n },\n async updateDarkMode(darkMode: boolean) {\n this.config.darkMode = darkMode;\n const user = await getCurrentUser();\n if (user) {\n await user.setConfig({\n darkMode,\n });\n }\n },\n\n async updateLikesConfetti(likesConfetti: boolean) {\n this.config.likesConfetti = likesConfetti;\n const user = await getCurrentUser();\n if (user) {\n await user.setConfig({\n likesConfetti,\n });\n }\n },\n\n async updateSessionTimeLimit(sessionTimeLimit: number) {\n this.config.sessionTimeLimit = sessionTimeLimit;\n const user = await getCurrentUser();\n if (user) {\n await user.setConfig({\n sessionTimeLimit,\n });\n }\n },\n\n async hydrate() {\n try {\n const user = await getCurrentUser();\n if (user) {\n const cfg = await user.getConfig();\n console.log(`user config: ${JSON.stringify(cfg)}`);\n this.updateConfig(cfg);\n } else {\n console.log('No user logged in, using default config');\n }\n } catch (e) {\n console.warn('Failed to hydrate config store, using defaults:', e);\n }\n },\n async init() {\n await this.hydrate();\n },\n resetDefaults() {\n this.config = {\n darkMode: false,\n likesConfetti: false,\n sessionTimeLimit: 5,\n };\n },\n },\n })();\n};\n"],"mappings":";;;;;AAMA,IAAa,uBAAuB;CAElC,IAAM,IAAQ,GAAU;AAMxB,QALI,KACF,EAAe,EAAM,EAIhB,EAAY,UAAU;EAC3B,cAAc,EACZ,QAAQ;GACN,UAAU;GACV,eAAe;GACf,kBAAkB;GACnB,EACF;EAED,SAAS;GACP,aAAa,GAAuB;AAClC,SAAK,SAAS;;GAEhB,MAAM,eAAe,GAAmB;AACtC,SAAK,OAAO,WAAW;IACvB,IAAM,IAAO,MAAM,GAAgB;AACnC,IAAI,KACF,MAAM,EAAK,UAAU,EACnB,aACD,CAAC;;GAIN,MAAM,oBAAoB,GAAwB;AAChD,SAAK,OAAO,gBAAgB;IAC5B,IAAM,IAAO,MAAM,GAAgB;AACnC,IAAI,KACF,MAAM,EAAK,UAAU,EACnB,kBACD,CAAC;;GAIN,MAAM,uBAAuB,GAA0B;AACrD,SAAK,OAAO,mBAAmB;IAC/B,IAAM,IAAO,MAAM,GAAgB;AACnC,IAAI,KACF,MAAM,EAAK,UAAU,EACnB,qBACD,CAAC;;GAIN,MAAM,UAAU;AACd,QAAI;KACF,IAAM,IAAO,MAAM,GAAgB;AACnC,SAAI,GAAM;MACR,IAAM,IAAM,MAAM,EAAK,WAAW;AAElC,MADA,QAAQ,IAAI,gBAAgB,KAAK,UAAU,EAAI,GAAG,EAClD,KAAK,aAAa,EAAI;WAEtB,SAAQ,IAAI,0CAA0C;aAEjD,GAAG;AACV,aAAQ,KAAK,mDAAmD,EAAE;;;GAGtE,MAAM,OAAO;AACX,UAAM,KAAK,SAAS;;GAEtB,gBAAgB;AACd,SAAK,SAAS;KACZ,UAAU;KACV,eAAe;KACf,kBAAkB;KACnB;;GAEJ;EACF,CAAC,EAAE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { _defineProperty as e } from "../_virtual/_@oxc-project_runtime@0.115.0/helpers/defineProperty.mjs";
|
|
3
|
+
import t from "mousetrap";
|
|
4
|
+
//#region src/utils/SkldrMouseTrap.ts
|
|
5
|
+
function inputElementIsFocused() {
|
|
6
|
+
let e = document.activeElement;
|
|
7
|
+
return e instanceof HTMLInputElement && (e.type === "checkbox" || e.type === "radio") ? !1 : e instanceof HTMLElement && (e.tagName === "INPUT" || e.tagName === "TEXTAREA" || e.tagName === "SELECT" || e.isContentEditable);
|
|
8
|
+
}
|
|
9
|
+
var n = class SkldrMouseTrap {
|
|
10
|
+
constructor() {
|
|
11
|
+
e(this, "mouseTrap", void 0), e(this, "hotkeys", void 0), this.mouseTrap = new t(), this.mouseTrap.stopCallback = () => !1, this.hotkeys = [];
|
|
12
|
+
}
|
|
13
|
+
static get commands() {
|
|
14
|
+
return SkldrMouseTrap.instance().hotkeys.map((e) => ({
|
|
15
|
+
command: e.command,
|
|
16
|
+
hotkey: e.hotkey
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
static addBinding(e) {
|
|
20
|
+
let t = Array.isArray(e) ? e : [e], n = SkldrMouseTrap.instance();
|
|
21
|
+
n.hotkeys = [...n.hotkeys, ...t], t.forEach((e) => {
|
|
22
|
+
n.mouseTrap.bind(e.hotkey, (t, n) => {
|
|
23
|
+
if (inputElementIsFocused()) {
|
|
24
|
+
console.log(`Ignoring hotkey ${e.hotkey} while input element is focused`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
e.callback(t, n);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
static removeBinding(e) {
|
|
32
|
+
let t = SkldrMouseTrap.instance(), n = [...t.hotkeys];
|
|
33
|
+
Array.isArray(e) && !e.every((e) => typeof e == "string" || typeof e == "number") ? e.forEach((e) => {
|
|
34
|
+
t.hotkeys = t.hotkeys.filter((t) => JSON.stringify(t.hotkey) !== JSON.stringify(e)), t.mouseTrap.unbind(e);
|
|
35
|
+
}) : (t.hotkeys = n.filter((t) => JSON.stringify(t.hotkey) !== JSON.stringify(e)), t.mouseTrap.unbind(e));
|
|
36
|
+
}
|
|
37
|
+
static reset() {
|
|
38
|
+
console.warn("SkldrMouseTrap.reset() may affect hotkeys registered by other components. Consider using removeBinding() with specific hotkeys for better component isolation."), SkldrMouseTrap.instance().mouseTrap.reset(), SkldrMouseTrap.instance().hotkeys = [];
|
|
39
|
+
}
|
|
40
|
+
static instance() {
|
|
41
|
+
return SkldrMouseTrap._instance || (SkldrMouseTrap._instance = new SkldrMouseTrap()), SkldrMouseTrap._instance;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
e(n, "_instance", void 0);
|
|
45
|
+
//#endregion
|
|
46
|
+
export { n as SkldrMouseTrap };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=SkldrMouseTrap.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkldrMouseTrap.mjs","names":[],"sources":["../../src/utils/SkldrMouseTrap.ts"],"sourcesContent":["import Mousetrap from 'mousetrap';\nimport { ExtendedKeyboardEvent, MousetrapInstance } from 'mousetrap';\n\nexport interface HotKey extends HotKeyMetaData {\n callback: (e: ExtendedKeyboardEvent, combo: string) => void;\n}\n\nexport interface HotKeyMetaData {\n command: string;\n hotkey: string | string[];\n}\n\n/**\n * Checks if focus is currently on an input element where hotkeys should be ignored\n * @returns true if hotkeys should be ignored, false otherwise\n */\nfunction inputElementIsFocused(): boolean {\n const activeElement = document.activeElement;\n\n // Special handling for checkbox and radio inputs\n if (\n activeElement instanceof HTMLInputElement &&\n (activeElement.type === 'checkbox' || activeElement.type === 'radio')\n ) {\n return false;\n }\n\n return (\n activeElement instanceof HTMLElement &&\n (activeElement.tagName === 'INPUT' ||\n activeElement.tagName === 'TEXTAREA' ||\n activeElement.tagName === 'SELECT' ||\n activeElement.isContentEditable)\n );\n}\n\nexport class SkldrMouseTrap {\n private static _instance: SkldrMouseTrap;\n\n private mouseTrap: MousetrapInstance;\n private hotkeys: HotKey[];\n\n private constructor() {\n this.mouseTrap = new Mousetrap();\n // Allow hotkeys to fire even when input elements are focused — the\n // inputElementIsFocused() guard in addBinding handles selective suppression.\n this.mouseTrap.stopCallback = () => false;\n this.hotkeys = [];\n }\n\n public static get commands(): HotKeyMetaData[] {\n return SkldrMouseTrap.instance().hotkeys.map((hk) => {\n return {\n command: hk.command,\n hotkey: hk.hotkey,\n };\n });\n }\n\n /**\n * Add keyboard bindings without resetting existing ones\n * @param hk Single hotkey or array of hotkeys to bind\n */\n public static addBinding(hk: HotKey | HotKey[]) {\n const hotkeys = Array.isArray(hk) ? hk : [hk];\n const instance = SkldrMouseTrap.instance();\n\n // Add to internal registry\n instance.hotkeys = [...instance.hotkeys, ...hotkeys];\n\n // Bind each hotkey\n hotkeys.forEach((k) => {\n instance.mouseTrap.bind(k.hotkey, (a, b) => {\n // Skip execution if focus is on input elements\n if (inputElementIsFocused()) {\n console.log(`Ignoring hotkey ${k.hotkey} while input element is focused`);\n return;\n }\n\n // console.log(`Running ${k.hotkey}`);\n k.callback(a, b);\n });\n });\n }\n\n /**\n * Remove specific keyboard binding(s) without affecting others\n * @param hotkey Single hotkey or array of hotkeys to remove\n */\n public static removeBinding(hotkey: string | string[]) {\n const instance = SkldrMouseTrap.instance();\n const currentHotkeys = [...instance.hotkeys];\n\n if (\n Array.isArray(hotkey) &&\n !hotkey.every((k) => typeof k === 'string' || typeof k === 'number')\n ) {\n // If it's an array of hotkey specifiers\n hotkey.forEach((key) => {\n // Remove from internal registry\n instance.hotkeys = instance.hotkeys.filter((k) => {\n return JSON.stringify(k.hotkey) !== JSON.stringify(key);\n });\n\n // Unbind from Mousetrap\n instance.mouseTrap.unbind(key);\n });\n } else {\n // Single hotkey removal (original implementation)\n // Remove from internal registry\n instance.hotkeys = currentHotkeys.filter((k) => {\n // Convert both to JSON for comparison to handle arrays correctly\n return JSON.stringify(k.hotkey) !== JSON.stringify(hotkey);\n });\n\n // Unbind from Mousetrap\n instance.mouseTrap.unbind(hotkey);\n }\n }\n\n /**\n * Reset all keyboard bindings\n * @warning Consider using removeBinding() for targeted cleanup instead to avoid affecting other components\n */\n public static reset() {\n console.warn(\n 'SkldrMouseTrap.reset() may affect hotkeys registered by other components. ' +\n 'Consider using removeBinding() with specific hotkeys for better component isolation.'\n );\n SkldrMouseTrap.instance().mouseTrap.reset();\n SkldrMouseTrap.instance().hotkeys = [];\n }\n\n private static instance(): SkldrMouseTrap {\n if (SkldrMouseTrap._instance) {\n return SkldrMouseTrap._instance;\n } else {\n SkldrMouseTrap._instance = new SkldrMouseTrap();\n return SkldrMouseTrap._instance;\n }\n }\n}\n"],"mappings":";;;;AAgBA,SAAS,wBAAiC;CACxC,IAAM,IAAgB,SAAS;AAU/B,QANE,aAAyB,qBACxB,EAAc,SAAS,cAAc,EAAc,SAAS,WAEtD,KAIP,aAAyB,gBACxB,EAAc,YAAY,WACzB,EAAc,YAAY,cAC1B,EAAc,YAAY,YAC1B,EAAc;;AAIpB,IAAa,IAAb,MAAa,eAAe;CAM1B,cAAsB;AAKpB,UARF,aAAA,KAAA,EAAQ,UACR,WAAA,KAAA,EAAQ,EAGN,KAAK,YAAY,IAAI,GAAW,EAGhC,KAAK,UAAU,qBAAqB,IACpC,KAAK,UAAU,EAAE;;CAGnB,WAAkB,WAA6B;AAC7C,SAAO,eAAe,UAAU,CAAC,QAAQ,KAAK,OACrC;GACL,SAAS,EAAG;GACZ,QAAQ,EAAG;GACZ,EACD;;CAOJ,OAAc,WAAW,GAAuB;EAC9C,IAAM,IAAU,MAAM,QAAQ,EAAG,GAAG,IAAK,CAAC,EAAG,EACvC,IAAW,eAAe,UAAU;AAM1C,EAHA,EAAS,UAAU,CAAC,GAAG,EAAS,SAAS,GAAG,EAAQ,EAGpD,EAAQ,SAAS,MAAM;AACrB,KAAS,UAAU,KAAK,EAAE,SAAS,GAAG,MAAM;AAE1C,QAAI,uBAAuB,EAAE;AAC3B,aAAQ,IAAI,mBAAmB,EAAE,OAAO,iCAAiC;AACzE;;AAIF,MAAE,SAAS,GAAG,EAAE;KAChB;IACF;;CAOJ,OAAc,cAAc,GAA2B;EACrD,IAAM,IAAW,eAAe,UAAU,EACpC,IAAiB,CAAC,GAAG,EAAS,QAAQ;AAE5C,EACE,MAAM,QAAQ,EAAO,IACrB,CAAC,EAAO,OAAO,MAAM,OAAO,KAAM,YAAY,OAAO,KAAM,SAAS,GAGpE,EAAO,SAAS,MAAQ;AAOtB,GALA,EAAS,UAAU,EAAS,QAAQ,QAAQ,MACnC,KAAK,UAAU,EAAE,OAAO,KAAK,KAAK,UAAU,EAAI,CACvD,EAGF,EAAS,UAAU,OAAO,EAAI;IAC9B,IAIF,EAAS,UAAU,EAAe,QAAQ,MAEjC,KAAK,UAAU,EAAE,OAAO,KAAK,KAAK,UAAU,EAAO,CAC1D,EAGF,EAAS,UAAU,OAAO,EAAO;;CAQrC,OAAc,QAAQ;AAMpB,EALA,QAAQ,KACN,iKAED,EACD,eAAe,UAAU,CAAC,UAAU,OAAO,EAC3C,eAAe,UAAU,CAAC,UAAU,EAAE;;CAGxC,OAAe,WAA2B;AAKtC,SAJE,eAAe,cAGjB,eAAe,YAAY,IAAI,gBAAgB,GAFxC,eAAe;;;KAlGX,aAAA,KAAA,EAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import "../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
//#region src/utils/passwordValidation.ts
|
|
3
|
+
function validatePassword(e) {
|
|
4
|
+
return e ? e.length < 6 ? "Password must be at least 6 characters" : new Set(e).size < 2 ? "Password must contain at least 2 different characters" : "" : "";
|
|
5
|
+
}
|
|
6
|
+
function isPasswordValid(e) {
|
|
7
|
+
return validatePassword(e) === "";
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { isPasswordValid, validatePassword };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=passwordValidation.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passwordValidation.mjs","names":[],"sources":["../../src/utils/passwordValidation.ts"],"sourcesContent":["/**\n * Simple password validation utilities.\n *\n * Requirements:\n * - At least 6 characters\n * - At least 2 distinct characters\n */\n\nexport function validatePassword(password: string): string {\n if (!password) return '';\n\n // At least 6 characters\n if (password.length < 6) {\n return 'Password must be at least 6 characters';\n }\n\n // At least 2 distinct characters\n const uniqueChars = new Set(password).size;\n if (uniqueChars < 2) {\n return 'Password must contain at least 2 different characters';\n }\n\n return '';\n}\n\n/**\n * Check if password is valid (no error message)\n */\nexport function isPasswordValid(password: string): boolean {\n return validatePassword(password) === '';\n}\n"],"mappings":";;AAQA,SAAgB,iBAAiB,GAA0B;AAczD,QAbK,IAGD,EAAS,SAAS,IACb,2CAIW,IAAI,IAAI,EAAS,CAAC,OACpB,IACT,0DAGF,KAbe;;AAmBxB,SAAgB,gBAAgB,GAA2B;AACzD,QAAO,iBAAiB,EAAS,KAAK"}
|
package/package.json
CHANGED
|
@@ -3,16 +3,14 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.37",
|
|
7
7
|
"sideEffects": false,
|
|
8
|
-
"
|
|
9
|
-
"module": "./dist/common-ui.es.js",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
10
9
|
"types": "./dist/index.d.ts",
|
|
11
10
|
"exports": {
|
|
12
11
|
".": {
|
|
13
12
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"import": "./dist/
|
|
15
|
-
"require": "./dist/common-ui.umd.js"
|
|
13
|
+
"import": "./dist/index.mjs"
|
|
16
14
|
},
|
|
17
15
|
"./admin": {
|
|
18
16
|
"types": "./dist/admin/index.d.ts",
|
|
@@ -47,8 +45,9 @@
|
|
|
47
45
|
"@highlightjs/vue-plugin": "^2.1.2",
|
|
48
46
|
"@mdi/font": "^7.3.67",
|
|
49
47
|
"@vojtechlanka/vue-tags-input": "^3",
|
|
50
|
-
"@vue-skuilder/common": "0.2.
|
|
51
|
-
"@vue-skuilder/db": "0.2.
|
|
48
|
+
"@vue-skuilder/common": "0.2.37",
|
|
49
|
+
"@vue-skuilder/db": "0.2.37",
|
|
50
|
+
"canvas-confetti": "^1.9.3",
|
|
52
51
|
"echarts": "6.1.0",
|
|
53
52
|
"highlight.js": "^11.0.1",
|
|
54
53
|
"marked": "^15.0.6",
|
|
@@ -85,5 +84,5 @@
|
|
|
85
84
|
"vite-plugin-dts": "^4.5.3",
|
|
86
85
|
"vitest": "^4.1.0"
|
|
87
86
|
},
|
|
88
|
-
"stableVersion": "0.2.
|
|
87
|
+
"stableVersion": "0.2.37"
|
|
89
88
|
}
|