@hydralms/components 0.2.0 → 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 (283) hide show
  1. package/dist/StudentProfile-BVfZMbnV.cjs +1 -0
  2. package/dist/StudentProfile-DeMxdrL3.js +3275 -0
  3. package/dist/assessment-toolbar/question-navigator.d.ts +1 -1
  4. package/dist/assessment-toolbar/timer-display.d.ts +1 -1
  5. package/dist/common/index.d.ts +2 -1
  6. package/dist/common/pagination.d.ts +26 -0
  7. package/dist/common/types.d.ts +1 -0
  8. package/dist/components.css +1 -1
  9. package/dist/content/audio-player.d.ts +22 -0
  10. package/dist/content/code-block.d.ts +30 -0
  11. package/dist/content/embed-block.d.ts +28 -0
  12. package/dist/content/index.d.ts +6 -0
  13. package/dist/content/types.d.ts +24 -0
  14. package/dist/curriculum/course-card.d.ts +51 -0
  15. package/dist/curriculum/index.d.ts +2 -0
  16. package/dist/curriculum/types.d.ts +2 -2
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.js +494 -444
  20. package/dist/license/HydraContext.d.ts +16 -0
  21. package/dist/license/ProBadge.d.ts +6 -0
  22. package/dist/license/index.d.ts +7 -0
  23. package/dist/license/tiers.d.ts +3 -0
  24. package/dist/license/useHydraLicense.d.ts +6 -0
  25. package/dist/license/validate.d.ts +13 -0
  26. package/dist/license/withProGate.d.ts +6 -0
  27. package/dist/modules/AssignmentModule/AssignmentModule.d.ts +4 -7
  28. package/dist/modules/AssignmentModule/types.d.ts +5 -1
  29. package/dist/modules/CertificateModule/CertificateModule.d.ts +4 -8
  30. package/dist/modules/CertificateModule/types.d.ts +6 -4
  31. package/dist/modules/CourseCatalogModule/CourseCatalogModule.d.ts +5 -0
  32. package/dist/modules/CourseCatalogModule/types.d.ts +43 -0
  33. package/dist/modules/CoursePlayer/CoursePlayer.d.ts +4 -1
  34. package/dist/modules/DiscussionModule/DiscussionModule.d.ts +4 -7
  35. package/dist/modules/ExamModule/ExamModule.d.ts +4 -7
  36. package/dist/modules/ExamModule/types.d.ts +5 -14
  37. package/dist/modules/FlashcardLab/FlashcardLab.d.ts +4 -1
  38. package/dist/modules/FlashcardLab/types.d.ts +2 -0
  39. package/dist/modules/GradeCenterModule/GradeCenterModule.d.ts +4 -8
  40. package/dist/modules/GradeCenterModule/types.d.ts +2 -0
  41. package/dist/modules/QuizModule/QuizModule.d.ts +4 -1
  42. package/dist/modules/QuizModule/types.d.ts +5 -14
  43. package/dist/modules/StudentDashboardModule/StudentDashboardModule.d.ts +5 -0
  44. package/dist/modules/StudentDashboardModule/types.d.ts +54 -0
  45. package/dist/modules/StudentProfileModule/StudentProfileModule.d.ts +5 -0
  46. package/dist/modules/StudentProfileModule/types.d.ts +43 -0
  47. package/dist/modules/SurveyModule/SurveyModule.d.ts +4 -6
  48. package/dist/modules/SurveyModule/types.d.ts +2 -0
  49. package/dist/modules/_shared/assessment-intro.d.ts +16 -0
  50. package/dist/modules/_shared/assessment-results.d.ts +23 -0
  51. package/dist/modules/_shared/types.d.ts +10 -0
  52. package/dist/modules/_shared/use-timer.d.ts +9 -0
  53. package/dist/modules/index.d.ts +6 -0
  54. package/dist/modules.cjs +1 -1
  55. package/dist/modules.js +1266 -854
  56. package/dist/progress/types.d.ts +2 -0
  57. package/dist/provider/HydraProvider.d.ts +5 -1
  58. package/dist/questions/choice.d.ts +1 -1
  59. package/dist/questions/confidence-indicator.d.ts +37 -0
  60. package/dist/questions/essay.d.ts +1 -1
  61. package/dist/questions/fill-in-the-blank.d.ts +1 -1
  62. package/dist/questions/hotspot.d.ts +1 -1
  63. package/dist/questions/index.d.ts +2 -0
  64. package/dist/questions/inline-choice.d.ts +1 -1
  65. package/dist/questions/matching.d.ts +1 -1
  66. package/dist/questions/multiple-choice.d.ts +1 -1
  67. package/dist/questions/numeric.d.ts +1 -1
  68. package/dist/questions/ordering.d.ts +1 -1
  69. package/dist/questions/question-renderer.d.ts +1 -1
  70. package/dist/questions/scenario.d.ts +1 -1
  71. package/dist/questions/spreadsheet.d.ts +1 -1
  72. package/dist/questions/true-false.d.ts +1 -1
  73. package/dist/sections/AnnouncementFeed/AnnouncementFeed.d.ts +1 -1
  74. package/dist/sections/AnnouncementFeed/types.d.ts +15 -1
  75. package/dist/sections/AssessmentReview/AssessmentReview.d.ts +1 -1
  76. package/dist/sections/AssessmentReview/types.d.ts +6 -0
  77. package/dist/sections/AssignmentSubmission/AssignmentSubmission.d.ts +1 -1
  78. package/dist/sections/AssignmentSubmission/types.d.ts +6 -0
  79. package/dist/sections/CertificateViewer/CertificateViewer.d.ts +1 -1
  80. package/dist/sections/CertificateViewer/certificate-variants.d.ts +42 -0
  81. package/dist/sections/CertificateViewer/types.d.ts +6 -0
  82. package/dist/sections/CourseCatalog/CourseCatalog.d.ts +2 -0
  83. package/dist/sections/CourseCatalog/types.d.ts +80 -0
  84. package/dist/sections/CourseOutline/CourseOutline.d.ts +1 -1
  85. package/dist/sections/CourseOutline/types.d.ts +6 -0
  86. package/dist/sections/DiscussionThread/DiscussionThread.d.ts +1 -1
  87. package/dist/sections/DiscussionThread/types.d.ts +6 -0
  88. package/dist/sections/EnrollmentWizard/EnrollmentWizard.d.ts +2 -0
  89. package/dist/sections/EnrollmentWizard/types.d.ts +66 -0
  90. package/dist/sections/ExamSession/ExamSession.d.ts +1 -1
  91. package/dist/sections/ExamSession/types.d.ts +6 -0
  92. package/dist/sections/FlashcardStudySession/FlashcardStudySession.d.ts +1 -1
  93. package/dist/sections/FlashcardStudySession/types.d.ts +6 -0
  94. package/dist/sections/ForumBoard/ForumBoard.d.ts +1 -1
  95. package/dist/sections/ForumBoard/types.d.ts +14 -0
  96. package/dist/sections/GradebookTable/GradebookTable.d.ts +1 -1
  97. package/dist/sections/GradebookTable/types.d.ts +14 -0
  98. package/dist/sections/LecturePlayer/LecturePlayer.d.ts +1 -1
  99. package/dist/sections/LecturePlayer/types.d.ts +8 -0
  100. package/dist/sections/LessonPage/LessonPage.d.ts +1 -1
  101. package/dist/sections/LessonPage/types.d.ts +6 -0
  102. package/dist/sections/PracticeQuiz/PracticeQuiz.d.ts +1 -1
  103. package/dist/sections/PracticeQuiz/types.d.ts +6 -0
  104. package/dist/sections/ProgressDashboard/ProgressDashboard.d.ts +1 -1
  105. package/dist/sections/ProgressDashboard/types.d.ts +6 -0
  106. package/dist/sections/QuizSession/QuizSession.d.ts +1 -1
  107. package/dist/sections/QuizSession/types.d.ts +6 -0
  108. package/dist/sections/RequirementsChecklist/RequirementsChecklist.d.ts +1 -1
  109. package/dist/sections/RequirementsChecklist/types.d.ts +6 -0
  110. package/dist/sections/ResourceLibrary/ResourceLibrary.d.ts +1 -1
  111. package/dist/sections/ResourceLibrary/types.d.ts +15 -1
  112. package/dist/sections/RubricView/RubricView.d.ts +1 -1
  113. package/dist/sections/RubricView/types.d.ts +6 -0
  114. package/dist/sections/ScrollableQuiz/ScrollableQuiz.d.ts +1 -1
  115. package/dist/sections/ScrollableQuiz/types.d.ts +6 -0
  116. package/dist/sections/StudentProfile/StudentProfile.d.ts +2 -0
  117. package/dist/sections/StudentProfile/types.d.ts +98 -0
  118. package/dist/sections/SurveyForm/SurveyForm.d.ts +1 -1
  119. package/dist/sections/SurveyForm/types.d.ts +6 -0
  120. package/dist/sections/_shared/merge-answers.d.ts +9 -0
  121. package/dist/sections/_shared/section-shell.d.ts +20 -0
  122. package/dist/sections/_shared/use-assessment-session.d.ts +30 -0
  123. package/dist/sections/index.d.ts +6 -0
  124. package/dist/sections.cjs +1 -1
  125. package/dist/sections.js +268 -307
  126. package/dist/tabs-BsfVo2Bl.cjs +173 -0
  127. package/dist/{tabs-Wf3h_Cx3.js → tabs-BuY1iNJE.js} +7532 -6807
  128. package/dist/ui/badge.d.ts +1 -1
  129. package/dist/ui/index.d.ts +2 -0
  130. package/dist/ui/progress.d.ts +1 -1
  131. package/dist/ui/rich-text-editor.d.ts +3 -1
  132. package/dist/ui/toast.d.ts +43 -0
  133. package/dist/utils/debounce.d.ts +5 -1
  134. package/dist/utils/pick-palette-color.d.ts +19 -0
  135. package/dist/video/types.d.ts +15 -0
  136. package/dist/video/video-player.d.ts +1 -1
  137. package/dist/withProGate-BWqcKdPM.js +137 -0
  138. package/dist/withProGate-DX6XqKLp.cjs +1 -0
  139. package/package.json +34 -220
  140. package/src/assessment-toolbar/question-navigator.tsx +10 -5
  141. package/src/assessment-toolbar/timer-display.tsx +4 -3
  142. package/src/assessment-toolbar/use-countdown.ts +1 -1
  143. package/src/common/empty-state.tsx +1 -0
  144. package/src/common/index.ts +2 -0
  145. package/src/common/pagination.tsx +135 -0
  146. package/src/common/search-input.tsx +2 -1
  147. package/src/common/types.ts +2 -0
  148. package/src/content/attachment-list.tsx +2 -0
  149. package/src/content/audio-player.tsx +196 -0
  150. package/src/content/code-block.tsx +113 -0
  151. package/src/content/content-block.tsx +64 -0
  152. package/src/content/embed-block.tsx +78 -0
  153. package/src/content/file-upload-zone.tsx +10 -0
  154. package/src/content/index.ts +6 -0
  155. package/src/content/types.ts +5 -0
  156. package/src/curriculum/course-card.tsx +199 -0
  157. package/src/curriculum/curriculum-item.tsx +3 -3
  158. package/src/curriculum/curriculum-tree.tsx +20 -13
  159. package/src/curriculum/index.ts +2 -0
  160. package/src/curriculum/types.ts +2 -2
  161. package/src/flashcards/flashcard.tsx +28 -8
  162. package/src/index.ts +3 -0
  163. package/src/license/HydraContext.tsx +62 -0
  164. package/src/license/ProBadge.tsx +43 -0
  165. package/src/license/index.ts +7 -0
  166. package/src/license/tiers.ts +24 -0
  167. package/src/license/useHydraLicense.ts +10 -0
  168. package/src/license/validate.ts +90 -0
  169. package/src/license/withProGate.tsx +21 -0
  170. package/src/modules/AssignmentModule/AssignmentModule.tsx +17 -8
  171. package/src/modules/AssignmentModule/types.ts +5 -1
  172. package/src/modules/CertificateModule/CertificateModule.tsx +21 -9
  173. package/src/modules/CertificateModule/types.ts +6 -4
  174. package/src/modules/CourseCatalogModule/CourseCatalogModule.tsx +126 -0
  175. package/src/modules/CourseCatalogModule/types.ts +47 -0
  176. package/src/modules/CoursePlayer/CoursePlayer.tsx +37 -22
  177. package/src/modules/DiscussionModule/DiscussionModule.tsx +57 -22
  178. package/src/modules/ExamModule/ExamModule.tsx +64 -198
  179. package/src/modules/ExamModule/types.ts +5 -14
  180. package/src/modules/FlashcardLab/FlashcardLab.tsx +10 -5
  181. package/src/modules/FlashcardLab/types.ts +2 -0
  182. package/src/modules/GradeCenterModule/GradeCenterModule.tsx +7 -2
  183. package/src/modules/GradeCenterModule/types.ts +2 -0
  184. package/src/modules/QuizModule/QuizModule.tsx +49 -169
  185. package/src/modules/QuizModule/types.ts +5 -15
  186. package/src/modules/StudentDashboardModule/StudentDashboardModule.tsx +117 -0
  187. package/src/modules/StudentDashboardModule/types.ts +56 -0
  188. package/src/modules/StudentProfileModule/StudentProfileModule.tsx +289 -0
  189. package/src/modules/StudentProfileModule/types.ts +45 -0
  190. package/src/modules/SurveyModule/SurveyModule.tsx +9 -4
  191. package/src/modules/SurveyModule/types.ts +2 -0
  192. package/src/modules/_shared/assessment-intro.tsx +75 -0
  193. package/src/modules/_shared/assessment-results.tsx +133 -0
  194. package/src/modules/_shared/types.ts +11 -0
  195. package/src/modules/_shared/use-timer.ts +49 -0
  196. package/src/modules/index.ts +9 -0
  197. package/src/progress/achievement-badge.tsx +3 -3
  198. package/src/progress/grade-indicator.tsx +9 -1
  199. package/src/progress/progress-ring.tsx +2 -1
  200. package/src/progress/stat-card.tsx +8 -1
  201. package/src/progress/types.ts +2 -0
  202. package/src/provider/HydraProvider.tsx +15 -6
  203. package/src/questions/choice.tsx +13 -6
  204. package/src/questions/confidence-indicator.tsx +107 -0
  205. package/src/questions/essay.tsx +6 -4
  206. package/src/questions/fill-in-the-blank.tsx +8 -4
  207. package/src/questions/hotspot.tsx +4 -4
  208. package/src/questions/index.ts +2 -0
  209. package/src/questions/inline-choice.tsx +5 -4
  210. package/src/questions/matching.tsx +5 -4
  211. package/src/questions/multiple-choice.tsx +13 -6
  212. package/src/questions/numeric.tsx +8 -4
  213. package/src/questions/ordering.tsx +12 -4
  214. package/src/questions/question-renderer.tsx +3 -2
  215. package/src/questions/scenario.tsx +4 -4
  216. package/src/questions/spreadsheet.tsx +5 -4
  217. package/src/questions/true-false.tsx +13 -6
  218. package/src/sections/AnnouncementFeed/AnnouncementFeed.tsx +64 -8
  219. package/src/sections/AnnouncementFeed/types.ts +15 -1
  220. package/src/sections/AssessmentReview/AssessmentReview.tsx +37 -0
  221. package/src/sections/AssessmentReview/types.ts +6 -0
  222. package/src/sections/AssignmentSubmission/AssignmentSubmission.tsx +37 -1
  223. package/src/sections/AssignmentSubmission/types.ts +6 -0
  224. package/src/sections/CertificateViewer/CertificateViewer.tsx +29 -227
  225. package/src/sections/CertificateViewer/certificate-variants.tsx +170 -0
  226. package/src/sections/CertificateViewer/types.ts +6 -0
  227. package/src/sections/CourseCatalog/CourseCatalog.tsx +220 -0
  228. package/src/sections/CourseCatalog/types.ts +76 -0
  229. package/src/sections/CourseOutline/CourseOutline.tsx +41 -0
  230. package/src/sections/CourseOutline/types.ts +6 -0
  231. package/src/sections/DiscussionThread/DiscussionThread.tsx +42 -1
  232. package/src/sections/DiscussionThread/types.ts +6 -0
  233. package/src/sections/EnrollmentWizard/EnrollmentWizard.tsx +343 -0
  234. package/src/sections/EnrollmentWizard/types.ts +65 -0
  235. package/src/sections/ExamSession/ExamSession.tsx +100 -94
  236. package/src/sections/ExamSession/types.ts +6 -0
  237. package/src/sections/FlashcardStudySession/FlashcardStudySession.tsx +53 -36
  238. package/src/sections/FlashcardStudySession/types.ts +6 -0
  239. package/src/sections/ForumBoard/ForumBoard.tsx +59 -1
  240. package/src/sections/ForumBoard/types.ts +14 -0
  241. package/src/sections/GradebookTable/GradebookTable.tsx +54 -1
  242. package/src/sections/GradebookTable/types.ts +14 -0
  243. package/src/sections/LecturePlayer/LecturePlayer.tsx +63 -37
  244. package/src/sections/LecturePlayer/types.ts +8 -0
  245. package/src/sections/LessonPage/LessonPage.tsx +36 -5
  246. package/src/sections/LessonPage/types.ts +6 -0
  247. package/src/sections/PracticeQuiz/PracticeQuiz.tsx +106 -74
  248. package/src/sections/PracticeQuiz/types.ts +6 -0
  249. package/src/sections/ProgressDashboard/ProgressDashboard.tsx +64 -10
  250. package/src/sections/ProgressDashboard/types.ts +6 -0
  251. package/src/sections/QuizSession/QuizSession.tsx +71 -82
  252. package/src/sections/QuizSession/types.ts +6 -0
  253. package/src/sections/RequirementsChecklist/RequirementsChecklist.tsx +41 -1
  254. package/src/sections/RequirementsChecklist/types.ts +6 -0
  255. package/src/sections/ResourceLibrary/ResourceLibrary.tsx +64 -8
  256. package/src/sections/ResourceLibrary/types.ts +15 -1
  257. package/src/sections/RubricView/RubricView.tsx +37 -1
  258. package/src/sections/RubricView/types.ts +6 -0
  259. package/src/sections/ScrollableQuiz/ScrollableQuiz.tsx +36 -15
  260. package/src/sections/ScrollableQuiz/types.ts +6 -0
  261. package/src/sections/StudentProfile/StudentProfile.tsx +279 -0
  262. package/src/sections/StudentProfile/types.ts +99 -0
  263. package/src/sections/SurveyForm/SurveyForm.tsx +32 -5
  264. package/src/sections/SurveyForm/types.ts +6 -0
  265. package/src/sections/_shared/merge-answers.ts +22 -0
  266. package/src/sections/_shared/section-shell.tsx +64 -0
  267. package/src/sections/_shared/use-assessment-session.ts +125 -0
  268. package/src/sections/index.ts +22 -0
  269. package/src/social/user-avatar.tsx +9 -5
  270. package/src/styles/globals.css +39 -41
  271. package/src/ui/badge.tsx +8 -0
  272. package/src/ui/index.ts +2 -0
  273. package/src/ui/progress.tsx +4 -0
  274. package/src/ui/rich-text-editor.tsx +10 -0
  275. package/src/ui/rich-text-toolbar.tsx +2 -1
  276. package/src/ui/toast.tsx +170 -0
  277. package/src/utils/debounce.ts +8 -2
  278. package/src/utils/pick-palette-color.ts +33 -0
  279. package/src/video/types.ts +16 -0
  280. package/src/video/video-player.tsx +13 -1
  281. package/dist/ForumBoard-CHXU3mjC.js +0 -2207
  282. package/dist/ForumBoard-d1w5-r6n.cjs +0 -1
  283. package/dist/tabs-DRM2Iq_J.cjs +0 -172
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from "react";
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "info" | "warning" | "default" | "destructive" | "success" | "muted" | "outline" | "secondary" | null | undefined;
4
+ variant?: "info" | "warning" | "default" | "destructive" | "success" | "muted" | "outline" | "secondary" | "palette0" | "palette1" | "palette2" | "palette3" | null | undefined;
5
5
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
6
  declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
7
  asChild?: boolean;
@@ -16,3 +16,5 @@ export { Skeleton } from './skeleton';
16
16
  export { Tooltip, TooltipTrigger, TooltipContent } from './tooltip';
17
17
  export { RichTextEditor } from './rich-text-editor';
18
18
  export type { RichTextEditorProps, RichTextEditorVariant } from './rich-text-editor';
19
+ export { ToastProvider, Toaster, useToast, toastVariants } from './toast';
20
+ export type { ToastOptions, ToastVariant } from './toast';
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from "react";
3
3
  declare const progressVariants: (props?: ({
4
- variant?: "info" | "warning" | "default" | "success" | null | undefined;
4
+ variant?: "info" | "warning" | "default" | "success" | "palette0" | "palette1" | "palette2" | "palette3" | null | undefined;
5
5
  size?: "default" | "sm" | null | undefined;
6
6
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
7
  interface ProgressProps extends Omit<React.ComponentProps<"div">, "children">, VariantProps<typeof progressVariants> {
@@ -12,6 +12,8 @@ export interface RichTextEditorProps {
12
12
  disabled?: boolean;
13
13
  /** `"default"` shows full toolbar; `"minimal"` shows only basic formatting */
14
14
  variant?: RichTextEditorVariant;
15
+ /** Accessible label for screen readers (defaults to "Rich text editor") */
16
+ ariaLabel?: string;
15
17
  className?: string;
16
18
  style?: React.CSSProperties;
17
19
  }
@@ -27,4 +29,4 @@ export interface RichTextEditorProps {
27
29
  * variant="default"
28
30
  * />
29
31
  */
30
- export declare function RichTextEditor({ value, onChange, placeholder, readOnly, disabled, variant, className, style, }: RichTextEditorProps): import("react/jsx-runtime").JSX.Element | null;
32
+ export declare function RichTextEditor({ value, onChange, placeholder, readOnly, disabled, variant, ariaLabel, className, style, }: RichTextEditorProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,43 @@
1
+ import { ReactNode } from 'react';
2
+ declare const toastVariants: (props?: ({
3
+ variant?: "info" | "warning" | "success" | "error" | null | undefined;
4
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
5
+ type ToastVariant = "success" | "error" | "warning" | "info";
6
+ /** Options for creating a toast notification. */
7
+ interface ToastOptions {
8
+ /** Toast message */
9
+ message: string;
10
+ /** Optional title */
11
+ title?: string;
12
+ /** Visual variant */
13
+ variant?: ToastVariant;
14
+ /** Auto-dismiss duration in ms (default 5000, 0 = no auto-dismiss) */
15
+ duration?: number;
16
+ }
17
+ interface ToastContextValue {
18
+ toast: (options: ToastOptions) => void;
19
+ }
20
+ /**
21
+ * ToastProvider wraps your app to enable toast notifications.
22
+ * Renders a fixed-position toast container via portal.
23
+ *
24
+ * @example
25
+ * <ToastProvider>
26
+ * <App />
27
+ * </ToastProvider>
28
+ */
29
+ declare function ToastProvider({ children }: {
30
+ children: ReactNode;
31
+ }): import("react/jsx-runtime").JSX.Element;
32
+ /**
33
+ * Hook to trigger toast notifications. Must be used within a ToastProvider.
34
+ *
35
+ * @example
36
+ * const { toast } = useToast();
37
+ * toast({ message: "Saved!", variant: "success" });
38
+ */
39
+ declare function useToast(): ToastContextValue;
40
+ /** Convenience alias for ToastProvider. */
41
+ declare const Toaster: typeof ToastProvider;
42
+ export { ToastProvider, Toaster, useToast, toastVariants };
43
+ export type { ToastOptions, ToastVariant };
@@ -1 +1,5 @@
1
- export declare function debounce<T extends (...args: Parameters<T>) => void>(fn: T, delay: number): (...args: Parameters<T>) => void;
1
+ type Cancellable<T extends (...args: Parameters<T>) => void> = ((...args: Parameters<T>) => void) & {
2
+ cancel: () => void;
3
+ };
4
+ export declare function debounce<T extends (...args: Parameters<T>) => void>(fn: T, delay: number): Cancellable<T>;
5
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Palette CSS variable names matching --palette-0 through --palette-3
3
+ * defined in globals.css.
4
+ */
5
+ export declare const PALETTE_VARS: readonly ["var(--palette-0)", "var(--palette-1)", "var(--palette-2)", "var(--palette-3)"];
6
+ /** Number of palette colors available. */
7
+ export declare const PALETTE_COUNT: 4;
8
+ /**
9
+ * Pick a palette CSS variable by cycling through the 4 palette colors.
10
+ * Useful for assigning varied colors to list items by index.
11
+ */
12
+ export declare function pickPaletteColor(index: number): string;
13
+ /** Palette variant name for CVA-based components (badge, progress). */
14
+ export type PaletteVariant = "palette0" | "palette1" | "palette2" | "palette3";
15
+ /**
16
+ * Pick a palette variant name by cycling through the 4 palette variants.
17
+ * Useful for assigning varied CVA variants to list items by index.
18
+ */
19
+ export declare function pickPaletteVariant(index: number): PaletteVariant;
@@ -9,6 +9,19 @@
9
9
  * onEnded={() => markLessonComplete()}
10
10
  * />
11
11
  */
12
+ /** A text track (captions, subtitles) for the video element. */
13
+ export interface VideoTrack {
14
+ /** URL of the track file (e.g., .vtt) */
15
+ src: string;
16
+ /** Track kind */
17
+ kind: "captions" | "subtitles" | "descriptions" | "chapters" | "metadata";
18
+ /** Human-readable track label (e.g., "English") */
19
+ label: string;
20
+ /** BCP 47 language code (e.g., "en") */
21
+ srcLang: string;
22
+ /** Whether this track should be active by default */
23
+ default?: boolean;
24
+ }
12
25
  export interface VideoPlayerProps {
13
26
  /** URL of the video source */
14
27
  src?: string;
@@ -30,6 +43,8 @@ export interface VideoPlayerProps {
30
43
  readOnly?: boolean;
31
44
  /** Aspect ratio of the video container */
32
45
  aspectRatio?: "16/9" | "4/3" | "1/1";
46
+ /** Array of text tracks (captions, subtitles) for the video */
47
+ tracks?: VideoTrack[];
33
48
  /** CSS class name for the root element */
34
49
  className?: string;
35
50
  /** Inline styles for the root element */
@@ -1,2 +1,2 @@
1
1
  import { VideoPlayerProps } from './types';
2
- export declare const VideoPlayer: ({ src, poster, title, autoPlay, onPlay, onPause, onEnded, onTimeUpdate, readOnly, aspectRatio, className, style, }: VideoPlayerProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const VideoPlayer: ({ src, poster, title, autoPlay, onPlay, onPause, onEnded, onTimeUpdate, readOnly, aspectRatio, tracks, className, style, }: VideoPlayerProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,137 @@
1
+ import { jsx as a, jsxs as c } from "react/jsx-runtime";
2
+ import { createContext as f, useState as p, useEffect as h, useContext as y } from "react";
3
+ const s = "hydra_key_v", g = 300 * 1e3;
4
+ function k(e) {
5
+ try {
6
+ const t = sessionStorage.getItem(s);
7
+ if (t) {
8
+ const { result: n, ts: r, key: o } = JSON.parse(t);
9
+ if (o === e && Date.now() - r < g) return n;
10
+ }
11
+ } catch {
12
+ }
13
+ return null;
14
+ }
15
+ function m(e, t) {
16
+ try {
17
+ sessionStorage.setItem(s, JSON.stringify({ result: t, ts: Date.now(), key: e }));
18
+ } catch {
19
+ }
20
+ }
21
+ function l(e) {
22
+ try {
23
+ const t = sessionStorage.getItem(s);
24
+ if (t) {
25
+ const { result: n, key: r } = JSON.parse(t);
26
+ if (r === e && n === "valid-pro") return "valid-pro";
27
+ }
28
+ } catch {
29
+ }
30
+ return "invalid";
31
+ }
32
+ async function v(e, t) {
33
+ if (!t) return "skip";
34
+ if (!e) return "no-key";
35
+ const n = k(e);
36
+ if (n) return n;
37
+ try {
38
+ const r = await fetch(`${t}?key=${encodeURIComponent(e)}`, {
39
+ method: "GET",
40
+ signal: AbortSignal.timeout(4e3)
41
+ });
42
+ if (!r.ok) return l(e);
43
+ const o = await r.json();
44
+ let i;
45
+ return o.valid ? o.plan === "pro" || o.plan === "enterprise" ? i = "valid-pro" : i = "valid-free" : i = "invalid", m(e, i), i;
46
+ } catch {
47
+ return l(e);
48
+ }
49
+ }
50
+ const u = f({
51
+ plan: "free",
52
+ isPro: !1
53
+ });
54
+ function x(e) {
55
+ switch (e) {
56
+ case "valid-pro":
57
+ case "skip":
58
+ return "pro";
59
+ case "valid-free":
60
+ case "no-key":
61
+ return "free";
62
+ case "invalid":
63
+ return "invalid";
64
+ }
65
+ }
66
+ function H({ licenseKey: e, validateUrl: t = "", children: n }) {
67
+ const [r, o] = p(() => t ? e ? "validating" : "free" : "pro");
68
+ return h(() => {
69
+ if (!t) {
70
+ o("pro");
71
+ return;
72
+ }
73
+ let i = !1;
74
+ return v(e ?? null, t).then((d) => {
75
+ i || o(x(d));
76
+ }), () => {
77
+ i = !0;
78
+ };
79
+ }, [e, t]), /* @__PURE__ */ a(u.Provider, { value: { plan: r, isPro: r === "pro" }, children: n });
80
+ }
81
+ function P() {
82
+ return y(u);
83
+ }
84
+ function S({ children: e, feature: t }) {
85
+ return /* @__PURE__ */ c("div", { style: { position: "relative" }, children: [
86
+ e,
87
+ /* @__PURE__ */ c(
88
+ "a",
89
+ {
90
+ href: "https://hydralms.com/pro",
91
+ target: "_blank",
92
+ rel: "noopener noreferrer",
93
+ style: {
94
+ position: "absolute",
95
+ bottom: 14,
96
+ right: 16,
97
+ zIndex: 9999,
98
+ display: "flex",
99
+ alignItems: "center",
100
+ gap: 5,
101
+ padding: "4px 10px 4px 8px",
102
+ background: "rgba(0,0,0,0.5)",
103
+ backdropFilter: "blur(6px)",
104
+ borderRadius: 20,
105
+ fontFamily: "system-ui, -apple-system, sans-serif",
106
+ fontSize: 11,
107
+ fontWeight: 500,
108
+ color: "rgba(255,255,255,0.85)",
109
+ letterSpacing: "0.01em",
110
+ whiteSpace: "nowrap",
111
+ lineHeight: 1,
112
+ pointerEvents: "auto",
113
+ textDecoration: "none"
114
+ },
115
+ title: t ? `"${t}" is a HydraLMS Pro module` : "Upgrade to HydraLMS Pro",
116
+ children: [
117
+ /* @__PURE__ */ a("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", style: { opacity: 0.8 }, children: /* @__PURE__ */ a("path", { d: "M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" }) }),
118
+ "HydraLMS Pro"
119
+ ]
120
+ }
121
+ )
122
+ ] });
123
+ }
124
+ function L(e, t) {
125
+ const n = (r) => {
126
+ const { isPro: o } = P();
127
+ return o ? /* @__PURE__ */ a(e, { ...r }) : /* @__PURE__ */ a(S, { feature: t, children: /* @__PURE__ */ a(e, { ...r }) });
128
+ };
129
+ return n.displayName = `ProGated(${t})`, n;
130
+ }
131
+ export {
132
+ H,
133
+ S as P,
134
+ u as a,
135
+ P as u,
136
+ L as w
137
+ };
@@ -0,0 +1 @@
1
+ "use strict";const s=require("react/jsx-runtime"),a=require("react"),c="hydra_key_v",h=300*1e3;function y(e){try{const t=sessionStorage.getItem(c);if(t){const{result:n,ts:r,key:i}=JSON.parse(t);if(i===e&&Date.now()-r<h)return n}}catch{}return null}function g(e,t){try{sessionStorage.setItem(c,JSON.stringify({result:t,ts:Date.now(),key:e}))}catch{}}function l(e){try{const t=sessionStorage.getItem(c);if(t){const{result:n,key:r}=JSON.parse(t);if(r===e&&n==="valid-pro")return"valid-pro"}}catch{}return"invalid"}async function x(e,t){if(!t)return"skip";if(!e)return"no-key";const n=y(e);if(n)return n;try{const r=await fetch(`${t}?key=${encodeURIComponent(e)}`,{method:"GET",signal:AbortSignal.timeout(4e3)});if(!r.ok)return l(e);const i=await r.json();let o;return i.valid?i.plan==="pro"||i.plan==="enterprise"?o="valid-pro":o="valid-free":o="invalid",g(e,o),o}catch{return l(e)}}const u=a.createContext({plan:"free",isPro:!1});function k(e){switch(e){case"valid-pro":case"skip":return"pro";case"valid-free":case"no-key":return"free";case"invalid":return"invalid"}}function v({licenseKey:e,validateUrl:t="",children:n}){const[r,i]=a.useState(()=>t?e?"validating":"free":"pro");return a.useEffect(()=>{if(!t){i("pro");return}let o=!1;return x(e??null,t).then(p=>{o||i(k(p))}),()=>{o=!0}},[e,t]),s.jsx(u.Provider,{value:{plan:r,isPro:r==="pro"},children:n})}function d(){return a.useContext(u)}function f({children:e,feature:t}){return s.jsxs("div",{style:{position:"relative"},children:[e,s.jsxs("a",{href:"https://hydralms.com/pro",target:"_blank",rel:"noopener noreferrer",style:{position:"absolute",bottom:14,right:16,zIndex:9999,display:"flex",alignItems:"center",gap:5,padding:"4px 10px 4px 8px",background:"rgba(0,0,0,0.5)",backdropFilter:"blur(6px)",borderRadius:20,fontFamily:"system-ui, -apple-system, sans-serif",fontSize:11,fontWeight:500,color:"rgba(255,255,255,0.85)",letterSpacing:"0.01em",whiteSpace:"nowrap",lineHeight:1,pointerEvents:"auto",textDecoration:"none"},title:t?`"${t}" is a HydraLMS Pro module`:"Upgrade to HydraLMS Pro",children:[s.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",style:{opacity:.8},children:s.jsx("path",{d:"M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"})}),"HydraLMS Pro"]})]})}function P(e,t){const n=r=>{const{isPro:i}=d();return i?s.jsx(e,{...r}):s.jsx(f,{feature:t,children:s.jsx(e,{...r})})};return n.displayName=`ProGated(${t})`,n}exports.HydraLicenseContext=u;exports.HydraLicenseProvider=v;exports.ProBadge=f;exports.useHydraLicense=d;exports.withProGate=P;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydralms/components",
3
- "version": "0.2.0",
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,132 +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"
117
- },
118
- "./sections/RubricView": {
119
- "types": "./src/sections/RubricView/RubricView.tsx",
120
- "default": "./src/sections/RubricView/RubricView.tsx"
121
- },
122
- "./sections/RequirementsChecklist": {
123
- "types": "./src/sections/RequirementsChecklist/RequirementsChecklist.tsx",
124
- "default": "./src/sections/RequirementsChecklist/RequirementsChecklist.tsx"
125
- },
126
- "./sections/ForumBoard": {
127
- "types": "./src/sections/ForumBoard/ForumBoard.tsx",
128
- "default": "./src/sections/ForumBoard/ForumBoard.tsx"
52
+ "./sections/*": {
53
+ "types": "./src/sections/*/index.ts",
54
+ "default": "./src/sections/*/index.ts"
129
55
  },
130
56
  "./modules": {
131
- "types": "./src/modules/index.ts",
132
- "default": "./src/modules/index.ts"
133
- },
134
- "./modules/QuizModule": {
135
- "types": "./src/modules/QuizModule/QuizModule.tsx",
136
- "default": "./src/modules/QuizModule/QuizModule.tsx"
137
- },
138
- "./modules/FlashcardLab": {
139
- "types": "./src/modules/FlashcardLab/FlashcardLab.tsx",
140
- "default": "./src/modules/FlashcardLab/FlashcardLab.tsx"
141
- },
142
- "./modules/CoursePlayer": {
143
- "types": "./src/modules/CoursePlayer/CoursePlayer.tsx",
144
- "default": "./src/modules/CoursePlayer/CoursePlayer.tsx"
145
- },
146
- "./modules/ExamModule": {
147
- "types": "./src/modules/ExamModule/ExamModule.tsx",
148
- "default": "./src/modules/ExamModule/ExamModule.tsx"
57
+ "types": "./dist/modules/index.d.ts",
58
+ "import": "./dist/modules.js",
59
+ "require": "./dist/modules.cjs"
149
60
  },
150
- "./modules/SurveyModule": {
151
- "types": "./src/modules/SurveyModule/SurveyModule.tsx",
152
- "default": "./src/modules/SurveyModule/SurveyModule.tsx"
61
+ "./modules/*": {
62
+ "types": "./src/modules/*/index.ts",
63
+ "default": "./src/modules/*/index.ts"
153
64
  },
154
- "./modules/GradeCenterModule": {
155
- "types": "./src/modules/GradeCenterModule/GradeCenterModule.tsx",
156
- "default": "./src/modules/GradeCenterModule/GradeCenterModule.tsx"
157
- },
158
- "./modules/AssignmentModule": {
159
- "types": "./src/modules/AssignmentModule/AssignmentModule.tsx",
160
- "default": "./src/modules/AssignmentModule/AssignmentModule.tsx"
161
- },
162
- "./modules/CertificateModule": {
163
- "types": "./src/modules/CertificateModule/CertificateModule.tsx",
164
- "default": "./src/modules/CertificateModule/CertificateModule.tsx"
165
- },
166
- "./modules/DiscussionModule": {
167
- "types": "./src/modules/DiscussionModule/DiscussionModule.tsx",
168
- "default": "./src/modules/DiscussionModule/DiscussionModule.tsx"
65
+ "./license": {
66
+ "types": "./dist/license/index.d.ts",
67
+ "import": "./dist/license.js",
68
+ "require": "./dist/license.cjs"
169
69
  },
170
70
  "./provider": {
171
71
  "types": "./src/provider/index.ts",
@@ -207,104 +107,9 @@
207
107
  "types": "./src/social/index.ts",
208
108
  "default": "./src/social/index.ts"
209
109
  },
210
- "./ui/card": {
211
- "types": "./src/ui/card.tsx",
212
- "default": "./src/ui/card.tsx"
213
- },
214
- "./ui/progress": {
215
- "types": "./src/ui/progress.tsx",
216
- "default": "./src/ui/progress.tsx"
217
- },
218
- "./provider/HydraProvider": {
219
- "types": "./src/provider/HydraProvider.tsx",
220
- "default": "./src/provider/HydraProvider.tsx"
221
- },
222
- "./styles.css": "./src/styles/globals.css",
223
- "./styles/globals.css": "./src/styles/globals.css",
110
+ "./styles.css": "./dist/components.css",
224
111
  "./package.json": "./package.json"
225
112
  },
226
- "publishConfig": {
227
- "main": "./dist/index.cjs",
228
- "module": "./dist/index.js",
229
- "types": "./dist/index.d.ts",
230
- "exports": {
231
- ".": {
232
- "types": "./dist/index.d.ts",
233
- "import": "./dist/index.js",
234
- "require": "./dist/index.cjs"
235
- },
236
- "./sections": {
237
- "types": "./dist/sections/index.d.ts",
238
- "import": "./dist/sections.js",
239
- "require": "./dist/sections.cjs"
240
- },
241
- "./sections/*": {
242
- "types": "./src/sections/*/index.ts",
243
- "default": "./src/sections/*/index.ts"
244
- },
245
- "./modules": {
246
- "types": "./dist/modules/index.d.ts",
247
- "import": "./dist/modules.js",
248
- "require": "./dist/modules.cjs"
249
- },
250
- "./modules/*": {
251
- "types": "./src/modules/*/index.ts",
252
- "default": "./src/modules/*/index.ts"
253
- },
254
- "./provider": {
255
- "types": "./src/provider/index.ts",
256
- "default": "./src/provider/index.ts"
257
- },
258
- "./questions": {
259
- "types": "./src/questions/index.ts",
260
- "default": "./src/questions/index.ts"
261
- },
262
- "./assessment-toolbar": {
263
- "types": "./src/assessment-toolbar/index.ts",
264
- "default": "./src/assessment-toolbar/index.ts"
265
- },
266
- "./flashcards": {
267
- "types": "./src/flashcards/index.ts",
268
- "default": "./src/flashcards/index.ts"
269
- },
270
- "./curriculum": {
271
- "types": "./src/curriculum/index.ts",
272
- "default": "./src/curriculum/index.ts"
273
- },
274
- "./video": {
275
- "types": "./src/video/index.ts",
276
- "default": "./src/video/index.ts"
277
- },
278
- "./progress": {
279
- "types": "./src/progress/index.ts",
280
- "default": "./src/progress/index.ts"
281
- },
282
- "./feedback": {
283
- "types": "./src/feedback/index.ts",
284
- "default": "./src/feedback/index.ts"
285
- },
286
- "./content": {
287
- "types": "./src/content/index.ts",
288
- "default": "./src/content/index.ts"
289
- },
290
- "./social": {
291
- "types": "./src/social/index.ts",
292
- "default": "./src/social/index.ts"
293
- },
294
- "./styles.css": "./dist/components.css",
295
- "./package.json": "./package.json"
296
- }
297
- },
298
- "scripts": {
299
- "build": "vite build",
300
- "dev": "vite build --watch",
301
- "generate-docs": "tsx scripts/generate-docs.ts",
302
- "check-docs": "tsx scripts/generate-docs.ts --check",
303
- "typecheck": "tsc --noEmit",
304
- "test": "vitest run",
305
- "test:watch": "vitest",
306
- "prepublishOnly": "pnpm run build"
307
- },
308
113
  "peerDependencies": {
309
114
  "react": "^18.0.0 || ^19.0.0",
310
115
  "react-dom": "^18.0.0 || ^19.0.0",
@@ -339,5 +144,14 @@
339
144
  "vite": "^6.0.0",
340
145
  "vite-plugin-dts": "^4.0.0",
341
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"
342
156
  }
343
- }
157
+ }
@@ -1,3 +1,4 @@
1
+ import { memo } from "react";
1
2
  import type { QuestionNavigatorProps } from "./types";
2
3
  import { cn } from "../lib/utils";
3
4
 
@@ -18,12 +19,12 @@ const getChipVariant = (
18
19
  return "default";
19
20
  };
20
21
 
21
- export const QuestionNavigator = ({
22
+ export const QuestionNavigator = memo(function QuestionNavigator({
22
23
  questions,
23
24
  currentQuestionUid,
24
25
  onNavigate,
25
26
  readOnly = false,
26
- }: QuestionNavigatorProps) => {
27
+ }: QuestionNavigatorProps) {
27
28
  const getTooltipContent = (q: (typeof questions)[0]): string => {
28
29
  const parts: string[] = [`Question ${q.sequence + 1}`];
29
30
  if (q.isFlagged) parts.push("Flagged");
@@ -37,22 +38,26 @@ export const QuestionNavigator = ({
37
38
  {questions.map((q) => {
38
39
  const variant = getChipVariant(q, currentQuestionUid);
39
40
  return (
40
- <div
41
+ <button
42
+ type="button"
41
43
  key={q.uid}
42
44
  title={getTooltipContent(q)}
45
+ aria-label={getTooltipContent(q)}
46
+ aria-current={q.uid === currentQuestionUid ? "step" : undefined}
43
47
  className={cn(
44
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",
45
49
  CHIP_CLASSES[variant],
46
50
  readOnly ? "cursor-default" : "cursor-pointer hover:shadow-sm hover:-translate-y-px",
47
51
  )}
48
52
  onClick={readOnly ? undefined : () => onNavigate?.(q.uid)}
53
+ disabled={readOnly}
49
54
  >
50
55
  <span className="font-semibold min-w-3.5 text-center">
51
56
  {q.sequence + 1}
52
57
  </span>
53
- </div>
58
+ </button>
54
59
  );
55
60
  })}
56
61
  </div>
57
62
  );
58
- };
63
+ });