@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.
Files changed (190) 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/common-ui-admin.es.js +259 -23774
  8. package/dist/admin/common-ui-admin.es.js.map +1 -1
  9. package/dist/assets/index.css +2 -1
  10. package/dist/components/CardBrowser.mjs +63 -0
  11. package/dist/components/CardBrowser.mjs.map +1 -0
  12. package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs +50 -0
  13. package/dist/components/CardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
  14. package/dist/components/CardHistoryViewer.mjs +70 -0
  15. package/dist/components/CardHistoryViewer.mjs.map +1 -0
  16. package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs +108 -0
  17. package/dist/components/CardHistoryViewer.vue_vue_type_script_lang.mjs.map +1 -0
  18. package/dist/components/CardSearch.mjs +26 -0
  19. package/dist/components/CardSearch.mjs.map +1 -0
  20. package/dist/components/CardSearch.vue_vue_type_script_lang.mjs +17 -0
  21. package/dist/components/CardSearch.vue_vue_type_script_lang.mjs.map +1 -0
  22. package/dist/components/CardSearchResults.mjs +32 -0
  23. package/dist/components/CardSearchResults.mjs.map +1 -0
  24. package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs +71 -0
  25. package/dist/components/CardSearchResults.vue_vue_type_script_lang.mjs.map +1 -0
  26. package/dist/components/CourseCardBrowser.mjs +175 -0
  27. package/dist/components/CourseCardBrowser.mjs.map +1 -0
  28. package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs +173 -0
  29. package/dist/components/CourseCardBrowser.vue_vue_type_script_lang.mjs.map +1 -0
  30. package/dist/components/CourseInformation.mjs +132 -0
  31. package/dist/components/CourseInformation.mjs.map +1 -0
  32. package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs +56 -0
  33. package/dist/components/CourseInformation.vue_vue_type_script_lang.mjs.map +1 -0
  34. package/dist/components/CourseTagFilterWidget.mjs +114 -0
  35. package/dist/components/CourseTagFilterWidget.mjs.map +1 -0
  36. package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs +65 -0
  37. package/dist/components/CourseTagFilterWidget.vue_vue_type_script_lang.mjs.map +1 -0
  38. package/dist/components/HeatMap.mjs +40 -0
  39. package/dist/components/HeatMap.mjs.map +1 -0
  40. package/dist/components/HeatMap.vue_vue_type_script_lang.mjs +211 -0
  41. package/dist/components/HeatMap.vue_vue_type_script_lang.mjs.map +1 -0
  42. package/dist/components/PaginatingToolbar.mjs +94 -0
  43. package/dist/components/PaginatingToolbar.mjs.map +1 -0
  44. package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs +36 -0
  45. package/dist/components/PaginatingToolbar.vue_vue_type_script_lang.mjs.map +1 -0
  46. package/dist/components/SessionControllerDebug.mjs +130 -0
  47. package/dist/components/SessionControllerDebug.mjs.map +1 -0
  48. package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs +45 -0
  49. package/dist/components/SessionControllerDebug.vue_vue_type_script_lang.mjs.map +1 -0
  50. package/dist/components/SkMouseTrap.mjs +66 -0
  51. package/dist/components/SkMouseTrap.mjs.map +1 -0
  52. package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs +31 -0
  53. package/dist/components/SkMouseTrap.vue_vue_type_script_lang.mjs.map +1 -0
  54. package/dist/components/SkMouseTrapToolTip.mjs +28 -0
  55. package/dist/components/SkMouseTrapToolTip.mjs.map +1 -0
  56. package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs +91 -0
  57. package/dist/components/SkMouseTrapToolTip.vue_vue_type_script_lang.mjs.map +1 -0
  58. package/dist/components/SnackbarService.mjs +24 -0
  59. package/dist/components/SnackbarService.mjs.map +1 -0
  60. package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs +34 -0
  61. package/dist/components/SnackbarService.vue_vue_type_script_lang.mjs.map +1 -0
  62. package/dist/components/SnackbarService2.mjs +40 -0
  63. package/dist/components/SnackbarService2.mjs.map +1 -0
  64. package/dist/components/StudySession.mjs +123 -0
  65. package/dist/components/StudySession.mjs.map +1 -0
  66. package/dist/components/StudySession.vue_vue_type_script_lang.mjs +280 -0
  67. package/dist/components/StudySession.vue_vue_type_script_lang.mjs.map +1 -0
  68. package/dist/components/StudySessionTimer.mjs +50 -0
  69. package/dist/components/StudySessionTimer.mjs.map +1 -0
  70. package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs +43 -0
  71. package/dist/components/StudySessionTimer.vue_vue_type_script_lang.mjs.map +1 -0
  72. package/dist/components/TagsInput.mjs +45 -0
  73. package/dist/components/TagsInput.mjs.map +1 -0
  74. package/dist/components/TagsInput.vue_vue_type_script_lang.mjs +117 -0
  75. package/dist/components/TagsInput.vue_vue_type_script_lang.mjs.map +1 -0
  76. package/dist/components/UserTagPreferences.mjs +205 -0
  77. package/dist/components/UserTagPreferences.mjs.map +1 -0
  78. package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs +139 -0
  79. package/dist/components/UserTagPreferences.vue_vue_type_script_lang.mjs.map +1 -0
  80. package/dist/components/auth/RequestPasswordReset.mjs +96 -0
  81. package/dist/components/auth/RequestPasswordReset.mjs.map +1 -0
  82. package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs +47 -0
  83. package/dist/components/auth/RequestPasswordReset.vue_vue_type_script_lang.mjs.map +1 -0
  84. package/dist/components/auth/ResetPassword.mjs +129 -0
  85. package/dist/components/auth/ResetPassword.mjs.map +1 -0
  86. package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs +69 -0
  87. package/dist/components/auth/ResetPassword.vue_vue_type_script_lang.mjs.map +1 -0
  88. package/dist/components/auth/UserChip.mjs +9 -0
  89. package/dist/components/auth/UserChip.mjs.map +1 -0
  90. package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs +213 -0
  91. package/dist/components/auth/UserChip.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  92. package/dist/components/auth/UserLogin.mjs +9 -0
  93. package/dist/components/auth/UserLogin.mjs.map +1 -0
  94. package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs +155 -0
  95. package/dist/components/auth/UserLogin.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  96. package/dist/components/auth/UserLoginAndRegistrationContainer.mjs +9 -0
  97. package/dist/components/auth/UserLoginAndRegistrationContainer.mjs.map +1 -0
  98. package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs +126 -0
  99. package/dist/components/auth/UserLoginAndRegistrationContainer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  100. package/dist/components/auth/UserRegistration.mjs +147 -0
  101. package/dist/components/auth/UserRegistration.mjs.map +1 -0
  102. package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs +130 -0
  103. package/dist/components/auth/UserRegistration.vue_vue_type_script_lang.mjs.map +1 -0
  104. package/dist/components/auth/VerifyEmail.mjs +118 -0
  105. package/dist/components/auth/VerifyEmail.mjs.map +1 -0
  106. package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs +59 -0
  107. package/dist/components/auth/VerifyEmail.vue_vue_type_script_lang.mjs.map +1 -0
  108. package/dist/components/cardRendering/AudioAutoPlayer.mjs +9 -0
  109. package/dist/components/cardRendering/AudioAutoPlayer.mjs.map +1 -0
  110. package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs +69 -0
  111. package/dist/components/cardRendering/AudioAutoPlayer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  112. package/dist/components/cardRendering/CardLoader.mjs +31 -0
  113. package/dist/components/cardRendering/CardLoader.mjs.map +1 -0
  114. package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs +75 -0
  115. package/dist/components/cardRendering/CardLoader.vue_vue_type_script_lang.mjs.map +1 -0
  116. package/dist/components/cardRendering/CardViewer.mjs +39 -0
  117. package/dist/components/cardRendering/CardViewer.mjs.map +1 -0
  118. package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs +66 -0
  119. package/dist/components/cardRendering/CardViewer.vue_vue_type_script_lang.mjs.map +1 -0
  120. package/dist/components/cardRendering/CodeBlockRenderer.mjs +8 -0
  121. package/dist/components/cardRendering/CodeBlockRenderer.mjs.map +1 -0
  122. package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs +44 -0
  123. package/dist/components/cardRendering/CodeBlockRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  124. package/dist/components/cardRendering/MarkdownRenderer.mjs +21 -0
  125. package/dist/components/cardRendering/MarkdownRenderer.mjs.map +1 -0
  126. package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs +24 -0
  127. package/dist/components/cardRendering/MarkdownRenderer.vue_vue_type_script_lang.mjs.map +1 -0
  128. package/dist/components/cardRendering/MarkdownRendererHelpers.mjs +79 -0
  129. package/dist/components/cardRendering/MarkdownRendererHelpers.mjs.map +1 -0
  130. package/dist/components/cardRendering/MdTokenRenderer.mjs +9 -0
  131. package/dist/components/cardRendering/MdTokenRenderer.mjs.map +1 -0
  132. package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs +176 -0
  133. package/dist/components/cardRendering/MdTokenRenderer.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  134. package/dist/components/studentInputs/BaseUserInput.mjs +54 -0
  135. package/dist/components/studentInputs/BaseUserInput.mjs.map +1 -0
  136. package/dist/components/studentInputs/MultipleChoiceOption.mjs +26 -0
  137. package/dist/components/studentInputs/MultipleChoiceOption.mjs.map +1 -0
  138. package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs +76 -0
  139. package/dist/components/studentInputs/MultipleChoiceOption.vue_vue_type_script_lang.mjs.map +1 -0
  140. package/dist/components/studentInputs/RadioMultipleChoice.mjs +33 -0
  141. package/dist/components/studentInputs/RadioMultipleChoice.mjs.map +1 -0
  142. package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs +105 -0
  143. package/dist/components/studentInputs/RadioMultipleChoice.vue_vue_type_script_lang.mjs.map +1 -0
  144. package/dist/components/studentInputs/TrueFalse.mjs +19 -0
  145. package/dist/components/studentInputs/TrueFalse.mjs.map +1 -0
  146. package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs +21 -0
  147. package/dist/components/studentInputs/TrueFalse.vue_vue_type_script_lang.mjs.map +1 -0
  148. package/dist/components/studentInputs/UserInputNumber.mjs +33 -0
  149. package/dist/components/studentInputs/UserInputNumber.mjs.map +1 -0
  150. package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs +25 -0
  151. package/dist/components/studentInputs/UserInputNumber.vue_vue_type_script_lang.mjs.map +1 -0
  152. package/dist/components/studentInputs/UserInputString.mjs +22 -0
  153. package/dist/components/studentInputs/UserInputString.mjs.map +1 -0
  154. package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs +23 -0
  155. package/dist/components/studentInputs/UserInputString.vue_vue_type_script_lang.mjs.map +1 -0
  156. package/dist/components/studentInputs/fillInInput.mjs +25 -0
  157. package/dist/components/studentInputs/fillInInput.mjs.map +1 -0
  158. package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs +26 -0
  159. package/dist/components/studentInputs/fillInInput.vue_vue_type_script_lang.mjs.map +1 -0
  160. package/dist/composables/CompositionViewable.mjs +65 -0
  161. package/dist/composables/CompositionViewable.mjs.map +1 -0
  162. package/dist/composables/Displayable.mjs +36 -0
  163. package/dist/composables/Displayable.mjs.map +1 -0
  164. package/dist/composables/useAuthUI.mjs +38 -0
  165. package/dist/composables/useAuthUI.mjs.map +1 -0
  166. package/dist/composables/useEntitlements.mjs +58 -0
  167. package/dist/composables/useEntitlements.mjs.map +1 -0
  168. package/dist/index.mjs +49 -0
  169. package/dist/plugins/pinia.mjs +12 -0
  170. package/dist/plugins/pinia.mjs.map +1 -0
  171. package/dist/services/authAPI.mjs +159 -0
  172. package/dist/services/authAPI.mjs.map +1 -0
  173. package/dist/stores/useAuthStore.mjs +68 -0
  174. package/dist/stores/useAuthStore.mjs.map +1 -0
  175. package/dist/stores/useCardPreviewModeStore.mjs +20 -0
  176. package/dist/stores/useCardPreviewModeStore.mjs.map +1 -0
  177. package/dist/stores/useConfigStore.mjs +60 -0
  178. package/dist/stores/useConfigStore.mjs.map +1 -0
  179. package/dist/utils/SkldrMouseTrap.mjs +48 -0
  180. package/dist/utils/SkldrMouseTrap.mjs.map +1 -0
  181. package/dist/utils/passwordValidation.mjs +12 -0
  182. package/dist/utils/passwordValidation.mjs.map +1 -0
  183. package/package.json +7 -8
  184. package/dist/MarkdownRenderer-U_iPiA2x.mjs +0 -4966
  185. package/dist/MarkdownRenderer-U_iPiA2x.mjs.map +0 -1
  186. package/dist/assets/MarkdownRenderer.css +0 -1
  187. package/dist/common-ui.es.js +0 -5090
  188. package/dist/common-ui.es.js.map +0 -1
  189. package/dist/common-ui.umd.js +0 -77
  190. package/dist/common-ui.umd.js.map +0 -1
@@ -0,0 +1,94 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import e from "../_virtual/_plugin-vue_export-helper.mjs";
3
+ import t from "./PaginatingToolbar.vue_vue_type_script_lang.mjs";
4
+ /* empty css */
5
+ import { createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createTextVNode as o, createVNode as s, openBlock as c, resolveComponent as l, toDisplayString as u, withCtx as d } from "vue";
6
+ //#region src/components/PaginatingToolbar.vue
7
+ var f = {
8
+ key: 0,
9
+ class: "ms-2 text-subtitle-2",
10
+ "data-cy": "paginating-toolbar-subtitle"
11
+ };
12
+ function _sfc_render(e, t, p, m, h, g) {
13
+ let _ = l("v-toolbar-title"), v = l("v-spacer"), y = l("v-icon"), b = l("v-btn"), x = l("v-select"), S = l("v-toolbar");
14
+ return c(), n(S, { density: "compact" }, {
15
+ default: d(() => [
16
+ s(_, null, {
17
+ default: d(() => [a("span", null, u(e.title), 1), e.subtitle ? (c(), i("span", f, u(e.subtitle), 1)) : r("", !0)]),
18
+ _: 1
19
+ }),
20
+ s(v),
21
+ s(b, {
22
+ variant: "text",
23
+ icon: "",
24
+ color: "secondary",
25
+ disabled: e.page == 1,
26
+ onClick: t[0] || (t[0] = (t) => e.$emit("first"))
27
+ }, {
28
+ default: d(() => [s(y, null, {
29
+ default: d(() => t[5] || (t[5] = [o("mdi-page-first")])),
30
+ _: 1
31
+ })]),
32
+ _: 1
33
+ }, 8, ["disabled"]),
34
+ s(b, {
35
+ variant: "text",
36
+ icon: "",
37
+ color: "secondary",
38
+ disabled: e.page == 1,
39
+ onClick: t[1] || (t[1] = (t) => e.$emit("prev"))
40
+ }, {
41
+ default: d(() => [s(y, null, {
42
+ default: d(() => t[6] || (t[6] = [o("mdi-chevron-left")])),
43
+ _: 1
44
+ })]),
45
+ _: 1
46
+ }, 8, ["disabled"]),
47
+ s(x, {
48
+ "model-value": e.page,
49
+ items: e.pages,
50
+ class: "pageSelect",
51
+ density: "compact",
52
+ "hide-details": "",
53
+ "return-object": !1,
54
+ variant: "outlined",
55
+ "onUpdate:modelValue": t[2] || (t[2] = (t) => e.$emit("set-page", t))
56
+ }, {
57
+ selection: d(({ item: e }) => [o(u(e.value), 1)]),
58
+ _: 1
59
+ }, 8, ["model-value", "items"]),
60
+ s(b, {
61
+ variant: "text",
62
+ icon: "",
63
+ color: "secondary",
64
+ disabled: e.page == e.pages.length,
65
+ onClick: t[3] || (t[3] = (t) => e.$emit("next"))
66
+ }, {
67
+ default: d(() => [s(y, null, {
68
+ default: d(() => t[7] || (t[7] = [o("mdi-chevron-right")])),
69
+ _: 1
70
+ })]),
71
+ _: 1
72
+ }, 8, ["disabled"]),
73
+ s(b, {
74
+ variant: "text",
75
+ icon: "",
76
+ color: "secondary",
77
+ disabled: e.page == e.pages.length,
78
+ onClick: t[4] || (t[4] = (t) => e.$emit("last"))
79
+ }, {
80
+ default: d(() => [s(y, null, {
81
+ default: d(() => t[8] || (t[8] = [o("mdi-page-last")])),
82
+ _: 1
83
+ })]),
84
+ _: 1
85
+ }, 8, ["disabled"])
86
+ ]),
87
+ _: 1
88
+ });
89
+ }
90
+ var p = /* @__PURE__ */ e(t, [["render", _sfc_render], ["__scopeId", "data-v-a75fea7e"]]);
91
+ //#endregion
92
+ export { p as default };
93
+
94
+ //# sourceMappingURL=PaginatingToolbar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaginatingToolbar.mjs","names":[],"sources":["../../src/components/PaginatingToolbar.vue"],"sourcesContent":["<template>\n <v-toolbar density=\"compact\">\n <v-toolbar-title>\n <span>{{ title }}</span>\n <span v-if=\"subtitle\" class=\"ms-2 text-subtitle-2\" data-cy=\"paginating-toolbar-subtitle\">{{ subtitle }}</span>\n </v-toolbar-title>\n <v-spacer></v-spacer>\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == 1\" @click=\"$emit('first')\">\n <v-icon>mdi-page-first</v-icon>\n </v-btn>\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == 1\" @click=\"$emit('prev')\">\n <v-icon>mdi-chevron-left</v-icon>\n </v-btn>\n\n <v-select\n :model-value=\"page\"\n :items=\"pages\"\n class=\"pageSelect\"\n density=\"compact\"\n hide-details\n :return-object=\"false\"\n variant=\"outlined\"\n @update:model-value=\"(val: unknown) => $emit('set-page', val)\"\n >\n <template #selection=\"{ item }\">\n {{ item.value }}\n </template>\n </v-select>\n\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == pages.length\" @click=\"$emit('next')\">\n <v-icon>mdi-chevron-right</v-icon>\n </v-btn>\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == pages.length\" @click=\"$emit('last')\">\n <v-icon>mdi-page-last</v-icon>\n </v-btn>\n </v-toolbar>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport type { PaginatingToolbarProps, PaginatingToolbarEvents } from './PaginatingToolbar.types';\n\nexport default defineComponent({\n name: 'PaginatingToolbar',\n\n props: {\n pages: {\n type: Array as PropType<number[]>,\n required: true,\n },\n page: {\n type: Number,\n required: true,\n },\n title: {\n type: String,\n required: false,\n default: '',\n },\n subtitle: {\n type: String,\n required: false,\n default: '',\n },\n } as const,\n\n emits: ['first', 'prev', 'next', 'last', 'set-page'],\n});\n</script>\n\n<style scoped>\n.pageSelect {\n max-width: 60px;\n}\n</style>\n"],"mappings":";;;;;;;CAAA,KAAA;CAI4B,OAAM;CAAuB,WAAQ;;;;aAH/D,EAkCY,GAAA,EAlCD,SAAQ,WAAS,EAAA;EAD9B,SAAA,QAKsB;GAHlB,EAGkB,GAAA,MAAA;IALtB,SAAA,QAG8B,CAAxB,EAAwB,QAAA,MAAA,EAAf,EAAA,MAAK,EAAA,EAAA,EACF,EAAA,YAAA,GAAA,EAAZ,EAA8G,QAA9G,GAA8G,EAAlB,EAAA,SAAQ,EAAA,EAAA,IAJ1G,EAAA,IAAA,GAAA,CAAA,CAAA;IAAA,GAAA;;GAMI,EAAqB,EAAA;GACrB,EAEQ,GAAA;IAFD,SAAQ;IAAO,MAAA;IAAK,OAAM;IAAa,UAAU,EAAA,QAAI;IAAQ,SAAK,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,QAAA;;IAPpF,SAAA,QAQqC,CAA/B,EAA+B,GAAA,MAAA;KARrC,SAAA,QAQ4B,EAAA,OAAA,EAAA,KAAA,CAR5B,EAQc,iBAAc,CAAA,EAAA;KAR5B,GAAA;;IAAA,GAAA;;GAUI,EAEQ,GAAA;IAFD,SAAQ;IAAO,MAAA;IAAK,OAAM;IAAa,UAAU,EAAA,QAAI;IAAQ,SAAK,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,OAAA;;IAVpF,SAAA,QAWuC,CAAjC,EAAiC,GAAA,MAAA;KAXvC,SAAA,QAW8B,EAAA,OAAA,EAAA,KAAA,CAX9B,EAWc,mBAAgB,CAAA,EAAA;KAX9B,GAAA;;IAAA,GAAA;;GAcI,EAaW,GAAA;IAZR,eAAa,EAAA;IACb,OAAO,EAAA;IACR,OAAM;IACN,SAAQ;IACR,gBAAA;IACC,iBAAe;IAChB,SAAQ;IACP,uBAAkB,EAAA,OAAA,EAAA,MAAG,MAAiB,EAAA,MAAK,YAAa,EAAG;;IAEjD,WAAS,GACF,EADM,cAAI,CAxBlC,EAAA,EAyBW,EAAK,MAAK,EAAA,EAAA,CAAA,CAAA;IAzBrB,GAAA;;GA6BI,EAEQ,GAAA;IAFD,SAAQ;IAAO,MAAA;IAAK,OAAM;IAAa,UAAU,EAAA,QAAQ,EAAA,MAAM;IAAS,SAAK,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,OAAA;;IA7B/F,SAAA,QA8BwC,CAAlC,EAAkC,GAAA,MAAA;KA9BxC,SAAA,QA8B+B,EAAA,OAAA,EAAA,KAAA,CA9B/B,EA8Bc,oBAAiB,CAAA,EAAA;KA9B/B,GAAA;;IAAA,GAAA;;GAgCI,EAEQ,GAAA;IAFD,SAAQ;IAAO,MAAA;IAAK,OAAM;IAAa,UAAU,EAAA,QAAQ,EAAA,MAAM;IAAS,SAAK,EAAA,OAAA,EAAA,MAAA,MAAE,EAAA,MAAK,OAAA;;IAhC/F,SAAA,QAiCoC,CAA9B,EAA8B,GAAA,MAAA;KAjCpC,SAAA,QAiC2B,EAAA,OAAA,EAAA,KAAA,CAjC3B,EAiCc,gBAAa,CAAA,EAAA;KAjC3B,GAAA;;IAAA,GAAA;;;EAAA,GAAA"}
@@ -0,0 +1,36 @@
1
+ import { defineComponent as e } from "vue";
2
+ //#region src/components/PaginatingToolbar.vue?vue&type=script&lang.ts
3
+ var t = e({
4
+ name: "PaginatingToolbar",
5
+ props: {
6
+ pages: {
7
+ type: Array,
8
+ required: !0
9
+ },
10
+ page: {
11
+ type: Number,
12
+ required: !0
13
+ },
14
+ title: {
15
+ type: String,
16
+ required: !1,
17
+ default: ""
18
+ },
19
+ subtitle: {
20
+ type: String,
21
+ required: !1,
22
+ default: ""
23
+ }
24
+ },
25
+ emits: [
26
+ "first",
27
+ "prev",
28
+ "next",
29
+ "last",
30
+ "set-page"
31
+ ]
32
+ });
33
+ //#endregion
34
+ export { t as default };
35
+
36
+ //# sourceMappingURL=PaginatingToolbar.vue_vue_type_script_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaginatingToolbar.vue_vue_type_script_lang.mjs","names":[],"sources":["../../src/components/PaginatingToolbar.vue"],"sourcesContent":["<template>\n <v-toolbar density=\"compact\">\n <v-toolbar-title>\n <span>{{ title }}</span>\n <span v-if=\"subtitle\" class=\"ms-2 text-subtitle-2\" data-cy=\"paginating-toolbar-subtitle\">{{ subtitle }}</span>\n </v-toolbar-title>\n <v-spacer></v-spacer>\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == 1\" @click=\"$emit('first')\">\n <v-icon>mdi-page-first</v-icon>\n </v-btn>\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == 1\" @click=\"$emit('prev')\">\n <v-icon>mdi-chevron-left</v-icon>\n </v-btn>\n\n <v-select\n :model-value=\"page\"\n :items=\"pages\"\n class=\"pageSelect\"\n density=\"compact\"\n hide-details\n :return-object=\"false\"\n variant=\"outlined\"\n @update:model-value=\"(val: unknown) => $emit('set-page', val)\"\n >\n <template #selection=\"{ item }\">\n {{ item.value }}\n </template>\n </v-select>\n\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == pages.length\" @click=\"$emit('next')\">\n <v-icon>mdi-chevron-right</v-icon>\n </v-btn>\n <v-btn variant=\"text\" icon color=\"secondary\" :disabled=\"page == pages.length\" @click=\"$emit('last')\">\n <v-icon>mdi-page-last</v-icon>\n </v-btn>\n </v-toolbar>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport type { PaginatingToolbarProps, PaginatingToolbarEvents } from './PaginatingToolbar.types';\n\nexport default defineComponent({\n name: 'PaginatingToolbar',\n\n props: {\n pages: {\n type: Array as PropType<number[]>,\n required: true,\n },\n page: {\n type: Number,\n required: true,\n },\n title: {\n type: String,\n required: false,\n default: '',\n },\n subtitle: {\n type: String,\n required: false,\n default: '',\n },\n } as const,\n\n emits: ['first', 'prev', 'next', 'last', 'set-page'],\n});\n</script>\n\n<style scoped>\n.pageSelect {\n max-width: 60px;\n}\n</style>\n"],"mappings":";;AA0CA,IAAA,IAAe,EAAgB;CAC7B,MAAM;CAEN,OAAO;EACL,OAAO;GACL,MAAM;GACN,UAAU;GACX;EACD,MAAM;GACJ,MAAM;GACN,UAAU;GACX;EACD,OAAO;GACL,MAAM;GACN,UAAU;GACV,SAAS;GACV;EACD,UAAU;GACR,MAAM;GACN,UAAU;GACV,SAAS;GACV;EACH;CAEA,OAAO;EAAC;EAAS;EAAQ;EAAQ;EAAQ;EAAW;CACrD,CAAC"}
@@ -0,0 +1,130 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import e from "../_virtual/_plugin-vue_export-helper.mjs";
3
+ import t from "./SessionControllerDebug.vue_vue_type_script_lang.mjs";
4
+ /* empty css */
5
+ import { Fragment as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createTextVNode as s, createVNode as c, openBlock as l, renderList as u, resolveComponent as d, toDisplayString as f, withCtx as p } from "vue";
6
+ //#region src/components/SessionControllerDebug.vue
7
+ var m = { class: "debug-section" }, h = { class: "debug-header" }, g = { class: "debug-stats" }, _ = { class: "text-caption" }, v = { class: "text-caption ml-2" }, y = {
8
+ key: 0,
9
+ class: "debug-items"
10
+ }, b = { class: "text-caption" }, x = { class: "text-caption text-grey ml-1" }, S = {
11
+ class: "text-caption ml-1",
12
+ style: { color: "#90caf9" }
13
+ }, C = {
14
+ key: 0,
15
+ class: "text-caption text-grey"
16
+ }, w = {
17
+ key: 1,
18
+ class: "text-caption text-grey"
19
+ }, T = { class: "debug-section" }, E = { class: "debug-header" }, D = { class: "debug-stats" }, O = { class: "text-caption" }, k = { class: "text-caption ml-2" }, A = {
20
+ key: 0,
21
+ class: "debug-items"
22
+ }, j = { class: "text-caption" }, M = { class: "text-caption text-grey ml-1" }, N = {
23
+ key: 0,
24
+ class: "text-caption text-grey"
25
+ }, P = {
26
+ key: 1,
27
+ class: "text-caption text-grey"
28
+ }, F = { class: "debug-section" }, I = { class: "debug-header" }, L = { class: "debug-stats" }, R = { class: "text-caption" }, z = { class: "text-caption ml-2" }, B = {
29
+ key: 0,
30
+ class: "debug-items"
31
+ }, V = { class: "text-caption" }, H = {
32
+ key: 0,
33
+ class: "text-caption text-grey"
34
+ }, U = {
35
+ key: 1,
36
+ class: "text-caption text-grey"
37
+ };
38
+ function _sfc_render(e, t, W, ee, te, G) {
39
+ let K = d("v-spacer"), q = d("v-icon"), J = d("v-card-title"), Y = d("v-col"), X = d("v-row"), Z = d("v-divider"), Q = d("v-card-text"), $ = d("v-card");
40
+ return e.sessionController ? (l(), r($, {
41
+ key: 0,
42
+ class: "session-debug ma-2",
43
+ elevation: "2"
44
+ }, {
45
+ default: p(() => [c(J, { class: "text-caption bg-grey-darken-3" }, {
46
+ default: p(() => [
47
+ t[1] || (t[1] = s(" Session Controller Debug ")),
48
+ c(K),
49
+ c(q, { size: "small" }, {
50
+ default: p(() => t[0] || (t[0] = [s("mdi-bug")])),
51
+ _: 1
52
+ })
53
+ ]),
54
+ _: 1
55
+ }), c(Q, { class: "pa-2" }, {
56
+ default: p(() => [c(X, { dense: "" }, {
57
+ default: p(() => [c(Y, {
58
+ cols: "12",
59
+ md: "8"
60
+ }, {
61
+ default: p(() => [o("div", m, [
62
+ o("div", h, [c(q, {
63
+ size: "x-small",
64
+ class: "mr-1"
65
+ }, {
66
+ default: p(() => t[2] || (t[2] = [s("mdi-sort")])),
67
+ _: 1
68
+ }), t[3] || (t[3] = o("strong", null, "Supply Queue", -1))]),
69
+ o("div", g, [o("span", _, "Length: " + f(e.debugInfo.supplyQueue.length), 1), o("span", v, "Dequeued: " + f(e.debugInfo.supplyQueue.dequeueCount), 1)]),
70
+ e.debugInfo.supplyQueue.items.length > 0 ? (l(), a("div", y, [(l(!0), a(n, null, u(e.debugInfo.supplyQueue.items.slice(0, 8), (t, n) => (l(), a("div", {
71
+ key: n,
72
+ class: "debug-item"
73
+ }, [
74
+ o("span", b, f(n) + ": " + f(t.courseID) + "::" + f(t.cardID), 1),
75
+ o("span", x, "(" + f(t.status) + ")", 1),
76
+ o("span", S, f(e.fmtScore(t.score)), 1)
77
+ ]))), 128)), e.debugInfo.supplyQueue.items.length > 8 ? (l(), a("div", C, " ... +" + f(e.debugInfo.supplyQueue.items.length - 8) + " more ", 1)) : i("", !0)])) : (l(), a("div", w, " (empty) "))
78
+ ])]),
79
+ _: 1
80
+ }), c(Y, {
81
+ cols: "12",
82
+ md: "4"
83
+ }, {
84
+ default: p(() => [o("div", T, [
85
+ o("div", E, [c(q, {
86
+ size: "x-small",
87
+ class: "mr-1"
88
+ }, {
89
+ default: p(() => t[4] || (t[4] = [s("mdi-alert-circle")])),
90
+ _: 1
91
+ }), t[5] || (t[5] = o("strong", null, "Failed Cards Queue", -1))]),
92
+ o("div", D, [o("span", O, "Length: " + f(e.debugInfo.failedQueue.length), 1), o("span", k, "Dequeued: " + f(e.debugInfo.failedQueue.dequeueCount), 1)]),
93
+ e.debugInfo.failedQueue.items.length > 0 ? (l(), a("div", A, [(l(!0), a(n, null, u(e.debugInfo.failedQueue.items.slice(0, 5), (e, t) => (l(), a("div", {
94
+ key: t,
95
+ class: "debug-item"
96
+ }, [o("span", j, f(t) + ": " + f(e.courseID) + "::" + f(e.cardID), 1), o("span", M, "(" + f(e.status) + ")", 1)]))), 128)), e.debugInfo.failedQueue.items.length > 5 ? (l(), a("div", N, " ... +" + f(e.debugInfo.failedQueue.items.length - 5) + " more ", 1)) : i("", !0)])) : (l(), a("div", P, " (empty) "))
97
+ ])]),
98
+ _: 1
99
+ })]),
100
+ _: 1
101
+ }), c(X, { dense: "" }, {
102
+ default: p(() => [c(Y, { cols: "12" }, {
103
+ default: p(() => [c(Z, { class: "my-2" }), o("div", F, [
104
+ o("div", I, [c(q, {
105
+ size: "x-small",
106
+ class: "mr-1"
107
+ }, {
108
+ default: p(() => t[6] || (t[6] = [s("mdi-database")])),
109
+ _: 1
110
+ }), t[7] || (t[7] = o("strong", null, "Hydrated Cards Cache", -1))]),
111
+ o("div", L, [o("span", R, "Cached: " + f(e.debugInfo.hydratedCache.count), 1), o("span", z, "Failed Cache: " + f(e.debugInfo.hydratedCache.failedCacheSize), 1)]),
112
+ e.debugInfo.hydratedCache.items.length > 0 ? (l(), a("div", B, [(l(!0), a(n, null, u(e.debugInfo.hydratedCache.items.slice(0, 8), (e, t) => (l(), a("div", {
113
+ key: t,
114
+ class: "debug-item d-inline-block mr-3"
115
+ }, [o("span", V, f(e.courseID) + "::" + f(e.cardID), 1)]))), 128)), e.debugInfo.hydratedCache.items.length > 8 ? (l(), a("div", H, " ... +" + f(e.debugInfo.hydratedCache.items.length - 8) + " more ", 1)) : i("", !0)])) : (l(), a("div", U, " (empty) "))
116
+ ])]),
117
+ _: 1
118
+ })]),
119
+ _: 1
120
+ })]),
121
+ _: 1
122
+ })]),
123
+ _: 1
124
+ })) : i("", !0);
125
+ }
126
+ var W = /* @__PURE__ */ e(t, [["render", _sfc_render], ["__scopeId", "data-v-641ac170"]]);
127
+ //#endregion
128
+ export { W as default };
129
+
130
+ //# sourceMappingURL=SessionControllerDebug.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionControllerDebug.mjs","names":[],"sources":["../../src/components/SessionControllerDebug.vue"],"sourcesContent":["<template>\n <v-card v-if=\"sessionController\" class=\"session-debug ma-2\" elevation=\"2\">\n <v-card-title class=\"text-caption bg-grey-darken-3\">\n Session Controller Debug\n <v-spacer></v-spacer>\n <v-icon size=\"small\">mdi-bug</v-icon>\n </v-card-title>\n\n <v-card-text class=\"pa-2\">\n <v-row dense>\n <!-- Supply Queue (new + review, rank-ordered) -->\n <v-col cols=\"12\" md=\"8\">\n <div class=\"debug-section\">\n <div class=\"debug-header\">\n <v-icon size=\"x-small\" class=\"mr-1\">mdi-sort</v-icon>\n <strong>Supply Queue</strong>\n </div>\n <div class=\"debug-stats\">\n <span class=\"text-caption\">Length: {{ debugInfo.supplyQueue.length }}</span>\n <span class=\"text-caption ml-2\">Dequeued: {{ debugInfo.supplyQueue.dequeueCount }}</span>\n </div>\n <div v-if=\"debugInfo.supplyQueue.items.length > 0\" class=\"debug-items\">\n <div\n v-for=\"(item, idx) in debugInfo.supplyQueue.items.slice(0, 8)\"\n :key=\"idx\"\n class=\"debug-item\"\n >\n <span class=\"text-caption\">{{ idx }}: {{ item.courseID }}::{{ item.cardID }}</span>\n <span class=\"text-caption text-grey ml-1\">({{ item.status }})</span>\n <span class=\"text-caption ml-1\" style=\"color:#90caf9\">{{ fmtScore(item.score) }}</span>\n </div>\n <div v-if=\"debugInfo.supplyQueue.items.length > 8\" class=\"text-caption text-grey\">\n ... +{{ debugInfo.supplyQueue.items.length - 8 }} more\n </div>\n </div>\n <div v-else class=\"text-caption text-grey\">\n (empty)\n </div>\n </div>\n </v-col>\n\n <!-- Failed Cards Queue -->\n <v-col cols=\"12\" md=\"4\">\n <div class=\"debug-section\">\n <div class=\"debug-header\">\n <v-icon size=\"x-small\" class=\"mr-1\">mdi-alert-circle</v-icon>\n <strong>Failed Cards Queue</strong>\n </div>\n <div class=\"debug-stats\">\n <span class=\"text-caption\">Length: {{ debugInfo.failedQueue.length }}</span>\n <span class=\"text-caption ml-2\">Dequeued: {{ debugInfo.failedQueue.dequeueCount }}</span>\n </div>\n <div v-if=\"debugInfo.failedQueue.items.length > 0\" class=\"debug-items\">\n <div\n v-for=\"(item, idx) in debugInfo.failedQueue.items.slice(0, 5)\"\n :key=\"idx\"\n class=\"debug-item\"\n >\n <span class=\"text-caption\">{{ idx }}: {{ item.courseID }}::{{ item.cardID }}</span>\n <span class=\"text-caption text-grey ml-1\">({{ item.status }})</span>\n </div>\n <div v-if=\"debugInfo.failedQueue.items.length > 5\" class=\"text-caption text-grey\">\n ... +{{ debugInfo.failedQueue.items.length - 5 }} more\n </div>\n </div>\n <div v-else class=\"text-caption text-grey\">\n (empty)\n </div>\n </div>\n </v-col>\n </v-row>\n\n <!-- Hydrated Cards Cache -->\n <v-row dense>\n <v-col cols=\"12\">\n <v-divider class=\"my-2\"></v-divider>\n <div class=\"debug-section\">\n <div class=\"debug-header\">\n <v-icon size=\"x-small\" class=\"mr-1\">mdi-database</v-icon>\n <strong>Hydrated Cards Cache</strong>\n </div>\n <div class=\"debug-stats\">\n <span class=\"text-caption\">Cached: {{ debugInfo.hydratedCache.count }}</span>\n <span class=\"text-caption ml-2\">Failed Cache: {{ debugInfo.hydratedCache.failedCacheSize }}</span>\n </div>\n <div v-if=\"debugInfo.hydratedCache.items.length > 0\" class=\"debug-items\">\n <div\n v-for=\"(item, idx) in debugInfo.hydratedCache.items.slice(0, 8)\"\n :key=\"idx\"\n class=\"debug-item d-inline-block mr-3\"\n >\n <span class=\"text-caption\">{{ item.courseID }}::{{ item.cardID }}</span>\n </div>\n <div v-if=\"debugInfo.hydratedCache.items.length > 8\" class=\"text-caption text-grey\">\n ... +{{ debugInfo.hydratedCache.items.length - 8 }} more\n </div>\n </div>\n <div v-else class=\"text-caption text-grey\">\n (empty)\n </div>\n </div>\n </v-col>\n </v-row>\n </v-card-text>\n </v-card>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType, computed, ref, onMounted, onUnmounted } from 'vue';\nimport { SessionController } from '@vue-skuilder/db';\n\ninterface QueueDebugInfo {\n length: number;\n dequeueCount: number;\n items: Array<{ courseID: string; cardID: string; status: string; score?: number }>;\n}\n\ninterface HydratedCacheInfo {\n count: number;\n failedCacheSize: number;\n items: Array<{ courseID: string; cardID: string }>;\n}\n\nexport interface SessionDebugInfo {\n supplyQueue: QueueDebugInfo;\n failedQueue: QueueDebugInfo;\n hydratedCache: HydratedCacheInfo;\n}\n\nexport default defineComponent({\n name: 'SessionControllerDebug',\n\n props: {\n sessionController: {\n type: Object as PropType<SessionController<any> | null>,\n required: true,\n },\n },\n\n setup(props) {\n const refreshTrigger = ref(0);\n let pollInterval: NodeJS.Timeout | null = null;\n\n onMounted(() => {\n // Poll every 500ms to update debug display\n pollInterval = setInterval(() => {\n refreshTrigger.value++;\n }, 500);\n });\n\n onUnmounted(() => {\n if (pollInterval) {\n clearInterval(pollInterval);\n }\n });\n\n const debugInfo = computed((): SessionDebugInfo => {\n // Create dependency on refreshTrigger to force updates\n refreshTrigger.value;\n\n if (!props.sessionController) {\n return {\n supplyQueue: { length: 0, dequeueCount: 0, items: [] },\n failedQueue: { length: 0, dequeueCount: 0, items: [] },\n hydratedCache: { count: 0, failedCacheSize: 0, items: [] },\n };\n }\n\n return props.sessionController.getDebugInfo();\n });\n\n /** Format a rank score: finite → 2dp, `+INF` → REQ (required), missing → ''. */\n const fmtScore = (score?: number): string => {\n if (score === undefined) return '';\n if (!Number.isFinite(score)) return 'REQ';\n return score.toFixed(2);\n };\n\n return {\n debugInfo,\n fmtScore,\n };\n },\n});\n</script>\n\n<style scoped>\n.session-debug {\n font-family: 'Courier New', monospace;\n font-size: 0.75rem;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.debug-section {\n padding: 8px;\n background-color: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n min-height: 120px;\n}\n\n.debug-header {\n display: flex;\n align-items: center;\n margin-bottom: 4px;\n padding-bottom: 4px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n}\n\n.debug-stats {\n margin-bottom: 8px;\n display: flex;\n gap: 8px;\n}\n\n.debug-items {\n margin-top: 4px;\n padding-left: 8px;\n}\n\n.debug-item {\n padding: 2px 0;\n border-left: 2px solid rgba(255, 255, 255, 0.2);\n padding-left: 6px;\n margin-bottom: 2px;\n}\n</style>\n"],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import { computed as e, defineComponent as t, onMounted as n, onUnmounted as r, ref as i } from "vue";
3
+ //#region src/components/SessionControllerDebug.vue?vue&type=script&lang.ts
4
+ var a = t({
5
+ name: "SessionControllerDebug",
6
+ props: { sessionController: {
7
+ type: Object,
8
+ required: !0
9
+ } },
10
+ setup(t) {
11
+ let a = i(0), o = null;
12
+ n(() => {
13
+ o = setInterval(() => {
14
+ a.value++;
15
+ }, 500);
16
+ }), r(() => {
17
+ o && clearInterval(o);
18
+ });
19
+ let s = e(() => (a.value, t.sessionController ? t.sessionController.getDebugInfo() : {
20
+ supplyQueue: {
21
+ length: 0,
22
+ dequeueCount: 0,
23
+ items: []
24
+ },
25
+ failedQueue: {
26
+ length: 0,
27
+ dequeueCount: 0,
28
+ items: []
29
+ },
30
+ hydratedCache: {
31
+ count: 0,
32
+ failedCacheSize: 0,
33
+ items: []
34
+ }
35
+ })), fmtScore = (e) => e === void 0 ? "" : Number.isFinite(e) ? e.toFixed(2) : "REQ";
36
+ return {
37
+ debugInfo: s,
38
+ fmtScore
39
+ };
40
+ }
41
+ });
42
+ //#endregion
43
+ export { a as default };
44
+
45
+ //# sourceMappingURL=SessionControllerDebug.vue_vue_type_script_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionControllerDebug.vue_vue_type_script_lang.mjs","names":[],"sources":["../../src/components/SessionControllerDebug.vue"],"sourcesContent":["<template>\n <v-card v-if=\"sessionController\" class=\"session-debug ma-2\" elevation=\"2\">\n <v-card-title class=\"text-caption bg-grey-darken-3\">\n Session Controller Debug\n <v-spacer></v-spacer>\n <v-icon size=\"small\">mdi-bug</v-icon>\n </v-card-title>\n\n <v-card-text class=\"pa-2\">\n <v-row dense>\n <!-- Supply Queue (new + review, rank-ordered) -->\n <v-col cols=\"12\" md=\"8\">\n <div class=\"debug-section\">\n <div class=\"debug-header\">\n <v-icon size=\"x-small\" class=\"mr-1\">mdi-sort</v-icon>\n <strong>Supply Queue</strong>\n </div>\n <div class=\"debug-stats\">\n <span class=\"text-caption\">Length: {{ debugInfo.supplyQueue.length }}</span>\n <span class=\"text-caption ml-2\">Dequeued: {{ debugInfo.supplyQueue.dequeueCount }}</span>\n </div>\n <div v-if=\"debugInfo.supplyQueue.items.length > 0\" class=\"debug-items\">\n <div\n v-for=\"(item, idx) in debugInfo.supplyQueue.items.slice(0, 8)\"\n :key=\"idx\"\n class=\"debug-item\"\n >\n <span class=\"text-caption\">{{ idx }}: {{ item.courseID }}::{{ item.cardID }}</span>\n <span class=\"text-caption text-grey ml-1\">({{ item.status }})</span>\n <span class=\"text-caption ml-1\" style=\"color:#90caf9\">{{ fmtScore(item.score) }}</span>\n </div>\n <div v-if=\"debugInfo.supplyQueue.items.length > 8\" class=\"text-caption text-grey\">\n ... +{{ debugInfo.supplyQueue.items.length - 8 }} more\n </div>\n </div>\n <div v-else class=\"text-caption text-grey\">\n (empty)\n </div>\n </div>\n </v-col>\n\n <!-- Failed Cards Queue -->\n <v-col cols=\"12\" md=\"4\">\n <div class=\"debug-section\">\n <div class=\"debug-header\">\n <v-icon size=\"x-small\" class=\"mr-1\">mdi-alert-circle</v-icon>\n <strong>Failed Cards Queue</strong>\n </div>\n <div class=\"debug-stats\">\n <span class=\"text-caption\">Length: {{ debugInfo.failedQueue.length }}</span>\n <span class=\"text-caption ml-2\">Dequeued: {{ debugInfo.failedQueue.dequeueCount }}</span>\n </div>\n <div v-if=\"debugInfo.failedQueue.items.length > 0\" class=\"debug-items\">\n <div\n v-for=\"(item, idx) in debugInfo.failedQueue.items.slice(0, 5)\"\n :key=\"idx\"\n class=\"debug-item\"\n >\n <span class=\"text-caption\">{{ idx }}: {{ item.courseID }}::{{ item.cardID }}</span>\n <span class=\"text-caption text-grey ml-1\">({{ item.status }})</span>\n </div>\n <div v-if=\"debugInfo.failedQueue.items.length > 5\" class=\"text-caption text-grey\">\n ... +{{ debugInfo.failedQueue.items.length - 5 }} more\n </div>\n </div>\n <div v-else class=\"text-caption text-grey\">\n (empty)\n </div>\n </div>\n </v-col>\n </v-row>\n\n <!-- Hydrated Cards Cache -->\n <v-row dense>\n <v-col cols=\"12\">\n <v-divider class=\"my-2\"></v-divider>\n <div class=\"debug-section\">\n <div class=\"debug-header\">\n <v-icon size=\"x-small\" class=\"mr-1\">mdi-database</v-icon>\n <strong>Hydrated Cards Cache</strong>\n </div>\n <div class=\"debug-stats\">\n <span class=\"text-caption\">Cached: {{ debugInfo.hydratedCache.count }}</span>\n <span class=\"text-caption ml-2\">Failed Cache: {{ debugInfo.hydratedCache.failedCacheSize }}</span>\n </div>\n <div v-if=\"debugInfo.hydratedCache.items.length > 0\" class=\"debug-items\">\n <div\n v-for=\"(item, idx) in debugInfo.hydratedCache.items.slice(0, 8)\"\n :key=\"idx\"\n class=\"debug-item d-inline-block mr-3\"\n >\n <span class=\"text-caption\">{{ item.courseID }}::{{ item.cardID }}</span>\n </div>\n <div v-if=\"debugInfo.hydratedCache.items.length > 8\" class=\"text-caption text-grey\">\n ... +{{ debugInfo.hydratedCache.items.length - 8 }} more\n </div>\n </div>\n <div v-else class=\"text-caption text-grey\">\n (empty)\n </div>\n </div>\n </v-col>\n </v-row>\n </v-card-text>\n </v-card>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType, computed, ref, onMounted, onUnmounted } from 'vue';\nimport { SessionController } from '@vue-skuilder/db';\n\ninterface QueueDebugInfo {\n length: number;\n dequeueCount: number;\n items: Array<{ courseID: string; cardID: string; status: string; score?: number }>;\n}\n\ninterface HydratedCacheInfo {\n count: number;\n failedCacheSize: number;\n items: Array<{ courseID: string; cardID: string }>;\n}\n\nexport interface SessionDebugInfo {\n supplyQueue: QueueDebugInfo;\n failedQueue: QueueDebugInfo;\n hydratedCache: HydratedCacheInfo;\n}\n\nexport default defineComponent({\n name: 'SessionControllerDebug',\n\n props: {\n sessionController: {\n type: Object as PropType<SessionController<any> | null>,\n required: true,\n },\n },\n\n setup(props) {\n const refreshTrigger = ref(0);\n let pollInterval: NodeJS.Timeout | null = null;\n\n onMounted(() => {\n // Poll every 500ms to update debug display\n pollInterval = setInterval(() => {\n refreshTrigger.value++;\n }, 500);\n });\n\n onUnmounted(() => {\n if (pollInterval) {\n clearInterval(pollInterval);\n }\n });\n\n const debugInfo = computed((): SessionDebugInfo => {\n // Create dependency on refreshTrigger to force updates\n refreshTrigger.value;\n\n if (!props.sessionController) {\n return {\n supplyQueue: { length: 0, dequeueCount: 0, items: [] },\n failedQueue: { length: 0, dequeueCount: 0, items: [] },\n hydratedCache: { count: 0, failedCacheSize: 0, items: [] },\n };\n }\n\n return props.sessionController.getDebugInfo();\n });\n\n /** Format a rank score: finite → 2dp, `+INF` → REQ (required), missing → ''. */\n const fmtScore = (score?: number): string => {\n if (score === undefined) return '';\n if (!Number.isFinite(score)) return 'REQ';\n return score.toFixed(2);\n };\n\n return {\n debugInfo,\n fmtScore,\n };\n },\n});\n</script>\n\n<style scoped>\n.session-debug {\n font-family: 'Courier New', monospace;\n font-size: 0.75rem;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.debug-section {\n padding: 8px;\n background-color: rgba(255, 255, 255, 0.05);\n border-radius: 4px;\n min-height: 120px;\n}\n\n.debug-header {\n display: flex;\n align-items: center;\n margin-bottom: 4px;\n padding-bottom: 4px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n}\n\n.debug-stats {\n margin-bottom: 8px;\n display: flex;\n gap: 8px;\n}\n\n.debug-items {\n margin-top: 4px;\n padding-left: 8px;\n}\n\n.debug-item {\n padding: 2px 0;\n border-left: 2px solid rgba(255, 255, 255, 0.2);\n padding-left: 6px;\n margin-bottom: 2px;\n}\n</style>\n"],"mappings":";;;AAiIA,IAAA,IAAe,EAAgB;CAC7B,MAAM;CAEN,OAAO,EACL,mBAAmB;EACjB,MAAM;EACN,UAAU;EACX,EACF;CAED,MAAM,GAAO;EACX,IAAM,IAAiB,EAAI,EAAE,EACzB,IAAsC;AAS1C,EAPA,QAAgB;AAEd,OAAe,kBAAkB;AAC/B,MAAe;MACd,IAAI;IACP,EAEF,QAAkB;AAChB,GAAI,KACF,cAAc,EAAa;IAE7B;EAEF,IAAM,IAAY,SAEhB,EAAe,OAEV,EAAM,oBAQJ,EAAM,kBAAkB,cAAc,GAPpC;GACL,aAAa;IAAE,QAAQ;IAAG,cAAc;IAAG,OAAO,EAAC;IAAG;GACtD,aAAa;IAAE,QAAQ;IAAG,cAAc;IAAG,OAAO,EAAC;IAAG;GACtD,eAAe;IAAE,OAAO;IAAG,iBAAiB;IAAG,OAAO,EAAC;IAAG;GAC3D,EAIH,EAGI,YAAY,MACZ,MAAU,KAAA,IAAkB,KAC3B,OAAO,SAAS,EAAM,GACpB,EAAM,QAAQ,EAAE,GADa;AAItC,SAAO;GACL;GACA;GACD;;CAEJ,CAAC"}
@@ -0,0 +1,66 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import e from "../_virtual/_plugin-vue_export-helper.mjs";
3
+ import t from "./SkMouseTrap.vue_vue_type_script_lang.mjs";
4
+ import { Fragment as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createTextVNode as s, createVNode as c, mergeProps as l, openBlock as u, renderList as d, resolveComponent as f, toDisplayString as p, withCtx as m } from "vue";
5
+ //#region src/components/SkMouseTrap.vue
6
+ var h = { class: "text-caption ml-2" };
7
+ function _sfc_render(e, t, g, _, v, y) {
8
+ let b = f("v-icon"), x = f("v-btn"), S = f("v-toolbar-title"), C = f("v-toolbar"), w = f("v-spacer"), T = f("v-list-item"), E = f("v-list"), D = f("v-card"), O = f("v-dialog");
9
+ return e.display ? (u(), r(O, {
10
+ key: 0,
11
+ "max-width": "500px",
12
+ transition: "dialog-transition"
13
+ }, {
14
+ activator: m(({ props: e }) => [c(x, l({
15
+ icon: "",
16
+ color: "primary"
17
+ }, e), {
18
+ default: m(() => [c(b, null, {
19
+ default: m(() => t[0] || (t[0] = [s("mdi-keyboard")])),
20
+ _: 1
21
+ })]),
22
+ _: 2
23
+ }, 1040)]),
24
+ default: m(() => [c(D, null, {
25
+ default: m(() => [c(C, {
26
+ color: "secondary",
27
+ dark: "",
28
+ dense: ""
29
+ }, {
30
+ default: m(() => [c(S, { class: "text-subtitle-1" }, {
31
+ default: m(() => t[1] || (t[1] = [s("Shortcut keys:")])),
32
+ _: 1
33
+ })]),
34
+ _: 1
35
+ }), c(E, { dense: "" }, {
36
+ default: m(() => [(u(!0), a(n, null, d(e.commands, (e) => (u(), r(T, {
37
+ key: Array.isArray(e.hotkey) ? e.hotkey.join(",") : e.hotkey,
38
+ class: "py-1"
39
+ }, {
40
+ default: m(() => [
41
+ c(x, {
42
+ variant: "outlined",
43
+ color: "primary",
44
+ class: "text-white",
45
+ size: "small"
46
+ }, {
47
+ default: m(() => [s(p(Array.isArray(e.hotkey) ? e.hotkey[0] : e.hotkey), 1)]),
48
+ _: 2
49
+ }, 1024),
50
+ c(w),
51
+ o("span", h, p(e.command), 1)
52
+ ]),
53
+ _: 2
54
+ }, 1024))), 128))]),
55
+ _: 1
56
+ })]),
57
+ _: 1
58
+ })]),
59
+ _: 1
60
+ })) : i("", !0);
61
+ }
62
+ var g = /* @__PURE__ */ e(t, [["render", _sfc_render]]);
63
+ //#endregion
64
+ export { g as default };
65
+
66
+ //# sourceMappingURL=SkMouseTrap.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkMouseTrap.mjs","names":[],"sources":["../../src/components/SkMouseTrap.vue"],"sourcesContent":["<template>\n <v-dialog v-if=\"display\" max-width=\"500px\" transition=\"dialog-transition\">\n <template #activator=\"{ props }\">\n <v-btn icon color=\"primary\" v-bind=\"props\">\n <v-icon>mdi-keyboard</v-icon>\n </v-btn>\n </template>\n\n <v-card>\n <v-toolbar color=\"secondary\" dark dense>\n <v-toolbar-title class=\"text-subtitle-1\">Shortcut keys:</v-toolbar-title>\n </v-toolbar>\n <v-list dense>\n <v-list-item\n v-for=\"hk in commands\"\n :key=\"Array.isArray(hk.hotkey) ? hk.hotkey.join(',') : hk.hotkey\"\n class=\"py-1\"\n >\n <v-btn variant=\"outlined\" color=\"primary\" class=\"text-white\" size=\"small\">\n {{ Array.isArray(hk.hotkey) ? hk.hotkey[0] : hk.hotkey }}\n </v-btn>\n <v-spacer></v-spacer>\n <span class=\"text-caption ml-2\">{{ hk.command }}</span>\n </v-list-item>\n </v-list>\n </v-card>\n </v-dialog>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport { SkldrMouseTrap, HotKeyMetaData } from '../utils/SkldrMouseTrap';\nimport { SkMouseTrapProps } from './SkMouseTrap.types';\n\nexport default defineComponent({\n name: 'SkMouseTrap',\n\n props: {\n refreshInterval: {\n type: Number as PropType<SkMouseTrapProps['refreshInterval']>,\n default: 500,\n },\n },\n\n data() {\n return {\n commands: [] as HotKeyMetaData[],\n display: false,\n intervalId: null as number | null,\n };\n },\n\n created() {\n this.intervalId = window.setInterval(this.refreshState, this.refreshInterval);\n },\n\n beforeUnmount() {\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n }\n },\n\n methods: {\n refreshState() {\n this.commands = SkldrMouseTrap.commands;\n this.display = this.commands.length > 0;\n },\n },\n});\n</script>\n"],"mappings":";;;;;UAsBgB,OAAM,qBAAmB;;;QArBvB,EAAA,WAAA,GAAA,EAAhB,EAyBW,GAAA;EA1Bb,KAAA;EAC2B,aAAU;EAAQ,YAAW;;EACzC,WAAS,GAGV,EAHc,eAAK,CAC3B,EAEQ,GAFR,EAEQ;GAFD,MAAA;GAAK,OAAM;KAAkB,EAAK,EAAA;GAH/C,SAAA,QAIqC,CAA7B,EAA6B,GAAA,MAAA;IAJrC,SAAA,QAI4B,EAAA,OAAA,EAAA,KAAA,CAJ5B,EAIgB,eAAY,CAAA,EAAA;IAJ5B,GAAA;;GAAA,GAAA;;EAAA,SAAA,QAyBa,CAjBT,EAiBS,GAAA,MAAA;GAzBb,SAAA,QAWkB,CAFZ,EAEY,GAAA;IAFD,OAAM;IAAY,MAAA;IAAK,OAAA;;IATxC,SAAA,QAUiF,CAAzE,EAAyE,GAAA,EAAxD,OAAM,mBAAiB,EAAA;KAVhD,SAAA,QAU+D,EAAA,OAAA,EAAA,KAAA,CAV/D,EAUiD,iBAAc,CAAA,EAAA;KAV/D,GAAA;;IAAA,GAAA;OAYM,EAYS,GAAA,EAZD,OAAA,IAAK,EAAA;IAZnB,SAAA,QAcgC,EAAA,EAAA,GAAA,EADxB,EAUc,GAAA,MAvBtB,EAcuB,EAAA,WAAN,YADT,EAUc,GAAA;KARX,KAAK,MAAM,QAAQ,EAAG,OAAM,GAAI,EAAG,OAAO,KAAI,IAAA,GAAQ,EAAG;KAC1D,OAAM;;KAhBhB,SAAA,QAoBkB;MAFR,EAEQ,GAAA;OAFD,SAAQ;OAAW,OAAM;OAAU,OAAM;OAAa,MAAK;;OAlB5E,SAAA,QAmBqE,CAnBrE,EAAA,EAmBe,MAAM,QAAQ,EAAG,OAAM,GAAI,EAAG,OAAM,KAAM,EAAG,OAAM,EAAA,EAAA,CAAA,CAAA;OAnBlE,GAAA;;MAqBU,EAAqB,EAAA;MACrB,EAAuD,QAAvD,GAAuD,EAApB,EAAG,QAAO,EAAA,EAAA;;KAtBvD,GAAA;;IAAA,GAAA;;GAAA,GAAA;;EAAA,GAAA;OAAA,EAAA,IAAA,GAAA"}
@@ -0,0 +1,31 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import { SkldrMouseTrap as e } from "../utils/SkldrMouseTrap.mjs";
3
+ import { defineComponent as t } from "vue";
4
+ //#region src/components/SkMouseTrap.vue?vue&type=script&lang.ts
5
+ var n = t({
6
+ name: "SkMouseTrap",
7
+ props: { refreshInterval: {
8
+ type: Number,
9
+ default: 500
10
+ } },
11
+ data() {
12
+ return {
13
+ commands: [],
14
+ display: !1,
15
+ intervalId: null
16
+ };
17
+ },
18
+ created() {
19
+ this.intervalId = window.setInterval(this.refreshState, this.refreshInterval);
20
+ },
21
+ beforeUnmount() {
22
+ this.intervalId !== null && clearInterval(this.intervalId);
23
+ },
24
+ methods: { refreshState() {
25
+ this.commands = e.commands, this.display = this.commands.length > 0;
26
+ } }
27
+ });
28
+ //#endregion
29
+ export { n as default };
30
+
31
+ //# sourceMappingURL=SkMouseTrap.vue_vue_type_script_lang.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkMouseTrap.vue_vue_type_script_lang.mjs","names":[],"sources":["../../src/components/SkMouseTrap.vue"],"sourcesContent":["<template>\n <v-dialog v-if=\"display\" max-width=\"500px\" transition=\"dialog-transition\">\n <template #activator=\"{ props }\">\n <v-btn icon color=\"primary\" v-bind=\"props\">\n <v-icon>mdi-keyboard</v-icon>\n </v-btn>\n </template>\n\n <v-card>\n <v-toolbar color=\"secondary\" dark dense>\n <v-toolbar-title class=\"text-subtitle-1\">Shortcut keys:</v-toolbar-title>\n </v-toolbar>\n <v-list dense>\n <v-list-item\n v-for=\"hk in commands\"\n :key=\"Array.isArray(hk.hotkey) ? hk.hotkey.join(',') : hk.hotkey\"\n class=\"py-1\"\n >\n <v-btn variant=\"outlined\" color=\"primary\" class=\"text-white\" size=\"small\">\n {{ Array.isArray(hk.hotkey) ? hk.hotkey[0] : hk.hotkey }}\n </v-btn>\n <v-spacer></v-spacer>\n <span class=\"text-caption ml-2\">{{ hk.command }}</span>\n </v-list-item>\n </v-list>\n </v-card>\n </v-dialog>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType } from 'vue';\nimport { SkldrMouseTrap, HotKeyMetaData } from '../utils/SkldrMouseTrap';\nimport { SkMouseTrapProps } from './SkMouseTrap.types';\n\nexport default defineComponent({\n name: 'SkMouseTrap',\n\n props: {\n refreshInterval: {\n type: Number as PropType<SkMouseTrapProps['refreshInterval']>,\n default: 500,\n },\n },\n\n data() {\n return {\n commands: [] as HotKeyMetaData[],\n display: false,\n intervalId: null as number | null,\n };\n },\n\n created() {\n this.intervalId = window.setInterval(this.refreshState, this.refreshInterval);\n },\n\n beforeUnmount() {\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n }\n },\n\n methods: {\n refreshState() {\n this.commands = SkldrMouseTrap.commands;\n this.display = this.commands.length > 0;\n },\n },\n});\n</script>\n"],"mappings":";;;;AAkCA,IAAA,IAAe,EAAgB;CAC7B,MAAM;CAEN,OAAO,EACL,iBAAiB;EACf,MAAM;EACN,SAAS;EACV,EACF;CAED,OAAO;AACL,SAAO;GACL,UAAU,EAAC;GACX,SAAS;GACT,YAAY;GACb;;CAGH,UAAU;AACR,OAAK,aAAa,OAAO,YAAY,KAAK,cAAc,KAAK,gBAAgB;;CAG/E,gBAAgB;AACd,EAAI,KAAK,eAAe,QACtB,cAAc,KAAK,WAAW;;CAIlC,SAAS,EACP,eAAe;AAEb,EADA,KAAK,WAAW,EAAe,UAC/B,KAAK,UAAU,KAAK,SAAS,SAAS;IAEzC;CACF,CAAC"}
@@ -0,0 +1,28 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import e from "../_virtual/_plugin-vue_export-helper.mjs";
3
+ import t from "./SkMouseTrapToolTip.vue_vue_type_script_lang.mjs";
4
+ /* empty css */
5
+ import { Transition as n, createCommentVNode as r, createElementBlock as i, createVNode as a, normalizeClass as o, openBlock as s, renderSlot as c, toDisplayString as l, withCtx as u } from "vue";
6
+ //#region src/components/SkMouseTrapToolTip.vue
7
+ function _sfc_render(e, t, d, f, p, m) {
8
+ return s(), i("div", {
9
+ class: o(["sk-mousetrap-tooltip-wrapper", [e.isControlKeyPressed && !e.disabled && e.highlightEffect !== "none" ? `sk-mousetrap-highlight-${e.highlightEffect}` : ""]]),
10
+ ref: "wrapperElement"
11
+ }, [c(e.$slots, "default", {}, void 0, !0), a(n, { name: "fade" }, {
12
+ default: u(() => [e.showTooltip && e.isControlKeyPressed && !e.disabled ? (s(), i("div", {
13
+ key: 0,
14
+ class: o(["sk-mousetrap-tooltip", {
15
+ "sk-mt-tooltip-top": e.position === "top",
16
+ "sk-mt-tooltip-bottom": e.position === "bottom",
17
+ "sk-mt-tooltip-left": e.position === "left",
18
+ "sk-mt-tooltip-right": e.position === "right"
19
+ }])
20
+ }, l(e.formattedHotkey), 3)) : r("", !0)]),
21
+ _: 1
22
+ })], 2);
23
+ }
24
+ var d = /* @__PURE__ */ e(t, [["render", _sfc_render], ["__scopeId", "data-v-5d6fb09c"]]);
25
+ //#endregion
26
+ export { d as default };
27
+
28
+ //# sourceMappingURL=SkMouseTrapToolTip.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkMouseTrapToolTip.mjs","names":[],"sources":["../../src/components/SkMouseTrapToolTip.vue"],"sourcesContent":["<template>\n <div\n class=\"sk-mousetrap-tooltip-wrapper\"\n ref=\"wrapperElement\"\n :class=\"[\n isControlKeyPressed && !disabled && highlightEffect !== 'none' ? `sk-mousetrap-highlight-${highlightEffect}` : '',\n ]\"\n >\n <slot></slot>\n <transition name=\"fade\">\n <div\n v-if=\"showTooltip && isControlKeyPressed && !disabled\"\n class=\"sk-mousetrap-tooltip\"\n :class=\"{\n 'sk-mt-tooltip-top': position === 'top',\n 'sk-mt-tooltip-bottom': position === 'bottom',\n 'sk-mt-tooltip-left': position === 'left',\n 'sk-mt-tooltip-right': position === 'right',\n }\"\n >\n {{ formattedHotkey }}\n </div>\n </transition>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType, ref, onMounted, onBeforeUnmount, computed, watch } from 'vue';\nimport { SkldrMouseTrap, HotKeyMetaData } from '../utils/SkldrMouseTrap';\n\nexport default defineComponent({\n name: 'SkMouseTrapToolTip',\n\n props: {\n hotkey: {\n type: [String, Array] as PropType<string | string[]>,\n required: true,\n },\n command: {\n type: String,\n required: true,\n },\n disabled: {\n type: Boolean,\n default: false,\n },\n position: {\n type: String as PropType<'top' | 'bottom' | 'left' | 'right'>,\n default: 'top',\n },\n showTooltip: {\n type: Boolean,\n default: true,\n },\n highlightEffect: {\n type: String as PropType<'glow' | 'scale' | 'border' | 'none'>,\n default: 'glow',\n },\n },\n\n emits: ['hotkey-triggered'],\n\n setup(props, { emit }) {\n const wrapperElement = ref<HTMLElement | null>(null);\n const isControlKeyPressed = ref(false);\n const hotkeyId = ref(`hotkey-${Math.random().toString(36).substring(2, 15)}`);\n\n // Format hotkey for display\n const formattedHotkey = computed(() => {\n const hotkey = Array.isArray(props.hotkey) ? props.hotkey[0] : props.hotkey;\n // Check if this is a sequence (has spaces) or a combination (has +)\n if (hotkey.includes(' ')) {\n // For sequences like \"g h\", display as \"g, h\"\n return hotkey\n .toLowerCase()\n .split(' ')\n .map((part) => part.charAt(0) + part.slice(1))\n .join(', ');\n } else {\n // For combinations like \"ctrl+s\", display as \"Ctrl + S\"\n return hotkey\n .toLowerCase()\n .split('+')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' + ');\n }\n });\n\n // Apply highlight effect to the actual button/control when Ctrl is pressed\n watch(\n () => isControlKeyPressed.value,\n (pressed) => {\n if (!wrapperElement.value || props.disabled) return;\n\n const clickableElement = wrapperElement.value.querySelector(\n 'button, a, input[type=\"button\"], [role=\"button\"]'\n ) as HTMLElement;\n\n if (clickableElement) {\n clickableElement.style.transition = 'all 250ms ease';\n\n if (pressed && props.highlightEffect !== 'none') {\n // Add slight brightness increase to the inner element\n clickableElement.style.filter = 'brightness(1.1)';\n } else {\n clickableElement.style.filter = '';\n }\n }\n }\n );\n\n // Handle Ctrl key detection\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Control') {\n isControlKeyPressed.value = true;\n }\n };\n\n const handleKeyUp = (e: KeyboardEvent) => {\n if (e.key === 'Control') {\n isControlKeyPressed.value = false;\n }\n };\n\n // Handle clicking the element when hotkey is pressed\n const handleHotkeyPress = () => {\n if (props.disabled || !wrapperElement.value) return;\n\n // Try finding a clickable element within our wrapper\n let clickableElement = wrapperElement.value.querySelector(\n 'button, a, input[type=\"button\"], [role=\"button\"]'\n ) as HTMLElement;\n\n // If no standard clickable element found, try to find navigation or list items\n if (!clickableElement) {\n clickableElement = wrapperElement.value.querySelector(\n 'v-list-item, .v-list-item, router-link, .router-link, a, [to]'\n ) as HTMLElement;\n }\n\n // If still no element found, try the wrapper itself - it might be clickable\n if (\n !clickableElement &&\n (wrapperElement.value.hasAttribute('to') ||\n wrapperElement.value.tagName === 'A' ||\n wrapperElement.value.classList.contains('v-list-item'))\n ) {\n clickableElement = wrapperElement.value;\n }\n\n // Get closest parent list item or router link if we found a title/content element\n if (!clickableElement) {\n const closestClickableParent = wrapperElement.value.closest('v-list-item, .v-list-item, a, [to]');\n if (closestClickableParent) {\n clickableElement = closestClickableParent as HTMLElement;\n }\n }\n\n if (clickableElement) {\n if (clickableElement.hasAttribute('to')) {\n // Handle router-link style navigation\n const routePath = clickableElement.getAttribute('to');\n if (routePath && window.location.pathname !== routePath) {\n // Use parent router if available (Vue component)\n const router = (window as any).$nuxt?.$router || (window as any).$router;\n if (router && typeof router.push === 'function') {\n router.push(routePath);\n } else {\n // Fallback to regular navigation\n window.location.pathname = routePath;\n }\n }\n emit('hotkey-triggered', props.hotkey);\n } else {\n // Regular click for standard elements\n clickableElement.click();\n emit('hotkey-triggered', props.hotkey);\n }\n } else {\n // If no clickable element found, emit the event for parent handling\n console.log('No clickable element found for hotkey', props.hotkey);\n emit('hotkey-triggered', props.hotkey);\n }\n };\n\n // Register/unregister the hotkey binding\n const registerHotkey = () => {\n if (!props.disabled) {\n SkldrMouseTrap.addBinding({\n hotkey: props.hotkey,\n command: props.command,\n callback: handleHotkeyPress,\n });\n }\n };\n\n const unregisterHotkey = () => {\n if (!props.disabled) {\n SkldrMouseTrap.removeBinding(props.hotkey);\n }\n };\n\n // Watch for changes to the disabled prop\n watch(\n () => props.disabled,\n (newValue) => {\n if (newValue) {\n unregisterHotkey();\n } else {\n registerHotkey();\n }\n }\n );\n\n onMounted(() => {\n // Register global keyboard listeners for the Ctrl key\n document.addEventListener('keydown', handleKeyDown);\n document.addEventListener('keyup', handleKeyUp);\n\n // Register the hotkey\n registerHotkey();\n });\n\n onBeforeUnmount(() => {\n // Clean up event listeners\n document.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('keyup', handleKeyUp);\n\n // Unregister the hotkey\n unregisterHotkey();\n });\n\n return {\n wrapperElement,\n isControlKeyPressed,\n formattedHotkey,\n };\n },\n});\n</script>\n\n<style scoped>\n.sk-mousetrap-tooltip-wrapper {\n display: inline-block;\n position: relative;\n}\n\n.sk-mousetrap-tooltip {\n position: absolute;\n background-color: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 12px;\n white-space: nowrap;\n pointer-events: none;\n z-index: 9999;\n}\n\n.sk-mt-tooltip-top {\n bottom: 100%;\n margin-bottom: 5px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.sk-mt-tooltip-bottom {\n top: 100%;\n margin-top: 5px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.sk-mt-tooltip-left {\n right: 100%;\n margin-right: 5px;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.sk-mt-tooltip-right {\n left: 100%;\n margin-left: 5px;\n top: 50%;\n transform: translateY(-50%);\n}\n\n/* Highlight effects when Ctrl is pressed */\n.sk-mousetrap-highlight-glow {\n box-shadow: 0 0 8px 2px rgba(25, 118, 210, 0.6);\n transition: box-shadow 250ms ease;\n}\n\n.sk-mousetrap-highlight-scale {\n transform: scale(1.03);\n transition: transform 250ms ease;\n}\n\n.sk-mousetrap-highlight-border {\n outline: 2px solid rgba(25, 118, 210, 0.8);\n outline-offset: 2px;\n border-radius: 4px;\n transition: outline 250ms ease, outline-offset 250ms ease;\n}\n\n/* Fade transition */\n.fade-enter-active,\n.fade-leave-active {\n transition: opacity 250ms ease;\n}\n\n.fade-enter-from,\n.fade-leave-to {\n opacity: 0;\n}\n</style>\n"],"mappings":";;;;;;;aACE,EAsBM,OAAA;EArBJ,OAFJ,EAAA,CAEU,gCAA8B,CAEpB,EAAA,uBAAmB,CAAK,EAAA,YAAY,EAAA,oBAAe,SAAA,0BAAwC,EAAA,oBAAe,GAAA,CAAA,CAAA;EAD1H,KAAI;KAKJ,EAAa,EAAA,QAAA,WAAA,EAAA,EAAA,KAAA,GAAA,GAAA,EACb,EAaa,GAAA,EAbD,MAAK,QAAM,EAAA;EAT3B,SAAA,QAqBY,CAVE,EAAA,eAAe,EAAA,uBAAmB,CAAK,EAAA,YAAA,GAAA,EAD/C,EAWM,OAAA;GArBZ,KAAA;GAYQ,OAZR,EAAA,CAYc,wBAAsB;yBACa,EAAA,aAAQ;4BAA8C,EAAA,aAAQ;0BAA+C,EAAA,aAAQ;2BAA8C,EAAA,aAAQ;;OAOjN,EAAA,gBAAe,EAAA,EAAA,IApB1B,EAAA,IAAA,GAAA,CAAA,CAAA;EAAA,GAAA"}
@@ -0,0 +1,91 @@
1
+ import "../_virtual/_rolldown/runtime.mjs";
2
+ import { SkldrMouseTrap as e } from "../utils/SkldrMouseTrap.mjs";
3
+ import { computed as t, defineComponent as n, onBeforeUnmount as r, onMounted as i, ref as a, watch as o } from "vue";
4
+ //#region src/components/SkMouseTrapToolTip.vue?vue&type=script&lang.ts
5
+ var s = n({
6
+ name: "SkMouseTrapToolTip",
7
+ props: {
8
+ hotkey: {
9
+ type: [String, Array],
10
+ required: !0
11
+ },
12
+ command: {
13
+ type: String,
14
+ required: !0
15
+ },
16
+ disabled: {
17
+ type: Boolean,
18
+ default: !1
19
+ },
20
+ position: {
21
+ type: String,
22
+ default: "top"
23
+ },
24
+ showTooltip: {
25
+ type: Boolean,
26
+ default: !0
27
+ },
28
+ highlightEffect: {
29
+ type: String,
30
+ default: "glow"
31
+ }
32
+ },
33
+ emits: ["hotkey-triggered"],
34
+ setup(n, { emit: s }) {
35
+ let c = a(null), l = a(!1);
36
+ a(`hotkey-${Math.random().toString(36).substring(2, 15)}`);
37
+ let u = t(() => {
38
+ let e = Array.isArray(n.hotkey) ? n.hotkey[0] : n.hotkey;
39
+ return e.includes(" ") ? e.toLowerCase().split(" ").map((e) => e.charAt(0) + e.slice(1)).join(", ") : e.toLowerCase().split("+").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" + ");
40
+ });
41
+ o(() => l.value, (e) => {
42
+ if (!c.value || n.disabled) return;
43
+ let t = c.value.querySelector("button, a, input[type=\"button\"], [role=\"button\"]");
44
+ t && (t.style.transition = "all 250ms ease", e && n.highlightEffect !== "none" ? t.style.filter = "brightness(1.1)" : t.style.filter = "");
45
+ });
46
+ let handleKeyDown = (e) => {
47
+ e.key === "Control" && (l.value = !0);
48
+ }, handleKeyUp = (e) => {
49
+ e.key === "Control" && (l.value = !1);
50
+ }, handleHotkeyPress = () => {
51
+ if (n.disabled || !c.value) return;
52
+ let e = c.value.querySelector("button, a, input[type=\"button\"], [role=\"button\"]");
53
+ if (e || (e = c.value.querySelector("v-list-item, .v-list-item, router-link, .router-link, a, [to]")), !e && (c.value.hasAttribute("to") || c.value.tagName === "A" || c.value.classList.contains("v-list-item")) && (e = c.value), !e) {
54
+ let t = c.value.closest("v-list-item, .v-list-item, a, [to]");
55
+ t && (e = t);
56
+ }
57
+ if (e) if (e.hasAttribute("to")) {
58
+ let t = e.getAttribute("to");
59
+ if (t && window.location.pathname !== t) {
60
+ let e = window.$nuxt?.$router || window.$router;
61
+ e && typeof e.push == "function" ? e.push(t) : window.location.pathname = t;
62
+ }
63
+ s("hotkey-triggered", n.hotkey);
64
+ } else e.click(), s("hotkey-triggered", n.hotkey);
65
+ else console.log("No clickable element found for hotkey", n.hotkey), s("hotkey-triggered", n.hotkey);
66
+ }, registerHotkey = () => {
67
+ n.disabled || e.addBinding({
68
+ hotkey: n.hotkey,
69
+ command: n.command,
70
+ callback: handleHotkeyPress
71
+ });
72
+ }, unregisterHotkey = () => {
73
+ n.disabled || e.removeBinding(n.hotkey);
74
+ };
75
+ return o(() => n.disabled, (e) => {
76
+ e ? unregisterHotkey() : registerHotkey();
77
+ }), i(() => {
78
+ document.addEventListener("keydown", handleKeyDown), document.addEventListener("keyup", handleKeyUp), registerHotkey();
79
+ }), r(() => {
80
+ document.removeEventListener("keydown", handleKeyDown), document.removeEventListener("keyup", handleKeyUp), unregisterHotkey();
81
+ }), {
82
+ wrapperElement: c,
83
+ isControlKeyPressed: l,
84
+ formattedHotkey: u
85
+ };
86
+ }
87
+ });
88
+ //#endregion
89
+ export { s as default };
90
+
91
+ //# sourceMappingURL=SkMouseTrapToolTip.vue_vue_type_script_lang.mjs.map