@vue-skuilder/common-ui 0.2.34 → 0.2.36

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 (207) hide show
  1. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/defineProperty.mjs +13 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/toPrimitive.mjs +15 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/toPropertyKey.mjs +10 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/typeof.mjs +12 -0
  5. package/dist/_virtual/_plugin-vue_export-helper.mjs +9 -0
  6. package/dist/_virtual/_rolldown/runtime.mjs +7 -0
  7. package/dist/admin/admin.css +1 -1
  8. package/dist/admin/common-ui-admin.es.js +1074 -473
  9. package/dist/admin/common-ui-admin.es.js.map +1 -1
  10. package/dist/admin/components/EChart.vue.d.ts +14 -0
  11. package/dist/admin/components/EChart.vue.d.ts.map +1 -0
  12. package/dist/admin/components/LearnerDiagnostics.vue.d.ts +3 -3
  13. package/dist/admin/components/LearnerDiagnostics.vue.d.ts.map +1 -1
  14. package/dist/admin/components/LearnerTagElo.vue.d.ts +14 -0
  15. package/dist/admin/components/LearnerTagElo.vue.d.ts.map +1 -0
  16. package/dist/admin/index.d.ts +1 -0
  17. package/dist/admin/index.d.ts.map +1 -1
  18. package/dist/assets/index.css +2 -1
  19. package/dist/components/CardBrowser.mjs +63 -0
  20. package/dist/components/CardBrowser.mjs.map +1 -0
  21. package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs +50 -0
  22. package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
  23. package/dist/components/CardHistoryViewer.mjs +70 -0
  24. package/dist/components/CardHistoryViewer.mjs.map +1 -0
  25. package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs +108 -0
  26. package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs.map +1 -0
  27. package/dist/components/CardSearch.mjs +26 -0
  28. package/dist/components/CardSearch.mjs.map +1 -0
  29. package/dist/components/CardSearch.vue_vue_type_script_lang.mjs +17 -0
  30. package/dist/components/CardSearch.vue_vue_type_script_lang.mjs.map +1 -0
  31. package/dist/components/CardSearchResults.mjs +32 -0
  32. package/dist/components/CardSearchResults.mjs.map +1 -0
  33. package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs +71 -0
  34. package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs.map +1 -0
  35. package/dist/components/CourseCardBrowser.mjs +175 -0
  36. package/dist/components/CourseCardBrowser.mjs.map +1 -0
  37. package/dist/components/CourseCardBrowser.vue.d.ts +3 -3
  38. package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs +173 -0
  39. package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
  40. package/dist/components/CourseInformation.mjs +132 -0
  41. package/dist/components/CourseInformation.mjs.map +1 -0
  42. package/dist/components/CourseInformation.vue.d.ts +3 -3
  43. package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs +56 -0
  44. package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs.map +1 -0
  45. package/dist/components/CourseTagFilterWidget.mjs +114 -0
  46. package/dist/components/CourseTagFilterWidget.mjs.map +1 -0
  47. package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs +65 -0
  48. package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs.map +1 -0
  49. package/dist/components/HeatMap.mjs +40 -0
  50. package/dist/components/HeatMap.mjs.map +1 -0
  51. package/dist/components/HeatMap.vue_vue_type_script_lang.mjs +211 -0
  52. package/dist/components/HeatMap.vue_vue_type_script_lang.mjs.map +1 -0
  53. package/dist/components/PaginatingToolbar.mjs +94 -0
  54. package/dist/components/PaginatingToolbar.mjs.map +1 -0
  55. package/dist/components/PaginatingToolbar.vue.d.ts +3 -3
  56. package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs +36 -0
  57. package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs.map +1 -0
  58. package/dist/components/SessionControllerDebug.mjs +130 -0
  59. package/dist/components/SessionControllerDebug.mjs.map +1 -0
  60. package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs +45 -0
  61. package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs.map +1 -0
  62. package/dist/components/SkMouseTrap.mjs +66 -0
  63. package/dist/components/SkMouseTrap.mjs.map +1 -0
  64. package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs +31 -0
  65. package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs.map +1 -0
  66. package/dist/components/SkMouseTrapToolTip.mjs +28 -0
  67. package/dist/components/SkMouseTrapToolTip.mjs.map +1 -0
  68. package/dist/components/SkMouseTrapToolTip.vue.d.ts +1 -1
  69. package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs +91 -0
  70. package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs.map +1 -0
  71. package/dist/components/SnackbarService.mjs +24 -0
  72. package/dist/components/SnackbarService.mjs.map +1 -0
  73. package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs +34 -0
  74. package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs.map +1 -0
  75. package/dist/components/SnackbarService2.mjs +40 -0
  76. package/dist/components/SnackbarService2.mjs.map +1 -0
  77. package/dist/components/StudySession.mjs +123 -0
  78. package/dist/components/StudySession.mjs.map +1 -0
  79. package/dist/components/StudySession.vue_vue_type_script_lang.mjs +280 -0
  80. package/dist/components/StudySession.vue_vue_type_script_lang.mjs.map +1 -0
  81. package/dist/components/StudySessionTimer.mjs +50 -0
  82. package/dist/components/StudySessionTimer.mjs.map +1 -0
  83. package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs +43 -0
  84. package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs.map +1 -0
  85. package/dist/components/TagsInput.mjs +45 -0
  86. package/dist/components/TagsInput.mjs.map +1 -0
  87. package/dist/components/TagsInput.vue_vue_type_script_lang.mjs +117 -0
  88. package/dist/components/TagsInput.vue_vue_type_script_lang.mjs.map +1 -0
  89. package/dist/components/UserTagPreferences.mjs +205 -0
  90. package/dist/components/UserTagPreferences.mjs.map +1 -0
  91. package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs +139 -0
  92. package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs.map +1 -0
  93. package/dist/components/auth/RequestPasswordReset.mjs +96 -0
  94. package/dist/components/auth/RequestPasswordReset.mjs.map +1 -0
  95. package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs +47 -0
  96. package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs.map +1 -0
  97. package/dist/components/auth/ResetPassword.mjs +129 -0
  98. package/dist/components/auth/ResetPassword.mjs.map +1 -0
  99. package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs +69 -0
  100. package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs.map +1 -0
  101. package/dist/components/auth/UserChip.mjs +9 -0
  102. package/dist/components/auth/UserChip.mjs.map +1 -0
  103. package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs +213 -0
  104. package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  105. package/dist/components/auth/UserLogin.mjs +9 -0
  106. package/dist/components/auth/UserLogin.mjs.map +1 -0
  107. package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs +155 -0
  108. package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  109. package/dist/components/auth/UserLoginAndRegistrationContainer.mjs +9 -0
  110. package/dist/components/auth/UserLoginAndRegistrationContainer.mjs.map +1 -0
  111. package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs +126 -0
  112. package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  113. package/dist/components/auth/UserRegistration.mjs +147 -0
  114. package/dist/components/auth/UserRegistration.mjs.map +1 -0
  115. package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs +130 -0
  116. package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs.map +1 -0
  117. package/dist/components/auth/VerifyEmail.mjs +118 -0
  118. package/dist/components/auth/VerifyEmail.mjs.map +1 -0
  119. package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs +59 -0
  120. package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs.map +1 -0
  121. package/dist/components/cardRendering/AudioAutoPlayer.mjs +9 -0
  122. package/dist/components/cardRendering/AudioAutoPlayer.mjs.map +1 -0
  123. package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs +69 -0
  124. package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  125. package/dist/components/cardRendering/CardLoader.mjs +31 -0
  126. package/dist/components/cardRendering/CardLoader.mjs.map +1 -0
  127. package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs +75 -0
  128. package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs.map +1 -0
  129. package/dist/components/cardRendering/CardViewer.mjs +39 -0
  130. package/dist/components/cardRendering/CardViewer.mjs.map +1 -0
  131. package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs +66 -0
  132. package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs.map +1 -0
  133. package/dist/components/cardRendering/CodeBlockRenderer.mjs +8 -0
  134. package/dist/components/cardRendering/CodeBlockRenderer.mjs.map +1 -0
  135. package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs +44 -0
  136. package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  137. package/dist/components/cardRendering/MarkdownRenderer.mjs +21 -0
  138. package/dist/components/cardRendering/MarkdownRenderer.mjs.map +1 -0
  139. package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs +24 -0
  140. package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs.map +1 -0
  141. package/dist/components/cardRendering/MarkdownRendererHelpers.mjs +79 -0
  142. package/dist/components/cardRendering/MarkdownRendererHelpers.mjs.map +1 -0
  143. package/dist/components/cardRendering/MdTokenRenderer.mjs +9 -0
  144. package/dist/components/cardRendering/MdTokenRenderer.mjs.map +1 -0
  145. package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs +176 -0
  146. package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  147. package/dist/components/studentInputs/BaseUserInput.mjs +54 -0
  148. package/dist/components/studentInputs/BaseUserInput.mjs.map +1 -0
  149. package/dist/components/studentInputs/MultipleChoiceOption.mjs +26 -0
  150. package/dist/components/studentInputs/MultipleChoiceOption.mjs.map +1 -0
  151. package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs +76 -0
  152. package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs.map +1 -0
  153. package/dist/components/studentInputs/RadioMultipleChoice.mjs +33 -0
  154. package/dist/components/studentInputs/RadioMultipleChoice.mjs.map +1 -0
  155. package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs +105 -0
  156. package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs.map +1 -0
  157. package/dist/components/studentInputs/TrueFalse.mjs +19 -0
  158. package/dist/components/studentInputs/TrueFalse.mjs.map +1 -0
  159. package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs +21 -0
  160. package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs.map +1 -0
  161. package/dist/components/studentInputs/UserInputNumber.mjs +33 -0
  162. package/dist/components/studentInputs/UserInputNumber.mjs.map +1 -0
  163. package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs +25 -0
  164. package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs.map +1 -0
  165. package/dist/components/studentInputs/UserInputString.mjs +22 -0
  166. package/dist/components/studentInputs/UserInputString.mjs.map +1 -0
  167. package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs +23 -0
  168. package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs.map +1 -0
  169. package/dist/components/studentInputs/fillInInput.mjs +25 -0
  170. package/dist/components/studentInputs/fillInInput.mjs.map +1 -0
  171. package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs +26 -0
  172. package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs.map +1 -0
  173. package/dist/composables/CompositionViewable.mjs +65 -0
  174. package/dist/composables/CompositionViewable.mjs.map +1 -0
  175. package/dist/composables/Displayable.mjs +36 -0
  176. package/dist/composables/Displayable.mjs.map +1 -0
  177. package/dist/composables/useAuthUI.mjs +38 -0
  178. package/dist/composables/useAuthUI.mjs.map +1 -0
  179. package/dist/composables/useEntitlements.mjs +58 -0
  180. package/dist/composables/useEntitlements.mjs.map +1 -0
  181. package/dist/index.mjs +49 -0
  182. package/dist/plugins/pinia.mjs +12 -0
  183. package/dist/plugins/pinia.mjs.map +1 -0
  184. package/dist/services/authAPI.mjs +159 -0
  185. package/dist/services/authAPI.mjs.map +1 -0
  186. package/dist/stores/useAuthStore.mjs +68 -0
  187. package/dist/stores/useAuthStore.mjs.map +1 -0
  188. package/dist/stores/useCardPreviewModeStore.mjs +20 -0
  189. package/dist/stores/useCardPreviewModeStore.mjs.map +1 -0
  190. package/dist/stores/useConfigStore.mjs +60 -0
  191. package/dist/stores/useConfigStore.mjs.map +1 -0
  192. package/dist/utils/SkldrMouseTrap.mjs +48 -0
  193. package/dist/utils/SkldrMouseTrap.mjs.map +1 -0
  194. package/dist/utils/passwordValidation.mjs +12 -0
  195. package/dist/utils/passwordValidation.mjs.map +1 -0
  196. package/package.json +8 -8
  197. package/src/admin/components/EChart.vue +59 -0
  198. package/src/admin/components/LearnerDiagnostics.vue +8 -4
  199. package/src/admin/components/LearnerTagElo.vue +563 -0
  200. package/src/admin/index.ts +1 -0
  201. package/dist/MarkdownRenderer-U_iPiA2x.mjs +0 -4966
  202. package/dist/MarkdownRenderer-U_iPiA2x.mjs.map +0 -1
  203. package/dist/assets/MarkdownRenderer.css +0 -1
  204. package/dist/common-ui.es.js +0 -5090
  205. package/dist/common-ui.es.js.map +0 -1
  206. package/dist/common-ui.umd.js +0 -77
  207. package/dist/common-ui.umd.js.map +0 -1
@@ -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.34",
6
+ "version": "0.2.36",
7
7
  "sideEffects": false,
8
- "main": "./dist/common-ui.umd.js",
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/common-ui.es.js",
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,10 @@
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.34",
51
- "@vue-skuilder/db": "0.2.34",
48
+ "@vue-skuilder/common": "0.2.36",
49
+ "@vue-skuilder/db": "0.2.36",
50
+ "canvas-confetti": "^1.9.3",
51
+ "echarts": "6.1.0",
52
52
  "highlight.js": "^11.0.1",
53
53
  "marked": "^15.0.6",
54
54
  "moment": "^2.29.4",
@@ -84,5 +84,5 @@
84
84
  "vite-plugin-dts": "^4.5.3",
85
85
  "vitest": "^4.1.0"
86
86
  },
87
- "stableVersion": "0.2.34"
87
+ "stableVersion": "0.2.36"
88
88
  }
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <div ref="el" :style="{ height: `${height}px`, width: '100%' }" />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import { onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue';
7
+ import { init, use, type ECElementEvent, type EChartsCoreOption, type EChartsType } from 'echarts/core';
8
+ import { LineChart, ScatterChart } from 'echarts/charts';
9
+ import {
10
+ DataZoomComponent,
11
+ GridComponent,
12
+ LegendComponent,
13
+ MarkLineComponent,
14
+ TooltipComponent,
15
+ } from 'echarts/components';
16
+ import { CanvasRenderer } from 'echarts/renderers';
17
+
18
+ /**
19
+ * An ECharts canvas for the admin views. Registers only what they draw, so
20
+ * the admin bundle carries a fraction of ECharts. Options are replaced
21
+ * whole on change (`notMerge`): callers compute the full option.
22
+ */
23
+ use([
24
+ LineChart,
25
+ ScatterChart,
26
+ DataZoomComponent,
27
+ GridComponent,
28
+ LegendComponent,
29
+ MarkLineComponent,
30
+ TooltipComponent,
31
+ CanvasRenderer,
32
+ ]);
33
+
34
+ const props = defineProps<{ option: EChartsCoreOption; height: number }>();
35
+ const emit = defineEmits<{ click: [event: ECElementEvent] }>();
36
+
37
+ const el = ref<HTMLElement | null>(null);
38
+ const chart = shallowRef<EChartsType | null>(null);
39
+ let resize: ResizeObserver | null = null;
40
+
41
+ onMounted(() => {
42
+ if (!el.value) return;
43
+ chart.value = init(el.value);
44
+ chart.value.setOption(props.option, { notMerge: true });
45
+ chart.value.on('click', (e) => emit('click', e as ECElementEvent));
46
+ resize = new ResizeObserver(() => chart.value?.resize());
47
+ resize.observe(el.value);
48
+ });
49
+
50
+ watch(
51
+ () => props.option,
52
+ (option) => chart.value?.setOption(option, { notMerge: true })
53
+ );
54
+
55
+ onBeforeUnmount(() => {
56
+ resize?.disconnect();
57
+ chart.value?.dispose();
58
+ });
59
+ </script>
@@ -4,6 +4,7 @@
4
4
  <v-tab value="sessions">Sessions ({{ dataset.sessions.length }})</v-tab>
5
5
  <v-tab value="cards">Cards ({{ dataset.cardHistories.length }})</v-tab>
6
6
  <v-tab v-if="dataset.strategies" value="pipeline">Pipeline</v-tab>
7
+ <v-tab value="elo">ELO</v-tab>
7
8
  </v-tabs>
8
9
 
9
10
  <template v-if="tab === 'sessions'">
@@ -40,6 +41,8 @@
40
41
  :stats="pipelineStats"
41
42
  :stats-label="dataset.username"
42
43
  />
44
+
45
+ <learner-tag-elo v-else-if="tab === 'elo'" :dataset="dataset" :interpreters="interpreters" />
43
46
  </div>
44
47
  </template>
45
48
 
@@ -49,20 +52,21 @@ import { pipelineRunStats, type DiagnosticsInterpreters, type LearnerDataset } f
49
52
  import LearnerCardHistory from './LearnerCardHistory.vue';
50
53
  import LearnerSessionDetail from './LearnerSessionDetail.vue';
51
54
  import LearnerSessionList from './LearnerSessionList.vue';
55
+ import LearnerTagElo from './LearnerTagElo.vue';
52
56
  import PipelineOverview from './PipelineOverview.vue';
53
57
 
54
58
  /**
55
- * One learner: sessions (list, then a session's detail), card history, and,
59
+ * One learner: sessions (list, then a session's detail), card history,
56
60
  * when the dataset carries the course's strategy docs, the pipeline with this
57
- * learner's run stats. Session timelines link into card history. Navigation is internal;
58
- * hosts that want URLs can compose the three views themselves.
61
+ * learner's run stats, and per-tag ELO. Session timelines link into card history. Navigation is internal;
62
+ * hosts that want URLs can compose the views themselves.
59
63
  */
60
64
  const props = defineProps<{
61
65
  dataset: LearnerDataset;
62
66
  interpreters?: DiagnosticsInterpreters;
63
67
  }>();
64
68
 
65
- const tab = ref<'sessions' | 'cards' | 'pipeline'>('sessions');
69
+ const tab = ref<'sessions' | 'cards' | 'pipeline' | 'elo'>('sessions');
66
70
  const sessionId = ref<string | null>(null);
67
71
  const focusCard = ref<string | undefined>(undefined);
68
72
  const pipelineStats = computed(() => pipelineRunStats(props.dataset));