@hydralms/components 0.1.2 → 0.2.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 (199) hide show
  1. package/dist/ForumBoard-CHXU3mjC.js +2207 -0
  2. package/dist/ForumBoard-d1w5-r6n.cjs +1 -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/types.d.ts +52 -4
  9. package/dist/assessment-toolbar/use-countdown.d.ts +43 -0
  10. package/dist/common/index.d.ts +2 -1
  11. package/dist/common/stepper.d.ts +6 -0
  12. package/dist/common/types.d.ts +37 -0
  13. package/dist/components.css +1 -1
  14. package/dist/content/attachment-list.d.ts +6 -0
  15. package/dist/content/content-block.d.ts +1 -1
  16. package/dist/content/index.d.ts +2 -1
  17. package/dist/content/types.d.ts +39 -0
  18. package/dist/curriculum/curriculum-item.d.ts +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.js +551 -312
  21. package/dist/modules/AssignmentModule/AssignmentModule.d.ts +8 -0
  22. package/dist/modules/AssignmentModule/types.d.ts +65 -0
  23. package/dist/modules/CertificateModule/CertificateModule.d.ts +9 -0
  24. package/dist/modules/CertificateModule/types.d.ts +49 -0
  25. package/dist/modules/DiscussionModule/DiscussionModule.d.ts +8 -0
  26. package/dist/modules/DiscussionModule/types.d.ts +47 -0
  27. package/dist/modules/ExamModule/ExamModule.d.ts +8 -0
  28. package/dist/modules/ExamModule/types.d.ts +64 -0
  29. package/dist/modules/GradeCenterModule/GradeCenterModule.d.ts +9 -0
  30. package/dist/modules/GradeCenterModule/types.d.ts +54 -0
  31. package/dist/modules/QuizModule/QuizModule.d.ts +1 -1
  32. package/dist/modules/QuizModule/types.d.ts +6 -1
  33. package/dist/modules/SurveyModule/SurveyModule.d.ts +7 -0
  34. package/dist/modules/SurveyModule/types.d.ts +49 -0
  35. package/dist/modules/index.d.ts +12 -0
  36. package/dist/modules.cjs +1 -0
  37. package/dist/modules.js +1422 -0
  38. package/dist/progress/achievement-badge.d.ts +6 -0
  39. package/dist/progress/activity-timeline.d.ts +6 -0
  40. package/dist/progress/index.d.ts +4 -1
  41. package/dist/progress/stat-card.d.ts +1 -1
  42. package/dist/progress/streak-badge.d.ts +6 -0
  43. package/dist/progress/types.d.ts +97 -0
  44. package/dist/questions/essay.d.ts +1 -1
  45. package/dist/questions/hotspot.d.ts +21 -0
  46. package/dist/questions/index.d.ts +9 -1
  47. package/dist/questions/inline-choice.d.ts +21 -0
  48. package/dist/questions/matching.d.ts +22 -0
  49. package/dist/questions/numeric.d.ts +11 -0
  50. package/dist/questions/ordering.d.ts +12 -0
  51. package/dist/questions/scenario.d.ts +23 -0
  52. package/dist/questions/scoring.d.ts +22 -0
  53. package/dist/questions/spreadsheet.d.ts +29 -0
  54. package/dist/questions/types.d.ts +106 -1
  55. package/dist/questions/use-drag-reorder.d.ts +17 -0
  56. package/dist/sections/CertificateViewer/types.d.ts +7 -5
  57. package/dist/sections/ExamSession/ExamSession.d.ts +1 -1
  58. package/dist/sections/ExamSession/types.d.ts +6 -1
  59. package/dist/sections/ForumBoard/ForumBoard.d.ts +8 -0
  60. package/dist/sections/ForumBoard/types.d.ts +64 -0
  61. package/dist/sections/QuizSession/QuizSession.d.ts +1 -1
  62. package/dist/sections/QuizSession/types.d.ts +6 -1
  63. package/dist/sections/RequirementsChecklist/RequirementsChecklist.d.ts +8 -0
  64. package/dist/sections/RequirementsChecklist/types.d.ts +37 -0
  65. package/dist/sections/RubricView/RubricView.d.ts +9 -0
  66. package/dist/sections/RubricView/types.d.ts +50 -0
  67. package/dist/sections/index.d.ts +7 -1
  68. package/dist/sections.cjs +1 -1
  69. package/dist/sections.js +250 -1715
  70. package/dist/social/post-card.d.ts +1 -1
  71. package/dist/tabs-DRM2Iq_J.cjs +172 -0
  72. package/dist/tabs-Wf3h_Cx3.js +21580 -0
  73. package/dist/ui/alert.d.ts +1 -1
  74. package/dist/ui/badge.d.ts +1 -1
  75. package/dist/ui/button.d.ts +1 -1
  76. package/dist/ui/drawer.d.ts +84 -0
  77. package/dist/ui/index.d.ts +3 -0
  78. package/dist/ui/progress.d.ts +1 -1
  79. package/dist/ui/rich-text-editor.d.ts +30 -0
  80. package/dist/ui/rich-text-toolbar.d.ts +8 -0
  81. package/dist/utils/array-utils.d.ts +4 -0
  82. package/dist/utils/flatten-leaves.d.ts +6 -0
  83. package/dist/utils/format-file-size.d.ts +1 -0
  84. package/dist/utils/format-timestamp.d.ts +1 -0
  85. package/dist/utils/is-empty-html.d.ts +5 -0
  86. package/dist/utils/shuffle.d.ts +1 -0
  87. package/dist/utils/string-utils.d.ts +12 -0
  88. package/dist/video/video-bookmark.d.ts +1 -1
  89. package/dist/video/video-playlist-item.d.ts +1 -1
  90. package/package.json +141 -3
  91. package/src/assessment-toolbar/assessment-toolbar.tsx +54 -49
  92. package/src/assessment-toolbar/index.ts +6 -0
  93. package/src/assessment-toolbar/question-header-bar.tsx +61 -0
  94. package/src/assessment-toolbar/question-materials-drawer.tsx +55 -0
  95. package/src/assessment-toolbar/question-navigator.tsx +3 -31
  96. package/src/assessment-toolbar/timer-display.tsx +2 -2
  97. package/src/assessment-toolbar/types.ts +54 -4
  98. package/src/assessment-toolbar/use-countdown.ts +153 -0
  99. package/src/common/index.ts +3 -0
  100. package/src/common/search-input.tsx +7 -6
  101. package/src/common/stepper.tsx +100 -0
  102. package/src/common/types.ts +39 -0
  103. package/src/content/attachment-list.tsx +90 -0
  104. package/src/content/content-block.tsx +4 -2
  105. package/src/content/file-upload-zone.tsx +1 -6
  106. package/src/content/index.ts +3 -0
  107. package/src/content/types.ts +41 -0
  108. package/src/curriculum/curriculum-item.tsx +7 -3
  109. package/src/feedback/feedback-banner.tsx +12 -14
  110. package/src/flashcards/flashcard-deck.tsx +1 -9
  111. package/src/flashcards/flashcard.tsx +1 -1
  112. package/src/modules/AssignmentModule/AssignmentModule.tsx +305 -0
  113. package/src/modules/AssignmentModule/types.ts +73 -0
  114. package/src/modules/CertificateModule/CertificateModule.tsx +161 -0
  115. package/src/modules/CertificateModule/types.ts +47 -0
  116. package/src/modules/CoursePlayer/CoursePlayer.tsx +44 -48
  117. package/src/modules/DiscussionModule/DiscussionModule.tsx +110 -0
  118. package/src/modules/DiscussionModule/types.ts +54 -0
  119. package/src/modules/ExamModule/ExamModule.tsx +285 -0
  120. package/src/modules/ExamModule/types.ts +66 -0
  121. package/src/modules/FlashcardLab/FlashcardLab.tsx +29 -16
  122. package/src/modules/GradeCenterModule/GradeCenterModule.tsx +169 -0
  123. package/src/modules/GradeCenterModule/types.ts +63 -0
  124. package/src/modules/QuizModule/QuizModule.tsx +88 -88
  125. package/src/modules/QuizModule/types.ts +6 -1
  126. package/src/modules/SurveyModule/SurveyModule.tsx +180 -0
  127. package/src/modules/SurveyModule/types.ts +51 -0
  128. package/src/modules/index.ts +24 -0
  129. package/src/progress/achievement-badge.tsx +52 -0
  130. package/src/progress/activity-timeline.tsx +84 -0
  131. package/src/progress/index.ts +7 -0
  132. package/src/progress/stat-card.tsx +30 -18
  133. package/src/progress/streak-badge.tsx +35 -0
  134. package/src/progress/types.ts +101 -0
  135. package/src/questions/choice.tsx +7 -9
  136. package/src/questions/essay.tsx +23 -25
  137. package/src/questions/fill-in-the-blank.tsx +13 -16
  138. package/src/questions/hotspot.tsx +154 -0
  139. package/src/questions/index.ts +16 -0
  140. package/src/questions/inline-choice.tsx +151 -0
  141. package/src/questions/matching.tsx +228 -0
  142. package/src/questions/multiple-choice.tsx +7 -9
  143. package/src/questions/numeric.tsx +102 -0
  144. package/src/questions/ordering.tsx +159 -0
  145. package/src/questions/question-renderer.tsx +21 -0
  146. package/src/questions/scenario.tsx +140 -0
  147. package/src/questions/scoring.ts +201 -0
  148. package/src/questions/spreadsheet.tsx +259 -0
  149. package/src/questions/true-false.tsx +7 -9
  150. package/src/questions/types.ts +123 -1
  151. package/src/questions/use-drag-reorder.ts +80 -0
  152. package/src/sections/AnnouncementFeed/AnnouncementFeed.tsx +2 -15
  153. package/src/sections/AssessmentReview/AssessmentReview.tsx +13 -2
  154. package/src/sections/AssignmentSubmission/AssignmentSubmission.tsx +7 -5
  155. package/src/sections/CertificateViewer/CertificateViewer.tsx +409 -56
  156. package/src/sections/CertificateViewer/types.ts +13 -5
  157. package/src/sections/CourseOutline/CourseOutline.tsx +4 -14
  158. package/src/sections/DiscussionThread/DiscussionThread.tsx +13 -10
  159. package/src/sections/ExamSession/ExamSession.tsx +44 -7
  160. package/src/sections/ExamSession/types.ts +6 -1
  161. package/src/sections/ForumBoard/ForumBoard.tsx +284 -0
  162. package/src/sections/ForumBoard/types.ts +67 -0
  163. package/src/sections/GradebookTable/GradebookTable.tsx +1 -1
  164. package/src/sections/LecturePlayer/LecturePlayer.tsx +1 -1
  165. package/src/sections/LessonPage/LessonPage.tsx +5 -9
  166. package/src/sections/PracticeQuiz/PracticeQuiz.tsx +15 -26
  167. package/src/sections/ProgressDashboard/ProgressDashboard.tsx +65 -65
  168. package/src/sections/QuizSession/QuizSession.tsx +67 -8
  169. package/src/sections/QuizSession/types.ts +6 -1
  170. package/src/sections/RequirementsChecklist/RequirementsChecklist.tsx +107 -0
  171. package/src/sections/RequirementsChecklist/types.ts +38 -0
  172. package/src/sections/ResourceLibrary/ResourceLibrary.tsx +4 -9
  173. package/src/sections/RubricView/RubricView.tsx +138 -0
  174. package/src/sections/RubricView/types.ts +52 -0
  175. package/src/sections/ScrollableQuiz/ScrollableQuiz.tsx +23 -9
  176. package/src/sections/SurveyForm/SurveyForm.tsx +8 -5
  177. package/src/sections/index.ts +20 -1
  178. package/src/social/post-card.tsx +8 -19
  179. package/src/social/user-avatar.tsx +1 -0
  180. package/src/styles/globals.css +13 -0
  181. package/src/ui/drawer.tsx +600 -0
  182. package/src/ui/index.ts +19 -0
  183. package/src/ui/rich-text-editor.tsx +109 -0
  184. package/src/ui/rich-text-toolbar.tsx +156 -0
  185. package/src/utils/array-utils.ts +17 -0
  186. package/src/utils/flatten-leaves.ts +17 -0
  187. package/src/utils/format-file-size.ts +5 -0
  188. package/src/utils/format-timestamp.ts +13 -0
  189. package/src/utils/is-empty-html.ts +7 -0
  190. package/src/utils/shuffle.ts +8 -0
  191. package/src/utils/string-utils.ts +30 -0
  192. package/src/video/video-bookmark.tsx +4 -3
  193. package/src/video/video-chapter-list.tsx +9 -4
  194. package/src/video/video-player.tsx +11 -4
  195. package/src/video/video-playlist-item.tsx +8 -3
  196. package/src/video/video-thumbnail-card.tsx +4 -0
  197. package/src/video/video-transcript.tsx +8 -5
  198. package/dist/table-BrS5cDQu.js +0 -2510
  199. package/dist/table-D6AkBBEo.cjs +0 -1
@@ -0,0 +1,6 @@
1
+ import { AchievementBadgeProps } from './types';
2
+ /**
3
+ * AchievementBadge displays a single achievement or badge earned by a learner,
4
+ * with support for locked/earned states and metal-tier variants.
5
+ */
6
+ export declare function AchievementBadge({ title, description, icon, earnedDate, locked, variant, className, style, }: AchievementBadgeProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { ActivityTimelineProps } from './types';
2
+ /**
3
+ * ActivityTimeline renders a vertical timeline of activity events
4
+ * with icons, timestamps, and an optional "load more" action.
5
+ */
6
+ export declare function ActivityTimeline({ events, limit, showLoadMore, onLoadMore, emptyMessage, className, style, }: ActivityTimelineProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,7 @@
1
1
  export { ProgressRing } from './progress-ring';
2
2
  export { GradeIndicator } from './grade-indicator';
3
3
  export { StatCard } from './stat-card';
4
- export type { ProgressRingProps, GradeIndicatorProps, StatCardProps, } from './types';
4
+ export { AchievementBadge } from './achievement-badge';
5
+ export { StreakBadge } from './streak-badge';
6
+ export { ActivityTimeline } from './activity-timeline';
7
+ export type { ProgressRingProps, GradeIndicatorProps, StatCardProps, AchievementBadgeProps, StreakBadgeProps, ActivityTimelineProps, TimelineEvent, } from './types';
@@ -1,2 +1,2 @@
1
1
  import { StatCardProps } from './types';
2
- export declare function StatCard({ icon, label, value, subtitle, trend, className, style, }: StatCardProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare const StatCard: import('react').NamedExoticComponent<StatCardProps>;
@@ -0,0 +1,6 @@
1
+ import { StreakBadgeProps } from './types';
2
+ /**
3
+ * StreakBadge displays a compact learning streak indicator with
4
+ * a fire icon and day count.
5
+ */
6
+ export declare function StreakBadge({ currentStreak, longestStreak, unit, showLongest, className, style, }: StreakBadgeProps): import("react/jsx-runtime").JSX.Element;
@@ -57,6 +57,8 @@ export interface StatCardProps {
57
57
  icon?: ReactNode;
58
58
  /** Stat label */
59
59
  label: string;
60
+ /** Short description displayed below the label */
61
+ description?: string;
60
62
  /** Stat value */
61
63
  value: string | number;
62
64
  /** Secondary text below the value */
@@ -71,3 +73,98 @@ export interface StatCardProps {
71
73
  /** Inline styles for the root element */
72
74
  style?: React.CSSProperties;
73
75
  }
76
+ /**
77
+ * AchievementBadge displays a single achievement or badge earned by a learner,
78
+ * with support for locked/earned states and metal-tier variants.
79
+ *
80
+ * @example
81
+ * <AchievementBadge
82
+ * title="Quiz Master"
83
+ * description="Pass 10 quizzes with 90%+ score"
84
+ * variant="gold"
85
+ * earnedDate="2025-12-01T00:00:00Z"
86
+ * />
87
+ */
88
+ export interface AchievementBadgeProps {
89
+ /** Achievement title */
90
+ title: string;
91
+ /** Optional description of how to earn the achievement */
92
+ description?: string;
93
+ /** Custom icon to display. Falls back to Trophy icon */
94
+ icon?: ReactNode;
95
+ /** ISO date string of when the achievement was earned */
96
+ earnedDate?: string;
97
+ /** Whether the achievement is locked (not yet earned). @default false */
98
+ locked?: boolean;
99
+ /** Visual tier variant. @default 'default' */
100
+ variant?: "default" | "gold" | "silver" | "bronze";
101
+ /** CSS class name for the root element */
102
+ className?: string;
103
+ /** Inline styles for the root element */
104
+ style?: React.CSSProperties;
105
+ }
106
+ /**
107
+ * StreakBadge displays a compact learning streak indicator with
108
+ * a fire icon and day count.
109
+ *
110
+ * @example
111
+ * <StreakBadge currentStreak={7} longestStreak={14} showLongest />
112
+ */
113
+ export interface StreakBadgeProps {
114
+ /** Current active streak count */
115
+ currentStreak: number;
116
+ /** All-time longest streak count */
117
+ longestStreak?: number;
118
+ /** Unit label for the streak count. @default "days" */
119
+ unit?: string;
120
+ /** Whether to show the longest streak subtitle. @default false */
121
+ showLongest?: boolean;
122
+ /** CSS class name for the root element */
123
+ className?: string;
124
+ /** Inline styles for the root element */
125
+ style?: React.CSSProperties;
126
+ }
127
+ /**
128
+ * A single event in an ActivityTimeline.
129
+ */
130
+ export interface TimelineEvent {
131
+ /** Unique identifier */
132
+ uid: string;
133
+ /** Event type — used for default icon selection */
134
+ type: string;
135
+ /** Event title */
136
+ title: string;
137
+ /** Optional longer description */
138
+ description?: string;
139
+ /** ISO 8601 timestamp */
140
+ timestamp: string;
141
+ /** Optional custom icon (overrides type-based default) */
142
+ icon?: ReactNode;
143
+ }
144
+ /**
145
+ * ActivityTimeline renders a vertical timeline of activity events
146
+ * with icons, timestamps, and an optional "load more" action.
147
+ *
148
+ * @example
149
+ * <ActivityTimeline
150
+ * events={[
151
+ * { uid: "1", type: "lesson_completed", title: "Completed Lesson 3", timestamp: "2025-03-01T12:00:00Z" },
152
+ * ]}
153
+ * />
154
+ */
155
+ export interface ActivityTimelineProps {
156
+ /** List of activity events to display */
157
+ events: TimelineEvent[];
158
+ /** Maximum number of events to display. When set, truncates the list. */
159
+ limit?: number;
160
+ /** Whether to show a "Load more" button at the bottom. @default false */
161
+ showLoadMore?: boolean;
162
+ /** Called when the user clicks "Load more" */
163
+ onLoadMore?: () => void;
164
+ /** Message displayed when the events list is empty. @default "No recent activity" */
165
+ emptyMessage?: string;
166
+ /** CSS class name for the root element */
167
+ className?: string;
168
+ /** Inline styles for the root element */
169
+ style?: React.CSSProperties;
170
+ }
@@ -1,6 +1,6 @@
1
1
  import { QuestionProps } from './types';
2
2
  /**
3
- * Essay renders a long-form text input question with a multiline textarea.
3
+ * Essay renders a long-form rich text input question.
4
4
  *
5
5
  * @example
6
6
  * <Essay
@@ -0,0 +1,21 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * Hotspot renders an image with clickable regions for selection.
4
+ *
5
+ * Regions are positioned using percentage-based coordinates so they scale with the image.
6
+ *
7
+ * @example
8
+ * <Hotspot
9
+ * question={{
10
+ * uid: "q1",
11
+ * type: "hotspot",
12
+ * content: "Click on the heart.",
13
+ * hotspotImageUrl: "/anatomy.png",
14
+ * hotspotRegions: [
15
+ * { uid: "r1", shape: "circle", coords: [50, 40, 8], isCorrect: true, label: "Heart" },
16
+ * ],
17
+ * }}
18
+ * onAnswer={(answers) => handleAnswer(answers)}
19
+ * />
20
+ */
21
+ export declare const Hotspot: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -4,4 +4,12 @@ export { Choice } from './choice';
4
4
  export { TrueFalse } from './true-false';
5
5
  export { FillInTheBlank } from './fill-in-the-blank';
6
6
  export { Essay } from './essay';
7
- export type { QuestionProps, QuestionData, QuestionTypeEnum, AnswerOption, SessionAnswer, } from './types';
7
+ export { Numeric } from './numeric';
8
+ export { Ordering } from './ordering';
9
+ export { Matching } from './matching';
10
+ export { Hotspot } from './hotspot';
11
+ export { InlineChoice } from './inline-choice';
12
+ export { Scenario } from './scenario';
13
+ export { Spreadsheet } from './spreadsheet';
14
+ export { scoreQuestion, scoreScenarioSubQuestions } from './scoring';
15
+ export type { QuestionProps, QuestionData, QuestionTypeEnum, QuestionMaterial, AnswerOption, SessionAnswer, MatchingPair, HotspotRegion, InlineBlank, ScenarioScoringMode, SpreadsheetColumn, SpreadsheetCell, SpreadsheetRow, } from './types';
@@ -0,0 +1,21 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * InlineChoice renders a cloze-style passage with embedded dropdown blanks.
4
+ *
5
+ * Content should contain `{{blank:uid}}` markers that correspond to entries in `question.inlineBlanks`.
6
+ *
7
+ * @example
8
+ * <InlineChoice
9
+ * question={{
10
+ * uid: "q1",
11
+ * type: "inline_choice",
12
+ * content: "The capital of France is {{blank:b1}}.",
13
+ * inlineBlanks: [{ uid: "b1", sequence: 0, options: [
14
+ * { uid: "o1", content: "Paris", isCorrect: true },
15
+ * { uid: "o2", content: "London" },
16
+ * ]}],
17
+ * }}
18
+ * onAnswer={(answers) => handleAnswer(answers)}
19
+ * />
20
+ */
21
+ export declare const InlineChoice: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * Matching renders a two-column matching question with dropdown selects and optional drag-and-drop.
4
+ *
5
+ * Each item (left column) must be matched to its correct target (right column).
6
+ * The dropdown is the primary accessible interaction; drag-and-drop is progressive enhancement.
7
+ *
8
+ * @example
9
+ * <Matching
10
+ * question={{
11
+ * uid: "q1",
12
+ * type: "matching",
13
+ * content: "Match each country to its capital.",
14
+ * matchingPairs: [
15
+ * { uid: "p1", item: "France", target: "Paris", sequence: 0 },
16
+ * { uid: "p2", item: "Germany", target: "Berlin", sequence: 1 },
17
+ * ],
18
+ * }}
19
+ * onAnswer={(answers) => handleAnswer(answers)}
20
+ * />
21
+ */
22
+ export declare const Matching: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * Numeric renders a number input question with optional tolerance and unit display.
4
+ *
5
+ * @example
6
+ * <Numeric
7
+ * question={{ uid: "q1", type: "numeric", content: "What is pi to 2 decimal places?", numericAnswer: 3.14, numericTolerance: 0.01 }}
8
+ * onAnswer={(answers) => handleAnswer(answers)}
9
+ * />
10
+ */
11
+ export declare const Numeric: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * Ordering renders a drag-and-drop reorderable list of items.
4
+ * The correct order is determined by each answer's `sequence` field.
5
+ *
6
+ * @example
7
+ * <Ordering
8
+ * question={question}
9
+ * onAnswer={(answers) => handleAnswer(answers)}
10
+ * />
11
+ */
12
+ export declare const Ordering: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * Scenario renders a shared context/stimulus with multiple sub-questions.
4
+ *
5
+ * Sub-questions can be any existing question type (choice, numeric, matching, etc.).
6
+ * The shared context is displayed prominently above all sub-questions.
7
+ *
8
+ * @example
9
+ * <Scenario
10
+ * question={{
11
+ * uid: "s1",
12
+ * type: "scenario",
13
+ * content: "<p>Read the following passage and answer the questions below.</p>",
14
+ * scenarioQuestions: [
15
+ * { uid: "sq1", type: "choice", content: "What is the main idea?", answers: [...] },
16
+ * { uid: "sq2", type: "true_false", content: "The author agrees.", answers: [...] },
17
+ * ],
18
+ * scenarioScoringMode: "per_question",
19
+ * }}
20
+ * onAnswer={(answers) => handleAnswer(answers)}
21
+ * />
22
+ */
23
+ export declare const Scenario: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { QuestionData, SessionAnswer } from './types';
2
+ /**
3
+ * Scores a single question against the user's answers.
4
+ *
5
+ * @returns `true` if correct, `false` if incorrect, `null` if the question is not auto-gradable.
6
+ */
7
+ export declare function scoreQuestion(question: QuestionData, userAnswers: SessionAnswer[]): boolean | null;
8
+ /**
9
+ * Scores an entire set of questions against user answers.
10
+ *
11
+ * @returns An object with correct count, total gradable, and percentage.
12
+ */
13
+ export declare function scoreAssessment(questions: QuestionData[], answers: SessionAnswer[]): {
14
+ correct: number;
15
+ total: number;
16
+ percentage: number;
17
+ };
18
+ /**
19
+ * Scores individual sub-questions within a scenario.
20
+ * Returns a Map of sub-question UID to score (`true`/`false`/`null`).
21
+ */
22
+ export declare function scoreScenarioSubQuestions(question: QuestionData, userAnswers: SessionAnswer[]): Map<string, boolean | null>;
@@ -0,0 +1,29 @@
1
+ import { QuestionProps } from './types';
2
+ /**
3
+ * Spreadsheet renders a grid-based question for accounting and tabular data entry.
4
+ * Students fill in editable cells while locked cells display pre-filled values.
5
+ * Each cell is graded independently with support for numeric tolerance.
6
+ *
7
+ * @example
8
+ * <Spreadsheet
9
+ * question={{
10
+ * uid: "q1",
11
+ * type: "spreadsheet",
12
+ * content: "Complete the trial balance:",
13
+ * spreadsheetColumns: [
14
+ * { uid: "col-acct", label: "Account", type: "text", width: 14 },
15
+ * { uid: "col-dr", label: "Debit ($)", type: "currency", width: 9 },
16
+ * { uid: "col-cr", label: "Credit ($)", type: "currency", width: 9 },
17
+ * ],
18
+ * spreadsheetRows: [
19
+ * { uid: "r1", cells: [
20
+ * { uid: "r1-acct", columnUid: "col-acct", locked: true, value: "Cash" },
21
+ * { uid: "r1-dr", columnUid: "col-dr", locked: false, correctAnswer: "5000" },
22
+ * { uid: "r1-cr", columnUid: "col-cr", locked: true, value: "" },
23
+ * ]},
24
+ * ],
25
+ * }}
26
+ * onAnswer={(answers) => handleAnswer(answers)}
27
+ * />
28
+ */
29
+ export declare const Spreadsheet: ({ question, sessionAnswers, onAnswer, readOnly, showCorrectAnswers, disabled, }: QuestionProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,6 @@
1
- export type QuestionTypeEnum = "multiple_choice" | "choice" | "true_false" | "fill_in_the_blank" | "essay";
1
+ export type QuestionTypeEnum = "multiple_choice" | "choice" | "true_false" | "fill_in_the_blank" | "essay" | "matching" | "ordering" | "numeric" | "hotspot" | "inline_choice" | "scenario" | "spreadsheet";
2
+ /** Scoring strategy for scenario questions. */
3
+ export type ScenarioScoringMode = "per_question" | "all_or_nothing";
2
4
  export interface AnswerOption {
3
5
  uid: string;
4
6
  content: string;
@@ -12,12 +14,115 @@ export interface SessionAnswer {
12
14
  content?: string;
13
15
  confidence?: string;
14
16
  }
17
+ /** A pair linking a left-side item to its correct right-side target. */
18
+ export interface MatchingPair {
19
+ uid: string;
20
+ /** Left-side item content (HTML) */
21
+ item: string;
22
+ /** Right-side target content (HTML) */
23
+ target: string;
24
+ sequence: number;
25
+ }
26
+ /** A clickable region on a hotspot image. Coordinates are percentages (0–100). */
27
+ export interface HotspotRegion {
28
+ uid: string;
29
+ shape: "rect" | "circle";
30
+ /** rect: [x, y, width, height]; circle: [centerX, centerY, radius] */
31
+ coords: number[];
32
+ isCorrect?: boolean;
33
+ label?: string;
34
+ }
35
+ /** A dropdown blank embedded in an inline-choice (cloze) passage. */
36
+ export interface InlineBlank {
37
+ uid: string;
38
+ options: {
39
+ uid: string;
40
+ content: string;
41
+ isCorrect?: boolean;
42
+ }[];
43
+ sequence: number;
44
+ }
45
+ /** A column definition for a spreadsheet question. */
46
+ export interface SpreadsheetColumn {
47
+ uid: string;
48
+ /** Column header text */
49
+ label: string;
50
+ /** Data type hint for input rendering and scoring */
51
+ type: "text" | "numeric" | "currency";
52
+ /** Column width in rems (default 8) */
53
+ width?: number;
54
+ }
55
+ /** A single cell in a spreadsheet row. */
56
+ export interface SpreadsheetCell {
57
+ /** Unique identifier — becomes the answerUid in SessionAnswer */
58
+ uid: string;
59
+ /** Which column this cell belongs to */
60
+ columnUid: string;
61
+ /** When true, cell is pre-filled and not editable */
62
+ locked: boolean;
63
+ /** Display value for locked cells, or pre-fill for editable cells */
64
+ value?: string;
65
+ /** Expected answer for grading (editable cells only) */
66
+ correctAnswer?: string;
67
+ /** Acceptable numeric deviation (default 0 = exact match) */
68
+ tolerance?: number;
69
+ /** Hint shown in review mode (e.g., "= Revenue – Expenses") */
70
+ formula?: string;
71
+ }
72
+ /** A row in a spreadsheet question grid. */
73
+ export interface SpreadsheetRow {
74
+ uid: string;
75
+ /** Optional row header label (e.g., "Cash", "Accounts Receivable") */
76
+ label?: string;
77
+ /** Ordered cells — one per column */
78
+ cells: SpreadsheetCell[];
79
+ /** Renders as a bold section divider row */
80
+ isHeader?: boolean;
81
+ /** Renders in table footer with top border */
82
+ isTotals?: boolean;
83
+ }
84
+ /** Content blocks associated with a question for open-book reference. */
85
+ export interface QuestionMaterial {
86
+ /** UID of the question this material is linked to */
87
+ questionUid: string;
88
+ /** Display label for the material group (e.g., "Chapter 3: Bonds") */
89
+ label?: string;
90
+ /** Content blocks to render in the materials drawer */
91
+ blocks: import('../content/types').LessonBlock[];
92
+ }
15
93
  export interface QuestionData {
16
94
  uid: string;
17
95
  type: QuestionTypeEnum;
96
+ /** Question prompt (HTML) */
18
97
  content: string;
98
+ /** Explanation shown in review mode (HTML) */
19
99
  explanation?: string;
100
+ /** Answer options for choice / multiple_choice / true_false / ordering */
20
101
  answers?: AnswerOption[];
102
+ /** Matching-specific: pairs of items and targets */
103
+ matchingPairs?: MatchingPair[];
104
+ /** Numeric-specific: correct answer */
105
+ numericAnswer?: number;
106
+ /** Numeric-specific: acceptable deviation (default 0 = exact) */
107
+ numericTolerance?: number;
108
+ /** Numeric-specific: unit label displayed after input */
109
+ numericUnit?: string;
110
+ /** Hotspot-specific: image URL */
111
+ hotspotImageUrl?: string;
112
+ /** Hotspot-specific: clickable regions */
113
+ hotspotRegions?: HotspotRegion[];
114
+ /** Hotspot-specific: allow selecting multiple regions */
115
+ hotspotMultiSelect?: boolean;
116
+ /** InlineChoice-specific: dropdown blanks embedded in content */
117
+ inlineBlanks?: InlineBlank[];
118
+ /** Scenario-specific: sub-questions grouped under this scenario's shared context */
119
+ scenarioQuestions?: QuestionData[];
120
+ /** Scenario-specific: how the scenario is scored (default "per_question") */
121
+ scenarioScoringMode?: ScenarioScoringMode;
122
+ /** Spreadsheet-specific: column definitions */
123
+ spreadsheetColumns?: SpreadsheetColumn[];
124
+ /** Spreadsheet-specific: row data with cells */
125
+ spreadsheetRows?: SpreadsheetRow[];
21
126
  }
22
127
  /**
23
128
  * Shared props interface for all question type components.
@@ -0,0 +1,17 @@
1
+ interface UseDragReorderOptions<T> {
2
+ items: T[];
3
+ onReorder: (items: T[]) => void;
4
+ disabled?: boolean;
5
+ }
6
+ export declare function useDragReorder<T>({ items, onReorder, disabled, }: UseDragReorderOptions<T>): {
7
+ getDragProps: (index: number) => {
8
+ draggable: boolean;
9
+ onDragStart: (e: React.DragEvent) => void;
10
+ onDragOver: (e: React.DragEvent) => void;
11
+ onDrop: (e: React.DragEvent) => void;
12
+ onDragEnd: () => void;
13
+ };
14
+ dragIndex: number | null;
15
+ dragOverIndex: number | null;
16
+ };
17
+ export {};
@@ -1,9 +1,11 @@
1
+ /** Available certificate visual styles */
2
+ export type CertificateVariant = "classic" | "modern" | "elegant" | "academic" | "minimal" | "bold";
1
3
  /**
2
4
  * CertificateViewer section — a printable completion certificate.
3
5
  *
4
6
  * Displays a certificate with recipient details, course information,
5
- * signatory, and verification ID. Supports three visual variants:
6
- * classic, modern, and minimal.
7
+ * signatory, and verification ID. Supports six visual variants:
8
+ * classic, modern, elegant, academic, minimal, and bold.
7
9
  *
8
10
  * @example
9
11
  * <CertificateViewer
@@ -11,7 +13,7 @@
11
13
  * courseTitle="Advanced React"
12
14
  * completionDate="2025-03-01"
13
15
  * organizationName="HydraLMS Academy"
14
- * variant="modern"
16
+ * variant="elegant"
15
17
  * />
16
18
  */
17
19
  export interface CertificateViewerProps {
@@ -32,8 +34,8 @@ export interface CertificateViewerProps {
32
34
  };
33
35
  /** Unique certificate ID */
34
36
  certificateId?: string;
35
- /** Certificate template variant */
36
- variant?: "classic" | "modern" | "minimal";
37
+ /** Certificate template variant @default "classic" */
38
+ variant?: CertificateVariant;
37
39
  /** Whether to show print/download actions */
38
40
  showActions?: boolean;
39
41
  /** Called when print is triggered */
@@ -1,2 +1,2 @@
1
1
  import { ExamSessionProps } from './types';
2
- export declare function ExamSession({ questions, initialAnswers, onSubmit, onAnswerChange, timeLimitSeconds, timeElapsedSeconds, autoSubmitOnTimeout, timeWarningThreshold, allowBackNavigation, confirmBeforeSubmit, examTitle, instructions, isSubmitting, readOnly, className, style, }: ExamSessionProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ExamSession({ questions, initialAnswers, onSubmit, onAnswerChange, timeLimitSeconds, timeElapsedSeconds, autoSubmitOnTimeout, timeWarningThreshold, allowBackNavigation, confirmBeforeSubmit, examTitle, instructions, questionMaterials, isSubmitting, readOnly, className, style, }: ExamSessionProps): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { QuestionData, SessionAnswer } from '../../questions/types';
2
+ import { QuestionData, QuestionMaterial, SessionAnswer } from '../../questions/types';
3
3
  /**
4
4
  * ExamSession section — a formal timed exam experience.
5
5
  *
@@ -43,6 +43,11 @@ export interface ExamSessionProps {
43
43
  instructions?: ReactNode;
44
44
  /** Whether the submit action is in flight */
45
45
  isSubmitting?: boolean;
46
+ /**
47
+ * Related materials keyed by question UID. When provided, a "Materials"
48
+ * button appears in the question header, opening a drawer with content blocks.
49
+ */
50
+ questionMaterials?: QuestionMaterial[];
46
51
  /** When true, all inputs are disabled */
47
52
  readOnly?: boolean;
48
53
  /** CSS class name for the root element */
@@ -0,0 +1,8 @@
1
+ import { ForumBoardProps } from './types';
2
+ /**
3
+ * ForumBoard — a topic listing view for a discussion forum.
4
+ *
5
+ * Displays a searchable, sortable list of discussion topics with author info,
6
+ * reply/like counts, timestamps, and new topic creation.
7
+ */
8
+ export declare function ForumBoard({ title, topics, onTopicClick, onCreateTopic, sortOrder, onSortChange, searchQuery, onSearchChange, readOnly, className, style, }: ForumBoardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,64 @@
1
+ import { DiscussionUser } from '../DiscussionThread/types';
2
+ export type ForumSortOrder = "newest" | "oldest" | "most_replies" | "most_liked";
3
+ /**
4
+ * ForumBoard section — a topic listing view for a discussion forum.
5
+ *
6
+ * Displays a searchable, sortable list of discussion topics with author info,
7
+ * reply/like counts, and timestamps. Supports creating new topics inline.
8
+ *
9
+ * @example
10
+ * <ForumBoard
11
+ * title="Class Discussion"
12
+ * topics={topics}
13
+ * onTopicClick={(uid) => openThread(uid)}
14
+ * onCreateTopic={(title, content) => createTopic(title, content)}
15
+ * />
16
+ */
17
+ export interface ForumBoardProps {
18
+ /** Forum title */
19
+ title?: string;
20
+ /** List of discussion topics */
21
+ topics: ForumTopic[];
22
+ /** The currently authenticated user (reserved for future use) */
23
+ currentUser?: DiscussionUser;
24
+ /** Called when a topic is clicked */
25
+ onTopicClick: (topicUid: string) => void;
26
+ /** Called when a new topic is created */
27
+ onCreateTopic?: (title: string, content: string) => void;
28
+ /** Current sort order */
29
+ sortOrder?: ForumSortOrder;
30
+ /** Called when sort order changes */
31
+ onSortChange?: (sort: ForumSortOrder) => void;
32
+ /** Current search query (controlled) */
33
+ searchQuery?: string;
34
+ /** Called when search query changes */
35
+ onSearchChange?: (query: string) => void;
36
+ /** When true, disables create and interactions */
37
+ readOnly?: boolean;
38
+ /** CSS class name for the root element */
39
+ className?: string;
40
+ /** Inline styles for the root element */
41
+ style?: React.CSSProperties;
42
+ }
43
+ export interface ForumTopic {
44
+ /** Unique identifier */
45
+ uid: string;
46
+ /** Topic title */
47
+ title: string;
48
+ /** Topic author */
49
+ author: DiscussionUser;
50
+ /** Creation timestamp */
51
+ createdAt: string;
52
+ /** Number of replies */
53
+ replyCount: number;
54
+ /** Number of likes */
55
+ likeCount: number;
56
+ /** Timestamp of the most recent reply */
57
+ lastReplyAt?: string;
58
+ /** Whether this topic is pinned to the top */
59
+ isPinned?: boolean;
60
+ /** Whether this topic has a marked answer */
61
+ isAnswered?: boolean;
62
+ /** Preview text (first ~100 chars of content) */
63
+ preview?: string;
64
+ }
@@ -1,2 +1,2 @@
1
1
  import { QuizSessionProps } from './types';
2
- export declare function QuizSession({ questions, initialAnswers, onSubmit, onAnswerChange, timeElapsedSeconds, timeLimitSeconds, isSubmitting, readOnly, className, style, }: QuizSessionProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function QuizSession({ questions, initialAnswers, onSubmit, onAnswerChange, timeElapsedSeconds, timeLimitSeconds, questionMaterials, isSubmitting, readOnly, className, style, }: QuizSessionProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { QuestionData, SessionAnswer } from '../../questions/types';
1
+ import { QuestionData, QuestionMaterial, SessionAnswer } from '../../questions/types';
2
2
  /**
3
3
  * QuizSession section — a complete assessment session experience.
4
4
  *
@@ -37,6 +37,11 @@ export interface QuizSessionProps {
37
37
  timeLimitSeconds?: number;
38
38
  /** Whether the submit action is currently in flight */
39
39
  isSubmitting?: boolean;
40
+ /**
41
+ * Related materials keyed by question UID. When provided, a "Materials"
42
+ * button appears in the question header, opening a drawer with content blocks.
43
+ */
44
+ questionMaterials?: QuestionMaterial[];
40
45
  /** When true, all inputs are disabled (e.g. after submission) */
41
46
  readOnly?: boolean;
42
47
  /** CSS class name for the root element */
@@ -0,0 +1,8 @@
1
+ import { RequirementsChecklistProps } from './types';
2
+ /**
3
+ * RequirementsChecklist — shows completion requirements with checked/unchecked status.
4
+ *
5
+ * Displays a vertical list of requirements with an overall progress bar.
6
+ * Incomplete items can be clicked to navigate to the relevant content.
7
+ */
8
+ export declare function RequirementsChecklist({ title, requirements, onRequirementClick, className, style, }: RequirementsChecklistProps): import("react/jsx-runtime").JSX.Element;