@hydralms/components 0.1.3 → 0.3.0

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 (344) hide show
  1. package/dist/StudentProfile-BVfZMbnV.cjs +1 -0
  2. package/dist/StudentProfile-DeMxdrL3.js +3275 -0
  3. package/dist/assessment-toolbar/assessment-toolbar.d.ts +1 -1
  4. package/dist/assessment-toolbar/index.d.ts +5 -1
  5. package/dist/assessment-toolbar/question-header-bar.d.ts +2 -0
  6. package/dist/assessment-toolbar/question-materials-drawer.d.ts +2 -0
  7. package/dist/assessment-toolbar/question-navigator.d.ts +1 -1
  8. package/dist/assessment-toolbar/timer-display.d.ts +1 -1
  9. package/dist/assessment-toolbar/types.d.ts +52 -4
  10. package/dist/assessment-toolbar/use-countdown.d.ts +43 -0
  11. package/dist/common/index.d.ts +3 -1
  12. package/dist/common/pagination.d.ts +26 -0
  13. package/dist/common/stepper.d.ts +6 -0
  14. package/dist/common/types.d.ts +38 -0
  15. package/dist/components.css +1 -1
  16. package/dist/content/attachment-list.d.ts +6 -0
  17. package/dist/content/audio-player.d.ts +22 -0
  18. package/dist/content/code-block.d.ts +30 -0
  19. package/dist/content/content-block.d.ts +1 -1
  20. package/dist/content/embed-block.d.ts +28 -0
  21. package/dist/content/index.d.ts +8 -1
  22. package/dist/content/types.d.ts +63 -0
  23. package/dist/curriculum/course-card.d.ts +51 -0
  24. package/dist/curriculum/curriculum-item.d.ts +1 -1
  25. package/dist/curriculum/index.d.ts +2 -0
  26. package/dist/curriculum/types.d.ts +2 -2
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +597 -308
  30. package/dist/license/HydraContext.d.ts +16 -0
  31. package/dist/license/ProBadge.d.ts +6 -0
  32. package/dist/license/index.d.ts +7 -0
  33. package/dist/license/tiers.d.ts +3 -0
  34. package/dist/license/useHydraLicense.d.ts +6 -0
  35. package/dist/license/validate.d.ts +13 -0
  36. package/dist/license/withProGate.d.ts +6 -0
  37. package/dist/modules/AssignmentModule/AssignmentModule.d.ts +5 -0
  38. package/dist/modules/AssignmentModule/types.d.ts +69 -0
  39. package/dist/modules/CertificateModule/CertificateModule.d.ts +5 -0
  40. package/dist/modules/CertificateModule/types.d.ts +51 -0
  41. package/dist/modules/CourseCatalogModule/CourseCatalogModule.d.ts +5 -0
  42. package/dist/modules/CourseCatalogModule/types.d.ts +43 -0
  43. package/dist/modules/CoursePlayer/CoursePlayer.d.ts +4 -1
  44. package/dist/modules/DiscussionModule/DiscussionModule.d.ts +5 -0
  45. package/dist/modules/DiscussionModule/types.d.ts +47 -0
  46. package/dist/modules/ExamModule/ExamModule.d.ts +5 -0
  47. package/dist/modules/ExamModule/types.d.ts +55 -0
  48. package/dist/modules/FlashcardLab/FlashcardLab.d.ts +4 -1
  49. package/dist/modules/FlashcardLab/types.d.ts +2 -0
  50. package/dist/modules/GradeCenterModule/GradeCenterModule.d.ts +5 -0
  51. package/dist/modules/GradeCenterModule/types.d.ts +56 -0
  52. package/dist/modules/QuizModule/QuizModule.d.ts +4 -1
  53. package/dist/modules/QuizModule/types.d.ts +10 -14
  54. package/dist/modules/StudentDashboardModule/StudentDashboardModule.d.ts +5 -0
  55. package/dist/modules/StudentDashboardModule/types.d.ts +54 -0
  56. package/dist/modules/StudentProfileModule/StudentProfileModule.d.ts +5 -0
  57. package/dist/modules/StudentProfileModule/types.d.ts +43 -0
  58. package/dist/modules/SurveyModule/SurveyModule.d.ts +5 -0
  59. package/dist/modules/SurveyModule/types.d.ts +51 -0
  60. package/dist/modules/_shared/assessment-intro.d.ts +16 -0
  61. package/dist/modules/_shared/assessment-results.d.ts +23 -0
  62. package/dist/modules/_shared/types.d.ts +10 -0
  63. package/dist/modules/_shared/use-timer.d.ts +9 -0
  64. package/dist/modules/index.d.ts +18 -0
  65. package/dist/modules.cjs +1 -0
  66. package/dist/modules.js +1834 -0
  67. package/dist/progress/achievement-badge.d.ts +6 -0
  68. package/dist/progress/activity-timeline.d.ts +6 -0
  69. package/dist/progress/index.d.ts +4 -1
  70. package/dist/progress/stat-card.d.ts +1 -1
  71. package/dist/progress/streak-badge.d.ts +6 -0
  72. package/dist/progress/types.d.ts +99 -0
  73. package/dist/provider/HydraProvider.d.ts +5 -1
  74. package/dist/questions/choice.d.ts +1 -1
  75. package/dist/questions/confidence-indicator.d.ts +37 -0
  76. package/dist/questions/essay.d.ts +2 -2
  77. package/dist/questions/fill-in-the-blank.d.ts +1 -1
  78. package/dist/questions/hotspot.d.ts +21 -0
  79. package/dist/questions/index.d.ts +11 -1
  80. package/dist/questions/inline-choice.d.ts +21 -0
  81. package/dist/questions/matching.d.ts +22 -0
  82. package/dist/questions/multiple-choice.d.ts +1 -1
  83. package/dist/questions/numeric.d.ts +11 -0
  84. package/dist/questions/ordering.d.ts +12 -0
  85. package/dist/questions/question-renderer.d.ts +1 -1
  86. package/dist/questions/scenario.d.ts +23 -0
  87. package/dist/questions/scoring.d.ts +22 -0
  88. package/dist/questions/spreadsheet.d.ts +29 -0
  89. package/dist/questions/true-false.d.ts +1 -1
  90. package/dist/questions/types.d.ts +106 -1
  91. package/dist/questions/use-drag-reorder.d.ts +17 -0
  92. package/dist/sections/AnnouncementFeed/AnnouncementFeed.d.ts +1 -1
  93. package/dist/sections/AnnouncementFeed/types.d.ts +15 -1
  94. package/dist/sections/AssessmentReview/AssessmentReview.d.ts +1 -1
  95. package/dist/sections/AssessmentReview/types.d.ts +6 -0
  96. package/dist/sections/AssignmentSubmission/AssignmentSubmission.d.ts +1 -1
  97. package/dist/sections/AssignmentSubmission/types.d.ts +6 -0
  98. package/dist/sections/CertificateViewer/CertificateViewer.d.ts +1 -1
  99. package/dist/sections/CertificateViewer/certificate-variants.d.ts +42 -0
  100. package/dist/sections/CertificateViewer/types.d.ts +13 -5
  101. package/dist/sections/CourseCatalog/CourseCatalog.d.ts +2 -0
  102. package/dist/sections/CourseCatalog/types.d.ts +80 -0
  103. package/dist/sections/CourseOutline/CourseOutline.d.ts +1 -1
  104. package/dist/sections/CourseOutline/types.d.ts +6 -0
  105. package/dist/sections/DiscussionThread/DiscussionThread.d.ts +1 -1
  106. package/dist/sections/DiscussionThread/types.d.ts +6 -0
  107. package/dist/sections/EnrollmentWizard/EnrollmentWizard.d.ts +2 -0
  108. package/dist/sections/EnrollmentWizard/types.d.ts +66 -0
  109. package/dist/sections/ExamSession/ExamSession.d.ts +1 -1
  110. package/dist/sections/ExamSession/types.d.ts +12 -1
  111. package/dist/sections/FlashcardStudySession/FlashcardStudySession.d.ts +1 -1
  112. package/dist/sections/FlashcardStudySession/types.d.ts +6 -0
  113. package/dist/sections/ForumBoard/ForumBoard.d.ts +8 -0
  114. package/dist/sections/ForumBoard/types.d.ts +78 -0
  115. package/dist/sections/GradebookTable/GradebookTable.d.ts +1 -1
  116. package/dist/sections/GradebookTable/types.d.ts +14 -0
  117. package/dist/sections/LecturePlayer/LecturePlayer.d.ts +1 -1
  118. package/dist/sections/LecturePlayer/types.d.ts +8 -0
  119. package/dist/sections/LessonPage/LessonPage.d.ts +1 -1
  120. package/dist/sections/LessonPage/types.d.ts +6 -0
  121. package/dist/sections/PracticeQuiz/PracticeQuiz.d.ts +1 -1
  122. package/dist/sections/PracticeQuiz/types.d.ts +6 -0
  123. package/dist/sections/ProgressDashboard/ProgressDashboard.d.ts +1 -1
  124. package/dist/sections/ProgressDashboard/types.d.ts +6 -0
  125. package/dist/sections/QuizSession/QuizSession.d.ts +1 -1
  126. package/dist/sections/QuizSession/types.d.ts +12 -1
  127. package/dist/sections/RequirementsChecklist/RequirementsChecklist.d.ts +8 -0
  128. package/dist/sections/RequirementsChecklist/types.d.ts +43 -0
  129. package/dist/sections/ResourceLibrary/ResourceLibrary.d.ts +1 -1
  130. package/dist/sections/ResourceLibrary/types.d.ts +15 -1
  131. package/dist/sections/RubricView/RubricView.d.ts +9 -0
  132. package/dist/sections/RubricView/types.d.ts +56 -0
  133. package/dist/sections/ScrollableQuiz/ScrollableQuiz.d.ts +1 -1
  134. package/dist/sections/ScrollableQuiz/types.d.ts +6 -0
  135. package/dist/sections/StudentProfile/StudentProfile.d.ts +2 -0
  136. package/dist/sections/StudentProfile/types.d.ts +98 -0
  137. package/dist/sections/SurveyForm/SurveyForm.d.ts +1 -1
  138. package/dist/sections/SurveyForm/types.d.ts +6 -0
  139. package/dist/sections/_shared/merge-answers.d.ts +9 -0
  140. package/dist/sections/_shared/section-shell.d.ts +20 -0
  141. package/dist/sections/_shared/use-assessment-session.d.ts +30 -0
  142. package/dist/sections/index.d.ts +13 -1
  143. package/dist/sections.cjs +1 -1
  144. package/dist/sections.js +282 -1786
  145. package/dist/social/post-card.d.ts +1 -1
  146. package/dist/tabs-BsfVo2Bl.cjs +173 -0
  147. package/dist/tabs-BuY1iNJE.js +22305 -0
  148. package/dist/ui/alert.d.ts +1 -1
  149. package/dist/ui/badge.d.ts +1 -1
  150. package/dist/ui/button.d.ts +1 -1
  151. package/dist/ui/drawer.d.ts +84 -0
  152. package/dist/ui/index.d.ts +5 -0
  153. package/dist/ui/progress.d.ts +1 -1
  154. package/dist/ui/rich-text-editor.d.ts +32 -0
  155. package/dist/ui/rich-text-toolbar.d.ts +8 -0
  156. package/dist/ui/toast.d.ts +43 -0
  157. package/dist/utils/array-utils.d.ts +4 -0
  158. package/dist/utils/debounce.d.ts +5 -1
  159. package/dist/utils/flatten-leaves.d.ts +6 -0
  160. package/dist/utils/format-file-size.d.ts +1 -0
  161. package/dist/utils/format-timestamp.d.ts +1 -0
  162. package/dist/utils/is-empty-html.d.ts +5 -0
  163. package/dist/utils/pick-palette-color.d.ts +19 -0
  164. package/dist/utils/shuffle.d.ts +1 -0
  165. package/dist/utils/string-utils.d.ts +12 -0
  166. package/dist/video/types.d.ts +15 -0
  167. package/dist/video/video-bookmark.d.ts +1 -1
  168. package/dist/video/video-player.d.ts +1 -1
  169. package/dist/video/video-playlist-item.d.ts +1 -1
  170. package/dist/withProGate-BWqcKdPM.js +137 -0
  171. package/dist/withProGate-DX6XqKLp.cjs +1 -0
  172. package/package.json +40 -137
  173. package/src/assessment-toolbar/assessment-toolbar.tsx +54 -49
  174. package/src/assessment-toolbar/index.ts +6 -0
  175. package/src/assessment-toolbar/question-header-bar.tsx +61 -0
  176. package/src/assessment-toolbar/question-materials-drawer.tsx +55 -0
  177. package/src/assessment-toolbar/question-navigator.tsx +13 -36
  178. package/src/assessment-toolbar/timer-display.tsx +6 -5
  179. package/src/assessment-toolbar/types.ts +54 -4
  180. package/src/assessment-toolbar/use-countdown.ts +153 -0
  181. package/src/common/empty-state.tsx +1 -0
  182. package/src/common/index.ts +5 -0
  183. package/src/common/pagination.tsx +135 -0
  184. package/src/common/search-input.tsx +8 -6
  185. package/src/common/stepper.tsx +100 -0
  186. package/src/common/types.ts +41 -0
  187. package/src/content/attachment-list.tsx +92 -0
  188. package/src/content/audio-player.tsx +196 -0
  189. package/src/content/code-block.tsx +113 -0
  190. package/src/content/content-block.tsx +68 -2
  191. package/src/content/embed-block.tsx +78 -0
  192. package/src/content/file-upload-zone.tsx +11 -6
  193. package/src/content/index.ts +9 -0
  194. package/src/content/types.ts +46 -0
  195. package/src/curriculum/course-card.tsx +199 -0
  196. package/src/curriculum/curriculum-item.tsx +9 -5
  197. package/src/curriculum/curriculum-tree.tsx +20 -13
  198. package/src/curriculum/index.ts +2 -0
  199. package/src/curriculum/types.ts +2 -2
  200. package/src/feedback/feedback-banner.tsx +12 -14
  201. package/src/flashcards/flashcard-deck.tsx +1 -9
  202. package/src/flashcards/flashcard.tsx +29 -9
  203. package/src/index.ts +3 -0
  204. package/src/license/HydraContext.tsx +62 -0
  205. package/src/license/ProBadge.tsx +43 -0
  206. package/src/license/index.ts +7 -0
  207. package/src/license/tiers.ts +24 -0
  208. package/src/license/useHydraLicense.ts +10 -0
  209. package/src/license/validate.ts +90 -0
  210. package/src/license/withProGate.tsx +21 -0
  211. package/src/modules/AssignmentModule/AssignmentModule.tsx +314 -0
  212. package/src/modules/AssignmentModule/types.ts +77 -0
  213. package/src/modules/CertificateModule/CertificateModule.tsx +173 -0
  214. package/src/modules/CertificateModule/types.ts +49 -0
  215. package/src/modules/CourseCatalogModule/CourseCatalogModule.tsx +126 -0
  216. package/src/modules/CourseCatalogModule/types.ts +47 -0
  217. package/src/modules/CoursePlayer/CoursePlayer.tsx +80 -69
  218. package/src/modules/DiscussionModule/DiscussionModule.tsx +145 -0
  219. package/src/modules/DiscussionModule/types.ts +54 -0
  220. package/src/modules/ExamModule/ExamModule.tsx +151 -0
  221. package/src/modules/ExamModule/types.ts +57 -0
  222. package/src/modules/FlashcardLab/FlashcardLab.tsx +39 -21
  223. package/src/modules/FlashcardLab/types.ts +2 -0
  224. package/src/modules/GradeCenterModule/GradeCenterModule.tsx +174 -0
  225. package/src/modules/GradeCenterModule/types.ts +65 -0
  226. package/src/modules/QuizModule/QuizModule.tsx +58 -178
  227. package/src/modules/QuizModule/types.ts +10 -15
  228. package/src/modules/StudentDashboardModule/StudentDashboardModule.tsx +117 -0
  229. package/src/modules/StudentDashboardModule/types.ts +56 -0
  230. package/src/modules/StudentProfileModule/StudentProfileModule.tsx +289 -0
  231. package/src/modules/StudentProfileModule/types.ts +45 -0
  232. package/src/modules/SurveyModule/SurveyModule.tsx +185 -0
  233. package/src/modules/SurveyModule/types.ts +53 -0
  234. package/src/modules/_shared/assessment-intro.tsx +75 -0
  235. package/src/modules/_shared/assessment-results.tsx +133 -0
  236. package/src/modules/_shared/types.ts +11 -0
  237. package/src/modules/_shared/use-timer.ts +49 -0
  238. package/src/modules/index.ts +33 -0
  239. package/src/progress/achievement-badge.tsx +52 -0
  240. package/src/progress/activity-timeline.tsx +84 -0
  241. package/src/progress/grade-indicator.tsx +9 -1
  242. package/src/progress/index.ts +7 -0
  243. package/src/progress/progress-ring.tsx +2 -1
  244. package/src/progress/stat-card.tsx +37 -18
  245. package/src/progress/streak-badge.tsx +35 -0
  246. package/src/progress/types.ts +103 -0
  247. package/src/provider/HydraProvider.tsx +15 -6
  248. package/src/questions/choice.tsx +19 -14
  249. package/src/questions/confidence-indicator.tsx +107 -0
  250. package/src/questions/essay.tsx +28 -28
  251. package/src/questions/fill-in-the-blank.tsx +20 -19
  252. package/src/questions/hotspot.tsx +154 -0
  253. package/src/questions/index.ts +18 -0
  254. package/src/questions/inline-choice.tsx +152 -0
  255. package/src/questions/matching.tsx +229 -0
  256. package/src/questions/multiple-choice.tsx +19 -14
  257. package/src/questions/numeric.tsx +106 -0
  258. package/src/questions/ordering.tsx +167 -0
  259. package/src/questions/question-renderer.tsx +24 -2
  260. package/src/questions/scenario.tsx +140 -0
  261. package/src/questions/scoring.ts +201 -0
  262. package/src/questions/spreadsheet.tsx +260 -0
  263. package/src/questions/true-false.tsx +19 -14
  264. package/src/questions/types.ts +123 -1
  265. package/src/questions/use-drag-reorder.ts +80 -0
  266. package/src/sections/AnnouncementFeed/AnnouncementFeed.tsx +66 -23
  267. package/src/sections/AnnouncementFeed/types.ts +15 -1
  268. package/src/sections/AssessmentReview/AssessmentReview.tsx +50 -2
  269. package/src/sections/AssessmentReview/types.ts +6 -0
  270. package/src/sections/AssignmentSubmission/AssignmentSubmission.tsx +44 -6
  271. package/src/sections/AssignmentSubmission/types.ts +6 -0
  272. package/src/sections/CertificateViewer/CertificateViewer.tsx +215 -60
  273. package/src/sections/CertificateViewer/certificate-variants.tsx +170 -0
  274. package/src/sections/CertificateViewer/types.ts +19 -5
  275. package/src/sections/CourseCatalog/CourseCatalog.tsx +220 -0
  276. package/src/sections/CourseCatalog/types.ts +76 -0
  277. package/src/sections/CourseOutline/CourseOutline.tsx +45 -14
  278. package/src/sections/CourseOutline/types.ts +6 -0
  279. package/src/sections/DiscussionThread/DiscussionThread.tsx +55 -11
  280. package/src/sections/DiscussionThread/types.ts +6 -0
  281. package/src/sections/EnrollmentWizard/EnrollmentWizard.tsx +343 -0
  282. package/src/sections/EnrollmentWizard/types.ts +65 -0
  283. package/src/sections/ExamSession/ExamSession.tsx +125 -82
  284. package/src/sections/ExamSession/types.ts +12 -1
  285. package/src/sections/FlashcardStudySession/FlashcardStudySession.tsx +53 -36
  286. package/src/sections/FlashcardStudySession/types.ts +6 -0
  287. package/src/sections/ForumBoard/ForumBoard.tsx +342 -0
  288. package/src/sections/ForumBoard/types.ts +81 -0
  289. package/src/sections/GradebookTable/GradebookTable.tsx +55 -2
  290. package/src/sections/GradebookTable/types.ts +14 -0
  291. package/src/sections/LecturePlayer/LecturePlayer.tsx +63 -37
  292. package/src/sections/LecturePlayer/types.ts +8 -0
  293. package/src/sections/LessonPage/LessonPage.tsx +40 -13
  294. package/src/sections/LessonPage/types.ts +6 -0
  295. package/src/sections/PracticeQuiz/PracticeQuiz.tsx +119 -98
  296. package/src/sections/PracticeQuiz/types.ts +6 -0
  297. package/src/sections/ProgressDashboard/ProgressDashboard.tsx +121 -67
  298. package/src/sections/ProgressDashboard/types.ts +6 -0
  299. package/src/sections/QuizSession/QuizSession.tsx +115 -67
  300. package/src/sections/QuizSession/types.ts +12 -1
  301. package/src/sections/RequirementsChecklist/RequirementsChecklist.tsx +147 -0
  302. package/src/sections/RequirementsChecklist/types.ts +44 -0
  303. package/src/sections/ResourceLibrary/ResourceLibrary.tsx +68 -17
  304. package/src/sections/ResourceLibrary/types.ts +15 -1
  305. package/src/sections/RubricView/RubricView.tsx +174 -0
  306. package/src/sections/RubricView/types.ts +58 -0
  307. package/src/sections/ScrollableQuiz/ScrollableQuiz.tsx +58 -23
  308. package/src/sections/ScrollableQuiz/types.ts +6 -0
  309. package/src/sections/StudentProfile/StudentProfile.tsx +279 -0
  310. package/src/sections/StudentProfile/types.ts +99 -0
  311. package/src/sections/SurveyForm/SurveyForm.tsx +40 -10
  312. package/src/sections/SurveyForm/types.ts +6 -0
  313. package/src/sections/_shared/merge-answers.ts +22 -0
  314. package/src/sections/_shared/section-shell.tsx +64 -0
  315. package/src/sections/_shared/use-assessment-session.ts +125 -0
  316. package/src/sections/index.ts +42 -1
  317. package/src/social/post-card.tsx +8 -19
  318. package/src/social/user-avatar.tsx +10 -5
  319. package/src/styles/globals.css +52 -41
  320. package/src/ui/badge.tsx +8 -0
  321. package/src/ui/drawer.tsx +600 -0
  322. package/src/ui/index.ts +21 -0
  323. package/src/ui/progress.tsx +4 -0
  324. package/src/ui/rich-text-editor.tsx +119 -0
  325. package/src/ui/rich-text-toolbar.tsx +157 -0
  326. package/src/ui/toast.tsx +170 -0
  327. package/src/utils/array-utils.ts +17 -0
  328. package/src/utils/debounce.ts +8 -2
  329. package/src/utils/flatten-leaves.ts +17 -0
  330. package/src/utils/format-file-size.ts +5 -0
  331. package/src/utils/format-timestamp.ts +13 -0
  332. package/src/utils/is-empty-html.ts +7 -0
  333. package/src/utils/pick-palette-color.ts +33 -0
  334. package/src/utils/shuffle.ts +8 -0
  335. package/src/utils/string-utils.ts +30 -0
  336. package/src/video/types.ts +16 -0
  337. package/src/video/video-bookmark.tsx +4 -3
  338. package/src/video/video-chapter-list.tsx +9 -4
  339. package/src/video/video-player.tsx +24 -5
  340. package/src/video/video-playlist-item.tsx +8 -3
  341. package/src/video/video-thumbnail-card.tsx +4 -0
  342. package/src/video/video-transcript.tsx +8 -5
  343. package/dist/table-BrS5cDQu.js +0 -2510
  344. package/dist/table-D6AkBBEo.cjs +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydralms/components",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "React component library for LMS platforms",
5
5
  "license": "MIT",
6
6
  "author": "HydraLMS",
@@ -26,9 +26,9 @@
26
26
  "course"
27
27
  ],
28
28
  "type": "module",
29
- "main": "./src/index.ts",
30
- "module": "./src/index.ts",
31
- "types": "./src/index.ts",
29
+ "main": "./dist/index.cjs",
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
32
  "files": [
33
33
  "src",
34
34
  "dist",
@@ -40,96 +40,32 @@
40
40
  ],
41
41
  "exports": {
42
42
  ".": {
43
- "types": "./src/index.ts",
44
- "default": "./src/index.ts"
43
+ "types": "./dist/index.d.ts",
44
+ "import": "./dist/index.js",
45
+ "require": "./dist/index.cjs"
45
46
  },
46
47
  "./sections": {
47
- "types": "./src/sections/index.ts",
48
- "default": "./src/sections/index.ts"
48
+ "types": "./dist/sections/index.d.ts",
49
+ "import": "./dist/sections.js",
50
+ "require": "./dist/sections.cjs"
49
51
  },
50
- "./sections/QuizSession": {
51
- "types": "./src/sections/QuizSession/QuizSession.tsx",
52
- "default": "./src/sections/QuizSession/QuizSession.tsx"
53
- },
54
- "./sections/LecturePlayer": {
55
- "types": "./src/sections/LecturePlayer/LecturePlayer.tsx",
56
- "default": "./src/sections/LecturePlayer/LecturePlayer.tsx"
57
- },
58
- "./sections/FlashcardStudySession": {
59
- "types": "./src/sections/FlashcardStudySession/FlashcardStudySession.tsx",
60
- "default": "./src/sections/FlashcardStudySession/FlashcardStudySession.tsx"
61
- },
62
- "./sections/AssessmentReview": {
63
- "types": "./src/sections/AssessmentReview/AssessmentReview.tsx",
64
- "default": "./src/sections/AssessmentReview/AssessmentReview.tsx"
65
- },
66
- "./sections/CourseOutline": {
67
- "types": "./src/sections/CourseOutline/CourseOutline.tsx",
68
- "default": "./src/sections/CourseOutline/CourseOutline.tsx"
69
- },
70
- "./sections/ScrollableQuiz": {
71
- "types": "./src/sections/ScrollableQuiz/ScrollableQuiz.tsx",
72
- "default": "./src/sections/ScrollableQuiz/ScrollableQuiz.tsx"
73
- },
74
- "./sections/PracticeQuiz": {
75
- "types": "./src/sections/PracticeQuiz/PracticeQuiz.tsx",
76
- "default": "./src/sections/PracticeQuiz/PracticeQuiz.tsx"
77
- },
78
- "./sections/ExamSession": {
79
- "types": "./src/sections/ExamSession/ExamSession.tsx",
80
- "default": "./src/sections/ExamSession/ExamSession.tsx"
81
- },
82
- "./sections/SurveyForm": {
83
- "types": "./src/sections/SurveyForm/SurveyForm.tsx",
84
- "default": "./src/sections/SurveyForm/SurveyForm.tsx"
85
- },
86
- "./sections/LessonPage": {
87
- "types": "./src/sections/LessonPage/LessonPage.tsx",
88
- "default": "./src/sections/LessonPage/LessonPage.tsx"
89
- },
90
- "./sections/ResourceLibrary": {
91
- "types": "./src/sections/ResourceLibrary/ResourceLibrary.tsx",
92
- "default": "./src/sections/ResourceLibrary/ResourceLibrary.tsx"
93
- },
94
- "./sections/AnnouncementFeed": {
95
- "types": "./src/sections/AnnouncementFeed/AnnouncementFeed.tsx",
96
- "default": "./src/sections/AnnouncementFeed/AnnouncementFeed.tsx"
97
- },
98
- "./sections/DiscussionThread": {
99
- "types": "./src/sections/DiscussionThread/DiscussionThread.tsx",
100
- "default": "./src/sections/DiscussionThread/DiscussionThread.tsx"
101
- },
102
- "./sections/AssignmentSubmission": {
103
- "types": "./src/sections/AssignmentSubmission/AssignmentSubmission.tsx",
104
- "default": "./src/sections/AssignmentSubmission/AssignmentSubmission.tsx"
105
- },
106
- "./sections/GradebookTable": {
107
- "types": "./src/sections/GradebookTable/GradebookTable.tsx",
108
- "default": "./src/sections/GradebookTable/GradebookTable.tsx"
109
- },
110
- "./sections/ProgressDashboard": {
111
- "types": "./src/sections/ProgressDashboard/ProgressDashboard.tsx",
112
- "default": "./src/sections/ProgressDashboard/ProgressDashboard.tsx"
113
- },
114
- "./sections/CertificateViewer": {
115
- "types": "./src/sections/CertificateViewer/CertificateViewer.tsx",
116
- "default": "./src/sections/CertificateViewer/CertificateViewer.tsx"
52
+ "./sections/*": {
53
+ "types": "./src/sections/*/index.ts",
54
+ "default": "./src/sections/*/index.ts"
117
55
  },
118
56
  "./modules": {
119
- "types": "./src/modules/index.ts",
120
- "default": "./src/modules/index.ts"
57
+ "types": "./dist/modules/index.d.ts",
58
+ "import": "./dist/modules.js",
59
+ "require": "./dist/modules.cjs"
121
60
  },
122
- "./modules/QuizModule": {
123
- "types": "./src/modules/QuizModule/QuizModule.tsx",
124
- "default": "./src/modules/QuizModule/QuizModule.tsx"
61
+ "./modules/*": {
62
+ "types": "./src/modules/*/index.ts",
63
+ "default": "./src/modules/*/index.ts"
125
64
  },
126
- "./modules/FlashcardLab": {
127
- "types": "./src/modules/FlashcardLab/FlashcardLab.tsx",
128
- "default": "./src/modules/FlashcardLab/FlashcardLab.tsx"
129
- },
130
- "./modules/CoursePlayer": {
131
- "types": "./src/modules/CoursePlayer/CoursePlayer.tsx",
132
- "default": "./src/modules/CoursePlayer/CoursePlayer.tsx"
65
+ "./license": {
66
+ "types": "./dist/license/index.d.ts",
67
+ "import": "./dist/license.js",
68
+ "require": "./dist/license.cjs"
133
69
  },
134
70
  "./provider": {
135
71
  "types": "./src/provider/index.ts",
@@ -171,63 +107,20 @@
171
107
  "types": "./src/social/index.ts",
172
108
  "default": "./src/social/index.ts"
173
109
  },
174
- "./ui/card": {
175
- "types": "./src/ui/card.tsx",
176
- "default": "./src/ui/card.tsx"
177
- },
178
- "./ui/progress": {
179
- "types": "./src/ui/progress.tsx",
180
- "default": "./src/ui/progress.tsx"
181
- },
182
- "./provider/HydraProvider": {
183
- "types": "./src/provider/HydraProvider.tsx",
184
- "default": "./src/provider/HydraProvider.tsx"
185
- },
186
- "./*": "./src/*",
187
- "./styles.css": "./src/styles/globals.css",
188
- "./styles/globals.css": "./src/styles/globals.css",
110
+ "./styles.css": "./dist/components.css",
189
111
  "./package.json": "./package.json"
190
112
  },
191
- "publishConfig": {
192
- "main": "./dist/index.cjs",
193
- "module": "./dist/index.js",
194
- "types": "./dist/index.d.ts",
195
- "exports": {
196
- ".": {
197
- "types": "./dist/index.d.ts",
198
- "import": "./dist/index.js",
199
- "require": "./dist/index.cjs"
200
- },
201
- "./sections": {
202
- "types": "./dist/sections/index.d.ts",
203
- "import": "./dist/sections.js",
204
- "require": "./dist/sections.cjs"
205
- },
206
- "./modules": {
207
- "types": "./dist/modules/index.d.ts",
208
- "import": "./dist/modules.js",
209
- "require": "./dist/modules.cjs"
210
- },
211
- "./styles.css": "./dist/components.css",
212
- "./package.json": "./package.json"
213
- }
214
- },
215
- "scripts": {
216
- "build": "tsc -b && vite build",
217
- "dev": "vite build --watch",
218
- "generate-docs": "tsx scripts/generate-docs.ts",
219
- "check-docs": "tsx scripts/generate-docs.ts --check",
220
- "typecheck": "tsc --noEmit",
221
- "test": "vitest run",
222
- "test:watch": "vitest",
223
- "prepublishOnly": "pnpm run build"
224
- },
225
113
  "peerDependencies": {
226
114
  "react": "^18.0.0 || ^19.0.0",
227
115
  "react-dom": "^18.0.0 || ^19.0.0",
228
116
  "tailwindcss": "^4.0.0"
229
117
  },
230
118
  "dependencies": {
119
+ "@tiptap/extension-link": "^3.20.1",
120
+ "@tiptap/extension-placeholder": "^3.20.1",
121
+ "@tiptap/extension-underline": "^3.20.1",
122
+ "@tiptap/react": "^3.20.1",
123
+ "@tiptap/starter-kit": "^3.20.1",
231
124
  "class-variance-authority": "^0.7.1",
232
125
  "clsx": "^2.1.1",
233
126
  "lucide-react": "^0.475.0",
@@ -244,11 +137,21 @@
244
137
  "jsdom": "^28.1.0",
245
138
  "react": "^19.0.0",
246
139
  "react-docgen-typescript": "^2.3.0",
140
+ "react-dom": "^19.0.0",
247
141
  "tailwindcss": "^4.0.0",
248
142
  "tsx": "^4.19.0",
249
143
  "typescript": "~5.7.0",
250
144
  "vite": "^6.0.0",
251
145
  "vite-plugin-dts": "^4.0.0",
252
146
  "vitest": "^4.0.18"
147
+ },
148
+ "scripts": {
149
+ "build": "vite build",
150
+ "dev": "vite build --watch",
151
+ "generate-docs": "tsx scripts/generate-docs.ts",
152
+ "check-docs": "tsx scripts/generate-docs.ts --check",
153
+ "typecheck": "tsc --noEmit",
154
+ "test": "vitest run",
155
+ "test:watch": "vitest"
253
156
  }
254
- }
157
+ }
@@ -2,6 +2,7 @@ import { ChevronLeft, ChevronRight, Send } from "lucide-react";
2
2
  import { TimerDisplay } from "./timer-display";
3
3
  import { QuestionNavigator } from "./question-navigator";
4
4
  import { Button } from "../ui/button";
5
+ import { cn } from "../lib/utils";
5
6
  import type { AssessmentToolbarProps } from "./types";
6
7
 
7
8
  export const AssessmentToolbar = ({
@@ -16,7 +17,6 @@ export const AssessmentToolbar = ({
16
17
  timeLimitSeconds,
17
18
  questions,
18
19
  onNavigateToQuestion,
19
- onToggleFlag,
20
20
  currentQuestionUid,
21
21
  isCompleted = false,
22
22
  isSubmitting = false,
@@ -27,70 +27,75 @@ export const AssessmentToolbar = ({
27
27
  const showNavigator = questions && questions.length > 0;
28
28
 
29
29
  return (
30
- <div className="rounded-lg border border-border overflow-hidden shadow-sm">
31
- {/* Header */}
32
- <div className="flex items-center justify-between px-4 py-2.5 bg-muted border-b border-border">
33
- <span className="text-sm font-medium text-foreground">
34
- Question{" "}
35
- <span className="font-bold">{currentQuestionIndex + 1}</span>
36
- {" "}of {totalQuestions}
37
- </span>
30
+ <div className="flex items-center gap-2 rounded-lg border border-border bg-muted px-2 py-1.5 shadow-sm">
31
+ {/* Previous */}
32
+ <Button
33
+ variant="ghost"
34
+ size="icon"
35
+ className="size-8 shrink-0 rounded-md"
36
+ disabled={!hasPrevious || readOnly}
37
+ onClick={onPrevious}
38
+ >
39
+ <ChevronLeft size={16} />
40
+ <span className="sr-only">Previous</span>
41
+ </Button>
38
42
 
39
- {showTimer && (
40
- <TimerDisplay
41
- timeElapsedSeconds={timeElapsedSeconds}
42
- timeLimitSeconds={timeLimitSeconds}
43
- />
44
- )}
45
- </div>
43
+ {/* Question indicator (shown when no navigator) */}
44
+ {!showNavigator && (
45
+ <span className="text-xs font-medium text-muted-foreground whitespace-nowrap">
46
+ <span className="font-bold text-foreground">{currentQuestionIndex + 1}</span>
47
+ <span className="mx-0.5">/</span>
48
+ {totalQuestions}
49
+ </span>
50
+ )}
46
51
 
47
- {/* Navigator */}
52
+ {/* Navigator chips */}
48
53
  {showNavigator && (
49
- <div className="px-4 py-3 border-b border-border">
54
+ <div className="min-w-0 flex-1 overflow-x-auto [scrollbar-width:none]">
50
55
  <QuestionNavigator
51
56
  questions={questions}
52
57
  currentQuestionUid={currentQuestionUid}
53
58
  onNavigate={onNavigateToQuestion}
54
- onToggleFlag={onToggleFlag}
55
59
  readOnly={readOnly}
56
60
  />
57
61
  </div>
58
62
  )}
59
63
 
60
- {/* Navigation buttons */}
61
- <div className="flex items-center justify-between gap-2 px-4 py-3">
64
+ {/* Spacer when no navigator */}
65
+ {!showNavigator && <div className="flex-1" />}
66
+
67
+ {/* Timer */}
68
+ {showTimer && (
69
+ <TimerDisplay
70
+ timeElapsedSeconds={timeElapsedSeconds}
71
+ timeLimitSeconds={timeLimitSeconds}
72
+ />
73
+ )}
74
+
75
+ {/* Next / Submit */}
76
+ {!hasNext || isCompleted ? (
62
77
  <Button
63
- variant="outline"
78
+ variant={isCompleted ? "secondary" : "default"}
64
79
  size="sm"
65
- className="rounded-lg"
66
- disabled={!hasPrevious || readOnly}
67
- onClick={onPrevious}
80
+ className={cn("shrink-0 rounded-md", isSubmitting && "gap-0")}
81
+ onClick={onSubmit}
82
+ disabled={readOnly || isSubmitting}
68
83
  >
69
- <ChevronLeft size={16} /> Previous
84
+ {isSubmitting ? "..." : isCompleted ? "Review" : "Submit"}
85
+ {!isSubmitting && <Send size={14} />}
70
86
  </Button>
71
-
72
- {!hasNext || isCompleted ? (
73
- <Button
74
- variant={isCompleted ? "secondary" : "default"}
75
- size="sm"
76
- className="rounded-lg"
77
- onClick={onSubmit}
78
- disabled={readOnly || isSubmitting}
79
- >
80
- {isSubmitting ? "Submitting..." : isCompleted ? "Review" : "Submit"}
81
- {!isSubmitting && <Send size={14} />}
82
- </Button>
83
- ) : (
84
- <Button
85
- size="sm"
86
- className="rounded-lg"
87
- disabled={!hasNext || readOnly}
88
- onClick={onNext}
89
- >
90
- Next <ChevronRight size={16} />
91
- </Button>
92
- )}
93
- </div>
87
+ ) : (
88
+ <Button
89
+ variant="ghost"
90
+ size="icon"
91
+ className="size-8 shrink-0 rounded-md"
92
+ disabled={!hasNext || readOnly}
93
+ onClick={onNext}
94
+ >
95
+ <ChevronRight size={16} />
96
+ <span className="sr-only">Next</span>
97
+ </Button>
98
+ )}
94
99
  </div>
95
100
  );
96
101
  };
@@ -1,10 +1,16 @@
1
1
  export { AssessmentToolbar } from "./assessment-toolbar";
2
2
  export { TimerDisplay } from "./timer-display";
3
3
  export { QuestionNavigator } from "./question-navigator";
4
+ export { QuestionHeaderBar } from "./question-header-bar";
5
+ export { QuestionMaterialsDrawer } from "./question-materials-drawer";
6
+ export { useCountdown } from "./use-countdown";
4
7
 
5
8
  export type {
6
9
  AssessmentToolbarProps,
7
10
  TimerDisplayProps,
8
11
  QuestionNavigatorProps,
9
12
  QuestionNavigatorItem,
13
+ QuestionHeaderBarProps,
14
+ QuestionMaterialsDrawerProps,
10
15
  } from "./types";
16
+ export type { UseCountdownOptions, UseCountdownReturn } from "./use-countdown";
@@ -0,0 +1,61 @@
1
+ import { BookOpen, Flag } from "lucide-react";
2
+ import { Button } from "../ui/button";
3
+ import { cn } from "../lib/utils";
4
+ import type { QuestionHeaderBarProps } from "./types";
5
+
6
+ export const QuestionHeaderBar = ({
7
+ questionNumber,
8
+ totalQuestions,
9
+ isFlagged,
10
+ onToggleFlag,
11
+ hasMaterials = false,
12
+ onOpenMaterials,
13
+ readOnly = false,
14
+ }: QuestionHeaderBarProps) => {
15
+ return (
16
+ <div className="flex items-center justify-between pb-3 border-b border-border">
17
+ <span className="text-sm font-semibold text-foreground">
18
+ Question {questionNumber}{" "}
19
+ <span className="font-normal text-muted-foreground">
20
+ of {totalQuestions}
21
+ </span>
22
+ </span>
23
+
24
+ {!readOnly && (
25
+ <div className="flex items-center gap-1">
26
+ {hasMaterials && onOpenMaterials && (
27
+ <Button
28
+ variant="ghost"
29
+ size="sm"
30
+ className="gap-1.5 text-muted-foreground hover:text-foreground"
31
+ onClick={onOpenMaterials}
32
+ >
33
+ <BookOpen size={14} />
34
+ Related Material
35
+ </Button>
36
+ )}
37
+
38
+ {onToggleFlag && (
39
+ <Button
40
+ variant="ghost"
41
+ size="icon"
42
+ className={cn(
43
+ "size-8",
44
+ isFlagged
45
+ ? "text-warning hover:text-warning/80"
46
+ : "text-muted-foreground hover:text-warning",
47
+ )}
48
+ onClick={onToggleFlag}
49
+ aria-label={isFlagged ? "Unflag question" : "Flag question"}
50
+ >
51
+ <Flag
52
+ size={14}
53
+ fill={isFlagged ? "currentColor" : "none"}
54
+ />
55
+ </Button>
56
+ )}
57
+ </div>
58
+ )}
59
+ </div>
60
+ );
61
+ };
@@ -0,0 +1,55 @@
1
+ import {
2
+ Drawer,
3
+ DrawerContent,
4
+ DrawerHeader,
5
+ DrawerTitle,
6
+ DrawerBody,
7
+ DrawerClose,
8
+ } from "../ui/drawer";
9
+ import { ContentBlock } from "../content";
10
+ import type { QuestionMaterialsDrawerProps } from "./types";
11
+
12
+ export const QuestionMaterialsDrawer = ({
13
+ open,
14
+ onOpenChange,
15
+ materials,
16
+ questionNumber,
17
+ }: QuestionMaterialsDrawerProps) => {
18
+ if (!materials.length) return null;
19
+
20
+ const drawerTitle = questionNumber
21
+ ? `Question ${questionNumber} — Related Material`
22
+ : "Related Material";
23
+
24
+ return (
25
+ <Drawer open={open} onOpenChange={onOpenChange} side="right">
26
+ <DrawerContent size="lg" scrollLock={false}>
27
+ <DrawerHeader className="flex-row items-center justify-between">
28
+ <DrawerTitle>{drawerTitle}</DrawerTitle>
29
+ <DrawerClose />
30
+ </DrawerHeader>
31
+ <DrawerBody>
32
+ <div className="space-y-6">
33
+ {materials.map((material, mi) => (
34
+ <section key={mi}>
35
+ {material.label && (
36
+ <h3 className="text-sm font-semibold text-foreground mb-3">
37
+ {material.label}
38
+ </h3>
39
+ )}
40
+ <div className="space-y-4">
41
+ {material.blocks.map((block, bi) => (
42
+ <ContentBlock key={bi} block={block} readOnly />
43
+ ))}
44
+ </div>
45
+ {mi < materials.length - 1 && (
46
+ <div className="border-b border-border mt-6" />
47
+ )}
48
+ </section>
49
+ ))}
50
+ </div>
51
+ </DrawerBody>
52
+ </DrawerContent>
53
+ </Drawer>
54
+ );
55
+ };
@@ -1,6 +1,5 @@
1
- import { Flag } from "lucide-react";
1
+ import { memo } from "react";
2
2
  import type { QuestionNavigatorProps } from "./types";
3
- import { Tooltip, TooltipTrigger, TooltipContent } from "../ui/tooltip";
4
3
  import { cn } from "../lib/utils";
5
4
 
6
5
  const CHIP_CLASSES = {
@@ -20,13 +19,12 @@ const getChipVariant = (
20
19
  return "default";
21
20
  };
22
21
 
23
- export const QuestionNavigator = ({
22
+ export const QuestionNavigator = memo(function QuestionNavigator({
24
23
  questions,
25
24
  currentQuestionUid,
26
25
  onNavigate,
27
- onToggleFlag,
28
26
  readOnly = false,
29
- }: QuestionNavigatorProps) => {
27
+ }: QuestionNavigatorProps) {
30
28
  const getTooltipContent = (q: (typeof questions)[0]): string => {
31
29
  const parts: string[] = [`Question ${q.sequence + 1}`];
32
30
  if (q.isFlagged) parts.push("Flagged");
@@ -36,51 +34,30 @@ export const QuestionNavigator = ({
36
34
  };
37
35
 
38
36
  return (
39
- <div className="flex flex-wrap gap-1.5">
37
+ <div className="flex gap-1">
40
38
  {questions.map((q) => {
41
39
  const variant = getChipVariant(q, currentQuestionUid);
42
40
  return (
43
- <div
41
+ <button
42
+ type="button"
44
43
  key={q.uid}
45
44
  title={getTooltipContent(q)}
45
+ aria-label={getTooltipContent(q)}
46
+ aria-current={q.uid === currentQuestionUid ? "step" : undefined}
46
47
  className={cn(
47
- "inline-flex items-center gap-1 px-2 py-1 rounded-md border transition-all duration-150",
48
+ "inline-flex items-center justify-center px-1.5 py-0.5 rounded border text-[11px] leading-tight transition-all duration-150 min-w-5.5",
48
49
  CHIP_CLASSES[variant],
49
50
  readOnly ? "cursor-default" : "cursor-pointer hover:shadow-sm hover:-translate-y-px",
50
51
  )}
51
52
  onClick={readOnly ? undefined : () => onNavigate?.(q.uid)}
53
+ disabled={readOnly}
52
54
  >
53
- <span className="text-xs font-semibold min-w-4 text-center">
55
+ <span className="font-semibold min-w-3.5 text-center">
54
56
  {q.sequence + 1}
55
57
  </span>
56
- {!readOnly && onToggleFlag && (
57
- <Tooltip>
58
- <TooltipTrigger>
59
- <span
60
- role="button"
61
- aria-label={q.isFlagged ? "Unflag question" : "Flag question"}
62
- className={cn(
63
- "inline-flex cursor-pointer transition-colors duration-150",
64
- q.isFlagged
65
- ? "text-warning"
66
- : variant === "current"
67
- ? "text-primary-foreground/60 hover:text-primary-foreground"
68
- : "text-muted-foreground hover:text-warning",
69
- )}
70
- onClick={(e: React.MouseEvent) => {
71
- e.stopPropagation();
72
- onToggleFlag(q.uid);
73
- }}
74
- >
75
- <Flag size={11} fill={q.isFlagged ? "currentColor" : "none"} />
76
- </span>
77
- </TooltipTrigger>
78
- <TooltipContent>{q.isFlagged ? "Unflag question" : "Flag question"}</TooltipContent>
79
- </Tooltip>
80
- )}
81
- </div>
58
+ </button>
82
59
  );
83
60
  })}
84
61
  </div>
85
62
  );
86
- };
63
+ });
@@ -1,3 +1,4 @@
1
+ import { memo } from "react";
1
2
  import { Clock } from "lucide-react";
2
3
  import { cn } from "../lib/utils";
3
4
  import { formatTimer } from "../utils/format-duration";
@@ -22,11 +23,11 @@ function getTimerClasses(isDanger: boolean, isWarning: boolean) {
22
23
  };
23
24
  }
24
25
 
25
- export const TimerDisplay = ({
26
+ export const TimerDisplay = memo(function TimerDisplay({
26
27
  timeElapsedSeconds,
27
28
  timeLimitSeconds,
28
29
  variant = "compact",
29
- }: TimerDisplayProps) => {
30
+ }: TimerDisplayProps) {
30
31
  const hasTimeLimit = timeLimitSeconds != null && timeLimitSeconds > 0;
31
32
  const remainingSeconds = hasTimeLimit
32
33
  ? Math.max(0, timeLimitSeconds - timeElapsedSeconds)
@@ -52,7 +53,7 @@ export const TimerDisplay = ({
52
53
  <span className="inline-flex leading-none">
53
54
  <Clock size={13} />
54
55
  </span>
55
- <span className="text-xs font-semibold font-mono tracking-wide">
56
+ <span className="text-xs font-semibold font-mono tracking-wide" aria-live="polite" aria-atomic="true">
56
57
  {displayTime}
57
58
  </span>
58
59
  </div>
@@ -66,8 +67,8 @@ export const TimerDisplay = ({
66
67
  </span>
67
68
  <span className={cn("text-sm", classes.bold && "font-semibold")}>
68
69
  {hasTimeLimit ? "Time remaining: " : "Time elapsed: "}
69
- <span className="font-mono font-semibold">{displayTime}</span>
70
+ <span className="font-mono font-semibold" aria-live="polite" aria-atomic="true">{displayTime}</span>
70
71
  </span>
71
72
  </div>
72
73
  );
73
- };
74
+ });