@hydralms/components 0.1.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 (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -0
  3. package/dist/assessment-toolbar/assessment-toolbar.d.ts +2 -0
  4. package/dist/assessment-toolbar/index.d.ts +4 -0
  5. package/dist/assessment-toolbar/question-navigator.d.ts +2 -0
  6. package/dist/assessment-toolbar/timer-display.d.ts +2 -0
  7. package/dist/assessment-toolbar/types.d.ts +89 -0
  8. package/dist/common/confirm-dialog.d.ts +2 -0
  9. package/dist/common/due-date-display.d.ts +2 -0
  10. package/dist/common/empty-state.d.ts +2 -0
  11. package/dist/common/index.d.ts +6 -0
  12. package/dist/common/search-input.d.ts +2 -0
  13. package/dist/common/status-badge.d.ts +2 -0
  14. package/dist/common/types.d.ts +124 -0
  15. package/dist/components.css +1 -0
  16. package/dist/content/content-block.d.ts +2 -0
  17. package/dist/content/file-upload-zone.d.ts +2 -0
  18. package/dist/content/index.d.ts +3 -0
  19. package/dist/content/types.d.ts +95 -0
  20. package/dist/curriculum/curriculum-item.d.ts +2 -0
  21. package/dist/curriculum/curriculum-tree.d.ts +2 -0
  22. package/dist/curriculum/index.d.ts +4 -0
  23. package/dist/curriculum/learning-object-icon.d.ts +2 -0
  24. package/dist/curriculum/types.d.ts +79 -0
  25. package/dist/feedback/feedback-banner.d.ts +2 -0
  26. package/dist/feedback/index.d.ts +4 -0
  27. package/dist/feedback/likert-scale.d.ts +2 -0
  28. package/dist/feedback/star-rating.d.ts +2 -0
  29. package/dist/feedback/types.d.ts +83 -0
  30. package/dist/flashcards/flashcard-deck.d.ts +2 -0
  31. package/dist/flashcards/flashcard.d.ts +2 -0
  32. package/dist/flashcards/index.d.ts +3 -0
  33. package/dist/flashcards/types.d.ts +58 -0
  34. package/dist/index.cjs +1 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.js +159 -0
  37. package/dist/lib/utils.d.ts +2 -0
  38. package/dist/progress/grade-indicator.d.ts +2 -0
  39. package/dist/progress/index.d.ts +4 -0
  40. package/dist/progress/progress-ring.d.ts +2 -0
  41. package/dist/progress/stat-card.d.ts +2 -0
  42. package/dist/progress/types.d.ts +73 -0
  43. package/dist/provider/HydraProvider.d.ts +9 -0
  44. package/dist/provider/index.d.ts +2 -0
  45. package/dist/questions/choice.d.ts +11 -0
  46. package/dist/questions/essay.d.ts +11 -0
  47. package/dist/questions/fill-in-the-blank.d.ts +11 -0
  48. package/dist/questions/index.d.ts +7 -0
  49. package/dist/questions/multiple-choice.d.ts +11 -0
  50. package/dist/questions/question-renderer.d.ts +12 -0
  51. package/dist/questions/true-false.d.ts +11 -0
  52. package/dist/questions/types.d.ts +47 -0
  53. package/dist/sections/AnnouncementFeed/AnnouncementFeed.d.ts +2 -0
  54. package/dist/sections/AnnouncementFeed/types.d.ts +52 -0
  55. package/dist/sections/AssessmentReview/AssessmentReview.d.ts +2 -0
  56. package/dist/sections/AssessmentReview/types.d.ts +58 -0
  57. package/dist/sections/AssignmentSubmission/AssignmentSubmission.d.ts +2 -0
  58. package/dist/sections/AssignmentSubmission/types.d.ts +65 -0
  59. package/dist/sections/CertificateViewer/CertificateViewer.d.ts +2 -0
  60. package/dist/sections/CertificateViewer/types.d.ts +47 -0
  61. package/dist/sections/CourseOutline/CourseOutline.d.ts +2 -0
  62. package/dist/sections/CourseOutline/types.d.ts +49 -0
  63. package/dist/sections/DiscussionThread/DiscussionThread.d.ts +2 -0
  64. package/dist/sections/DiscussionThread/types.d.ts +74 -0
  65. package/dist/sections/ExamSession/ExamSession.d.ts +2 -0
  66. package/dist/sections/ExamSession/types.d.ts +62 -0
  67. package/dist/sections/FlashcardStudySession/FlashcardStudySession.d.ts +2 -0
  68. package/dist/sections/FlashcardStudySession/types.d.ts +40 -0
  69. package/dist/sections/GradebookTable/GradebookTable.d.ts +2 -0
  70. package/dist/sections/GradebookTable/types.d.ts +71 -0
  71. package/dist/sections/LecturePlayer/LecturePlayer.d.ts +2 -0
  72. package/dist/sections/LecturePlayer/types.d.ts +47 -0
  73. package/dist/sections/LessonPage/LessonPage.d.ts +2 -0
  74. package/dist/sections/LessonPage/types.d.ts +40 -0
  75. package/dist/sections/PracticeQuiz/PracticeQuiz.d.ts +2 -0
  76. package/dist/sections/PracticeQuiz/types.d.ts +42 -0
  77. package/dist/sections/ProgressDashboard/ProgressDashboard.d.ts +2 -0
  78. package/dist/sections/ProgressDashboard/types.d.ts +73 -0
  79. package/dist/sections/QuizSession/QuizSession.d.ts +2 -0
  80. package/dist/sections/QuizSession/types.d.ts +46 -0
  81. package/dist/sections/ResourceLibrary/ResourceLibrary.d.ts +2 -0
  82. package/dist/sections/ResourceLibrary/types.d.ts +58 -0
  83. package/dist/sections/ScrollableQuiz/ScrollableQuiz.d.ts +2 -0
  84. package/dist/sections/ScrollableQuiz/types.d.ts +42 -0
  85. package/dist/sections/SurveyForm/SurveyForm.d.ts +2 -0
  86. package/dist/sections/SurveyForm/types.d.ts +69 -0
  87. package/dist/sections/index.d.ts +34 -0
  88. package/dist/sections.cjs +1 -0
  89. package/dist/sections.js +1898 -0
  90. package/dist/social/index.d.ts +3 -0
  91. package/dist/social/post-card.d.ts +2 -0
  92. package/dist/social/types.d.ts +59 -0
  93. package/dist/social/user-avatar.d.ts +2 -0
  94. package/dist/table-CW4_BYny.js +9869 -0
  95. package/dist/table-DSBBqb9X.cjs +56 -0
  96. package/dist/ui/alert-dialog.d.ts +14 -0
  97. package/dist/ui/alert.d.ts +9 -0
  98. package/dist/ui/avatar.d.ts +5 -0
  99. package/dist/ui/badge.d.ts +9 -0
  100. package/dist/ui/button.d.ts +10 -0
  101. package/dist/ui/card.d.ts +9 -0
  102. package/dist/ui/index.d.ts +15 -0
  103. package/dist/ui/input.d.ts +3 -0
  104. package/dist/ui/progress.d.ts +13 -0
  105. package/dist/ui/separator.d.ts +6 -0
  106. package/dist/ui/skeleton.d.ts +3 -0
  107. package/dist/ui/slot.d.ts +8 -0
  108. package/dist/ui/table.d.ts +10 -0
  109. package/dist/ui/tabs.d.ts +7 -0
  110. package/dist/ui/textarea.d.ts +3 -0
  111. package/dist/ui/tooltip.d.ts +8 -0
  112. package/dist/utils/debounce.d.ts +1 -0
  113. package/dist/utils/format-duration.d.ts +2 -0
  114. package/dist/video/index.d.ts +2 -0
  115. package/dist/video/types.d.ts +37 -0
  116. package/dist/video/video-player.d.ts +2 -0
  117. package/package.json +94 -0
@@ -0,0 +1,1898 @@
1
+ import { jsxs as t, jsx as e, Fragment as ee } from "react/jsx-runtime";
2
+ import { useState as I, useMemo as $, useRef as ge, useEffect as ie, useCallback as Qe, Fragment as Be } from "react";
3
+ import { o as be, C as L, r as Q, V as X, c as F, ai as oe, u as $e, v as je, p as R, L as Ee, B as Ne, X as V, S as ne, D as _e, H as He, A as ve, a as we, x as Ve, P as Ye, Y as Ze, ab as te, an as ye, y as Je, W as Ke, ad as Z, af as J, ae as K, a7 as Se, a9 as ke, aa as W, F as ze, O as ue, ah as We, R as Xe, _ as Ce, E as Ue, a8 as se, I as me, N as he, M as Ge, $ as Oe, a5 as qe, a6 as le, a4 as Ae, a0 as et, a2 as Y, T as tt, Z as ae } from "./table-CW4_BYny.js";
4
+ import { CheckCircle as G, Clock as De, Check as fe, ChevronRight as nt, List as rt, Grid as st, Download as Te, Pin as lt, MessageSquare as at, Heart as it, Reply as dt, Save as ct, Send as Ie, ArrowUp as ot, ArrowDown as ut, Flame as mt, BookOpen as Fe, Award as Le, Trophy as ht, Printer as ft } from "lucide-react";
5
+ function Ct({
6
+ questions: r,
7
+ initialAnswers: s = [],
8
+ onSubmit: a,
9
+ onAnswerChange: c,
10
+ timeElapsedSeconds: p,
11
+ timeLimitSeconds: l,
12
+ isSubmitting: h = !1,
13
+ readOnly: i = !1,
14
+ className: w,
15
+ style: y
16
+ }) {
17
+ const [d, b] = I(0), [T, u] = I(s), [U, N] = I(/* @__PURE__ */ new Set()), z = r[d], x = $(
18
+ () => r.map((S, f) => ({
19
+ uid: S.uid,
20
+ sequence: f + 1,
21
+ isFlagged: U.has(S.uid),
22
+ isAnswered: T.some((m) => m.uid === S.uid),
23
+ isSkipped: !1
24
+ })),
25
+ [r, T, U]
26
+ );
27
+ function C(S) {
28
+ if (!z) return;
29
+ const f = z.uid, m = S.map((v) => ({
30
+ uid: f,
31
+ answerUid: v.uid,
32
+ content: v.content
33
+ }));
34
+ u((v) => {
35
+ const k = [...v.filter((D) => D.uid !== f), ...m];
36
+ return c == null || c(k), k;
37
+ });
38
+ }
39
+ function n(S) {
40
+ const f = r.findIndex((m) => m.uid === S);
41
+ f !== -1 && b(f);
42
+ }
43
+ function o(S) {
44
+ N((f) => {
45
+ const m = new Set(f);
46
+ return m.has(S) ? m.delete(S) : m.add(S), m;
47
+ });
48
+ }
49
+ function g() {
50
+ a(T);
51
+ }
52
+ return /* @__PURE__ */ t("div", { className: F(w), style: y, children: [
53
+ /* @__PURE__ */ e(
54
+ be,
55
+ {
56
+ currentQuestionIndex: d,
57
+ totalQuestions: r.length,
58
+ hasNext: d < r.length - 1,
59
+ hasPrevious: d > 0,
60
+ onNext: () => b((S) => Math.min(S + 1, r.length - 1)),
61
+ onPrevious: () => b((S) => Math.max(S - 1, 0)),
62
+ onSubmit: g,
63
+ timeElapsedSeconds: p,
64
+ timeLimitSeconds: l,
65
+ questions: x,
66
+ onNavigateToQuestion: n,
67
+ onToggleFlag: o,
68
+ currentQuestionUid: z == null ? void 0 : z.uid,
69
+ isSubmitting: h,
70
+ readOnly: i
71
+ }
72
+ ),
73
+ z && /* @__PURE__ */ e(L, { className: "mt-3", children: /* @__PURE__ */ e(Q, { className: "pt-6", children: /* @__PURE__ */ e(
74
+ X,
75
+ {
76
+ question: z,
77
+ sessionAnswers: T.filter(
78
+ (S) => S.uid === z.uid
79
+ ),
80
+ onAnswer: C,
81
+ readOnly: i
82
+ }
83
+ ) }) })
84
+ ] });
85
+ }
86
+ function Ut({
87
+ video: r,
88
+ notes: s,
89
+ layout: a = "horizontal",
90
+ notesPanelWidth: c = "340px",
91
+ notesPanelHeight: p = "240px",
92
+ className: l,
93
+ style: h
94
+ }) {
95
+ const i = a === "horizontal";
96
+ return s ? /* @__PURE__ */ t(
97
+ "div",
98
+ {
99
+ className: F(
100
+ "flex overflow-hidden",
101
+ i ? "flex-row" : "flex-col",
102
+ l
103
+ ),
104
+ style: h,
105
+ children: [
106
+ /* @__PURE__ */ e("div", { className: "flex-1 min-w-0 min-h-0", children: /* @__PURE__ */ e(oe, { ...r }) }),
107
+ /* @__PURE__ */ t(
108
+ L,
109
+ {
110
+ className: F(
111
+ "overflow-auto shrink-0 rounded-none border-0",
112
+ i ? "border-l border-border" : "border-t border-border w-full"
113
+ ),
114
+ style: {
115
+ width: i ? c : void 0,
116
+ height: i ? void 0 : p
117
+ },
118
+ children: [
119
+ /* @__PURE__ */ e($e, { children: /* @__PURE__ */ e(je, { children: "Notes" }) }),
120
+ /* @__PURE__ */ e(Q, { children: typeof s == "string" ? /* @__PURE__ */ e("span", { className: "text-sm text-foreground", children: s }) : s })
121
+ ]
122
+ }
123
+ )
124
+ ]
125
+ }
126
+ ) : /* @__PURE__ */ e("div", { className: l, style: h, children: /* @__PURE__ */ e(oe, { ...r }) });
127
+ }
128
+ function At({
129
+ cards: r,
130
+ title: s,
131
+ description: a,
132
+ shuffled: c = !1,
133
+ onComplete: p,
134
+ readOnly: l = !1,
135
+ className: h,
136
+ style: i
137
+ }) {
138
+ const [w, y] = I(!1), d = {
139
+ totalCards: r.length,
140
+ wasShuffled: c
141
+ };
142
+ function b() {
143
+ y(!0), p == null || p(d);
144
+ }
145
+ function T() {
146
+ y(!1);
147
+ }
148
+ return w ? /* @__PURE__ */ e("div", { className: F(h), style: i, children: /* @__PURE__ */ e(L, { children: /* @__PURE__ */ t(Q, { className: "pt-6 text-center flex flex-col items-center gap-2", children: [
149
+ /* @__PURE__ */ e(G, { size: 48, className: "text-success" }),
150
+ /* @__PURE__ */ e("span", { className: "text-xl font-bold text-foreground", children: "Deck complete!" }),
151
+ s && /* @__PURE__ */ t("span", { className: "text-muted-foreground", children: [
152
+ "You finished ",
153
+ /* @__PURE__ */ e("strong", { children: s })
154
+ ] }),
155
+ /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
156
+ d.totalCards,
157
+ " card",
158
+ d.totalCards !== 1 ? "s" : "",
159
+ " studied",
160
+ d.wasShuffled ? " (shuffled)" : ""
161
+ ] }),
162
+ /* @__PURE__ */ e(R, { className: "mt-1", onClick: T, children: "Study Again" })
163
+ ] }) }) }) : /* @__PURE__ */ e("div", { className: F(h), style: i, children: /* @__PURE__ */ e(
164
+ Ee,
165
+ {
166
+ cards: r,
167
+ deckName: s,
168
+ deckDescription: a,
169
+ shuffled: c,
170
+ showProgress: !0,
171
+ onComplete: b,
172
+ readOnly: l
173
+ }
174
+ ) });
175
+ }
176
+ function pt({
177
+ score: r
178
+ }) {
179
+ const s = r.percentage !== void 0 ? r.percentage : r.total > 0 ? Math.round(r.correct / r.total * 100) : 0;
180
+ return /* @__PURE__ */ e(L, { className: "mb-3", children: /* @__PURE__ */ e(Q, { className: "pt-6", children: /* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-2", children: [
181
+ /* @__PURE__ */ t("div", { children: [
182
+ /* @__PURE__ */ t("span", { className: "text-2xl font-bold leading-none text-foreground", children: [
183
+ s,
184
+ "%"
185
+ ] }),
186
+ /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
187
+ r.correct,
188
+ " of ",
189
+ r.total,
190
+ " correct"
191
+ ] })
192
+ ] }),
193
+ r.passed !== void 0 && /* @__PURE__ */ e(Ne, { variant: r.passed ? "success" : "destructive", children: r.passed ? "Passed" : "Failed" }),
194
+ r.passingScore !== void 0 && /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
195
+ "Passing score: ",
196
+ r.passingScore,
197
+ "%"
198
+ ] })
199
+ ] }) }) });
200
+ }
201
+ function de({
202
+ questions: r,
203
+ sessionAnswers: s,
204
+ showCorrectAnswers: a
205
+ }) {
206
+ return /* @__PURE__ */ e("div", { className: "flex flex-col gap-3", children: r.map((c, p) => /* @__PURE__ */ t(L, { className: "overflow-hidden", children: [
207
+ /* @__PURE__ */ e("div", { className: "px-2 py-1 bg-muted", children: /* @__PURE__ */ t("span", { className: "text-xs text-muted-foreground font-semibold", children: [
208
+ "Question ",
209
+ p + 1
210
+ ] }) }),
211
+ /* @__PURE__ */ e(V, {}),
212
+ /* @__PURE__ */ e(Q, { className: "pt-4 pb-6", children: /* @__PURE__ */ e(
213
+ X,
214
+ {
215
+ question: c,
216
+ sessionAnswers: s.filter((l) => l.uid === c.uid),
217
+ readOnly: !0,
218
+ showCorrectAnswers: a
219
+ }
220
+ ) })
221
+ ] }, c.uid)) });
222
+ }
223
+ function xt(r, s, a, c) {
224
+ const p = new Map(r.map((i) => [i.uid, i])), l = new Set(a.flatMap((i) => i.questionUids)), h = r.filter((i) => !l.has(i.uid));
225
+ return /* @__PURE__ */ t("div", { className: "flex flex-col gap-4", children: [
226
+ a.map((i) => {
227
+ const w = i.questionUids.map((y) => p.get(y)).filter(Boolean);
228
+ return /* @__PURE__ */ t("div", { children: [
229
+ /* @__PURE__ */ e("span", { className: "uppercase text-xs tracking-wide text-muted-foreground font-semibold", children: i.label }),
230
+ /* @__PURE__ */ e(V, { className: "mb-2" }),
231
+ /* @__PURE__ */ e(
232
+ de,
233
+ {
234
+ questions: w,
235
+ sessionAnswers: s,
236
+ showCorrectAnswers: c
237
+ }
238
+ )
239
+ ] }, i.label);
240
+ }),
241
+ h.length > 0 && /* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(
242
+ de,
243
+ {
244
+ questions: h,
245
+ sessionAnswers: s,
246
+ showCorrectAnswers: c
247
+ }
248
+ ) })
249
+ ] });
250
+ }
251
+ function Dt({
252
+ questions: r,
253
+ sessionAnswers: s,
254
+ score: a,
255
+ questionGroups: c,
256
+ showCorrectAnswers: p = !0,
257
+ className: l,
258
+ style: h
259
+ }) {
260
+ return /* @__PURE__ */ t("div", { className: F(l), style: h, children: [
261
+ a && /* @__PURE__ */ e(pt, { score: a }),
262
+ c && c.length > 0 ? xt(r, s, c, p) : /* @__PURE__ */ e(
263
+ de,
264
+ {
265
+ questions: r,
266
+ sessionAnswers: s,
267
+ showCorrectAnswers: p
268
+ }
269
+ )
270
+ ] });
271
+ }
272
+ function Me(r) {
273
+ const s = [];
274
+ for (const a of r)
275
+ !a.children || a.children.length === 0 ? s.push(a.uid) : s.push(...Me(a.children));
276
+ return s;
277
+ }
278
+ function Tt({
279
+ items: r,
280
+ progress: s,
281
+ courseTitle: a,
282
+ activeItemUid: c,
283
+ onItemClick: p,
284
+ showOverallProgress: l = !0,
285
+ showDuration: h = !0,
286
+ showIcons: i = !0,
287
+ readOnly: w = !1,
288
+ className: y,
289
+ style: d
290
+ }) {
291
+ const { completedCount: b, totalCount: T, percentage: u } = $(() => {
292
+ const U = Me(r), N = U.length, z = s ? U.filter(
293
+ (x) => s.some((C) => C.resourceUid === x && C.isCompleted)
294
+ ).length : 0;
295
+ return {
296
+ completedCount: z,
297
+ totalCount: N,
298
+ percentage: N > 0 ? Math.round(z / N * 100) : 0
299
+ };
300
+ }, [r, s]);
301
+ return /* @__PURE__ */ t("div", { className: F(y), style: d, children: [
302
+ (a || l) && /* @__PURE__ */ t("div", { className: "px-2 pt-2 pb-1", children: [
303
+ a && /* @__PURE__ */ e("p", { className: F("font-semibold text-sm text-foreground", l && "mb-1"), children: a }),
304
+ l && /* @__PURE__ */ t("div", { children: [
305
+ /* @__PURE__ */ e(ne, { value: u, size: "sm" }),
306
+ /* @__PURE__ */ t("span", { className: "text-xs text-muted-foreground mt-0.5 block", children: [
307
+ b,
308
+ " of ",
309
+ T,
310
+ " completed"
311
+ ] })
312
+ ] })
313
+ ] }),
314
+ /* @__PURE__ */ e(
315
+ _e,
316
+ {
317
+ items: r,
318
+ progress: s,
319
+ activeItemUid: c,
320
+ onItemClick: p,
321
+ readOnly: w,
322
+ showDuration: h,
323
+ showIcons: i,
324
+ showProgress: !0
325
+ }
326
+ )
327
+ ] });
328
+ }
329
+ function It({
330
+ questions: r,
331
+ initialAnswers: s = [],
332
+ onSubmit: a,
333
+ onAnswerChange: c,
334
+ showNavigator: p = !0,
335
+ showQuestionNumbers: l = !0,
336
+ questionGroups: h,
337
+ isSubmitting: i = !1,
338
+ readOnly: w = !1,
339
+ className: y,
340
+ style: d
341
+ }) {
342
+ var S;
343
+ const [b, T] = I(s), [u, U] = I(((S = r[0]) == null ? void 0 : S.uid) ?? null), N = ge(/* @__PURE__ */ new Map()), z = $(() => {
344
+ const f = new Set(b.map((m) => m.uid));
345
+ return r.filter((m) => f.has(m.uid)).length;
346
+ }, [r, b]);
347
+ ie(() => {
348
+ const f = new IntersectionObserver(
349
+ (m) => {
350
+ for (const v of m)
351
+ v.isIntersecting && U(v.target.getAttribute("data-question-uid"));
352
+ },
353
+ { rootMargin: "-20% 0px -60% 0px" }
354
+ );
355
+ return N.current.forEach((m) => f.observe(m)), () => f.disconnect();
356
+ }, [r]);
357
+ const x = Qe((f, m) => {
358
+ m ? N.current.set(f, m) : N.current.delete(f);
359
+ }, []);
360
+ function C(f, m) {
361
+ const v = m.map((A) => ({
362
+ uid: f,
363
+ answerUid: A.uid,
364
+ content: A.content
365
+ }));
366
+ T((A) => {
367
+ const D = [...A.filter((P) => P.uid !== f), ...v];
368
+ return c == null || c(D), D;
369
+ });
370
+ }
371
+ function n(f) {
372
+ var m;
373
+ (m = N.current.get(f)) == null || m.scrollIntoView({ behavior: "smooth", block: "center" });
374
+ }
375
+ const o = $(() => {
376
+ if (!h) return [{ label: null, questions: r }];
377
+ const f = h.map(
378
+ (A) => ({
379
+ label: A.label,
380
+ questions: A.questionUids.map((k) => r.find((D) => D.uid === k)).filter(Boolean)
381
+ })
382
+ ), m = new Set(h.flatMap((A) => A.questionUids)), v = r.filter((A) => !m.has(A.uid));
383
+ return v.length > 0 && f.push({ label: null, questions: v }), f;
384
+ }, [r, h]);
385
+ let g = 0;
386
+ return /* @__PURE__ */ t("div", { className: F("flex gap-3", y), style: d, children: [
387
+ /* @__PURE__ */ t("div", { className: "flex-1 min-w-0", children: [
388
+ o.map((f, m) => /* @__PURE__ */ t("div", { children: [
389
+ f.label && /* @__PURE__ */ e("p", { className: F("text-lg font-semibold mb-2 text-foreground", m > 0 && "mt-4"), children: f.label }),
390
+ f.questions.map((v) => {
391
+ const A = g++;
392
+ return /* @__PURE__ */ e(
393
+ L,
394
+ {
395
+ ref: (k) => x(v.uid, k),
396
+ "data-question-uid": v.uid,
397
+ className: "mb-2",
398
+ children: /* @__PURE__ */ t(Q, { className: "pt-6", children: [
399
+ l && /* @__PURE__ */ t("p", { className: "font-semibold text-sm text-muted-foreground mb-1", children: [
400
+ "Question ",
401
+ A + 1
402
+ ] }),
403
+ /* @__PURE__ */ e(
404
+ X,
405
+ {
406
+ question: v,
407
+ sessionAnswers: b.filter((k) => k.uid === v.uid),
408
+ onAnswer: (k) => C(v.uid, k),
409
+ readOnly: w
410
+ }
411
+ )
412
+ ] })
413
+ },
414
+ v.uid
415
+ );
416
+ })
417
+ ] }, m)),
418
+ /* @__PURE__ */ t("div", { className: "mt-3 flex justify-between items-center", children: [
419
+ /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
420
+ z,
421
+ " of ",
422
+ r.length,
423
+ " answered"
424
+ ] }),
425
+ /* @__PURE__ */ e(
426
+ R,
427
+ {
428
+ onClick: () => a(b),
429
+ disabled: i || w,
430
+ children: i ? "Submitting..." : "Submit"
431
+ }
432
+ )
433
+ ] })
434
+ ] }),
435
+ p && /* @__PURE__ */ t(L, { className: "hidden md:block w-50 shrink-0 sticky top-4 self-start p-3", children: [
436
+ /* @__PURE__ */ e("p", { className: "font-semibold text-sm mb-1 text-foreground", children: "Questions" }),
437
+ /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-0.5", children: r.map((f, m) => {
438
+ const v = b.some((k) => k.uid === f.uid), A = u === f.uid;
439
+ return /* @__PURE__ */ e(
440
+ "button",
441
+ {
442
+ type: "button",
443
+ className: F(
444
+ "inline-flex items-center justify-center text-xs font-medium min-w-9 px-1 py-0.5 rounded-full cursor-pointer border transition-colors",
445
+ A ? "bg-primary border-primary text-primary-foreground" : v ? "border-success text-success bg-transparent" : "border-border text-foreground bg-transparent hover:bg-muted"
446
+ ),
447
+ onClick: () => n(f.uid),
448
+ children: m + 1
449
+ },
450
+ f.uid
451
+ );
452
+ }) })
453
+ ] })
454
+ ] });
455
+ }
456
+ function gt(r) {
457
+ const s = [...r];
458
+ for (let a = s.length - 1; a > 0; a--) {
459
+ const c = Math.floor(Math.random() * (a + 1));
460
+ [s[a], s[c]] = [s[c], s[a]];
461
+ }
462
+ return s;
463
+ }
464
+ function Ft({
465
+ questions: r,
466
+ instantFeedback: s = !0,
467
+ allowRetry: a = !0,
468
+ onComplete: c,
469
+ shuffled: p = !1,
470
+ readOnly: l = !1,
471
+ className: h,
472
+ style: i
473
+ }) {
474
+ const w = $(
475
+ () => p ? gt(r) : r,
476
+ // eslint-disable-next-line react-hooks/exhaustive-deps
477
+ [r, p]
478
+ ), [y, d] = I(0), [b, T] = I(/* @__PURE__ */ new Set()), [u, U] = I(/* @__PURE__ */ new Map()), [N, z] = I(/* @__PURE__ */ new Set()), [x, C] = I(null), [n, o] = I(!1), g = w[y], S = g ? b.has(g.uid) : !1;
479
+ function f() {
480
+ var O;
481
+ if (!g || !x) return;
482
+ const k = (u.get(g.uid) ?? 0) + 1;
483
+ U((B) => new Map(B).set(g.uid, k)), T((B) => new Set(B).add(g.uid));
484
+ const D = new Set(
485
+ ((O = g.answers) == null ? void 0 : O.filter((B) => B.isCorrect).map((B) => B.uid)) ?? []
486
+ ), P = new Set(x.map((B) => B.uid));
487
+ D.size === P.size && [...D].every((B) => P.has(B)) && k === 1 && z((B) => new Set(B).add(g.uid));
488
+ }
489
+ function m() {
490
+ g && (T((k) => {
491
+ const D = new Set(k);
492
+ return D.delete(g.uid), D;
493
+ }), C(null));
494
+ }
495
+ function v() {
496
+ if (y < w.length - 1)
497
+ d((k) => k + 1), C(null);
498
+ else {
499
+ const k = {
500
+ totalQuestions: w.length,
501
+ correctOnFirstAttempt: N.size,
502
+ totalAttempts: Array.from(u.values()).reduce((D, P) => D + P, 0)
503
+ };
504
+ o(!0), c == null || c(k);
505
+ }
506
+ }
507
+ const A = $(() => {
508
+ var P;
509
+ if (!g || !x) return !1;
510
+ const k = new Set(
511
+ ((P = g.answers) == null ? void 0 : P.filter((j) => j.isCorrect).map((j) => j.uid)) ?? []
512
+ ), D = new Set(x.map((j) => j.uid));
513
+ return k.size === D.size && [...k].every((j) => D.has(j));
514
+ }, [g, x]);
515
+ if (n) {
516
+ const k = w.length > 0 ? Math.round(N.size / w.length * 100) : 0;
517
+ return /* @__PURE__ */ e(L, { className: h, style: i, children: /* @__PURE__ */ t(Q, { className: "pt-6 text-center", children: [
518
+ /* @__PURE__ */ e(G, { size: 48, className: "text-success mx-auto mb-4" }),
519
+ /* @__PURE__ */ e("p", { className: "text-xl font-bold mb-1 text-foreground", children: "Practice Complete!" }),
520
+ /* @__PURE__ */ t("p", { className: "text-muted-foreground mb-2", children: [
521
+ N.size,
522
+ " of ",
523
+ w.length,
524
+ " correct on first attempt (",
525
+ k,
526
+ "%)"
527
+ ] }),
528
+ /* @__PURE__ */ e("div", { className: "flex justify-center", children: /* @__PURE__ */ e(
529
+ R,
530
+ {
531
+ variant: "outline",
532
+ onClick: () => {
533
+ d(0), T(/* @__PURE__ */ new Set()), U(/* @__PURE__ */ new Map()), z(/* @__PURE__ */ new Set()), C(null), o(!1);
534
+ },
535
+ children: "Practice Again"
536
+ }
537
+ ) })
538
+ ] }) });
539
+ }
540
+ return /* @__PURE__ */ t("div", { className: h, style: i, children: [
541
+ /* @__PURE__ */ t("div", { className: "flex justify-between items-center mb-2", children: [
542
+ /* @__PURE__ */ t("span", { className: "font-semibold text-sm text-foreground", children: [
543
+ "Question ",
544
+ y + 1,
545
+ " of ",
546
+ w.length
547
+ ] }),
548
+ /* @__PURE__ */ t("span", { className: "text-xs text-muted-foreground", children: [
549
+ N.size,
550
+ " correct on first try"
551
+ ] })
552
+ ] }),
553
+ /* @__PURE__ */ e(
554
+ ne,
555
+ {
556
+ value: y + (S ? 1 : 0),
557
+ max: w.length,
558
+ size: "sm",
559
+ className: "mb-3"
560
+ }
561
+ ),
562
+ g && /* @__PURE__ */ e(L, { children: /* @__PURE__ */ t(Q, { className: "pt-6", children: [
563
+ /* @__PURE__ */ e(
564
+ X,
565
+ {
566
+ question: g,
567
+ sessionAnswers: (x == null ? void 0 : x.map((k) => ({
568
+ uid: g.uid,
569
+ answerUid: k.uid,
570
+ content: k.content
571
+ }))) ?? [],
572
+ onAnswer: (k) => C(k),
573
+ readOnly: l || S,
574
+ showCorrectAnswers: S
575
+ }
576
+ ),
577
+ s && S && /* @__PURE__ */ e(
578
+ He,
579
+ {
580
+ isCorrect: A,
581
+ explanation: g.explanation,
582
+ onRetry: a && !A ? m : void 0
583
+ }
584
+ ),
585
+ /* @__PURE__ */ t("div", { className: "flex justify-end gap-1 mt-2", children: [
586
+ !S && s && /* @__PURE__ */ e(
587
+ R,
588
+ {
589
+ onClick: f,
590
+ disabled: !x || x.length === 0 || l,
591
+ children: "Check Answer"
592
+ }
593
+ ),
594
+ (!s || S) && /* @__PURE__ */ e(
595
+ R,
596
+ {
597
+ onClick: v,
598
+ disabled: l,
599
+ children: y < w.length - 1 ? "Next Question" : "Finish"
600
+ }
601
+ )
602
+ ] })
603
+ ] }) })
604
+ ] });
605
+ }
606
+ function Lt({
607
+ questions: r,
608
+ initialAnswers: s = [],
609
+ onSubmit: a,
610
+ onAnswerChange: c,
611
+ timeLimitSeconds: p,
612
+ timeElapsedSeconds: l,
613
+ autoSubmitOnTimeout: h = !0,
614
+ timeWarningThreshold: i = 300,
615
+ allowBackNavigation: w = !0,
616
+ confirmBeforeSubmit: y = !0,
617
+ examTitle: d,
618
+ instructions: b,
619
+ isSubmitting: T = !1,
620
+ readOnly: u = !1,
621
+ className: U,
622
+ style: N
623
+ }) {
624
+ const [z, x] = I(0), [C, n] = I(s), [o, g] = I(/* @__PURE__ */ new Set()), [S, f] = I(!1), [m, v] = I(!1), A = ge(!1), k = r[z], D = p - l;
625
+ ie(() => {
626
+ D <= i && D > 0 && v(!0);
627
+ }, [D, i]), ie(() => {
628
+ h && D <= 0 && !A.current && (A.current = !0, re(!0));
629
+ }, [D, h]);
630
+ const P = $(
631
+ () => r.map((M, _) => ({
632
+ uid: M.uid,
633
+ sequence: _ + 1,
634
+ isFlagged: o.has(M.uid),
635
+ isAnswered: C.some((E) => E.uid === M.uid),
636
+ isSkipped: !1
637
+ })),
638
+ [r, C, o]
639
+ );
640
+ function j(M) {
641
+ if (!k) return;
642
+ const _ = k.uid, E = M.map((H) => ({
643
+ uid: _,
644
+ answerUid: H.uid,
645
+ content: H.content
646
+ }));
647
+ n((H) => {
648
+ const ce = [...H.filter((Pe) => Pe.uid !== _), ...E];
649
+ return c == null || c(ce), ce;
650
+ });
651
+ }
652
+ function O(M) {
653
+ const _ = r.findIndex((E) => E.uid === M);
654
+ _ !== -1 && x(_);
655
+ }
656
+ function B(M) {
657
+ g((_) => {
658
+ const E = new Set(_);
659
+ return E.has(M) ? E.delete(M) : E.add(M), E;
660
+ });
661
+ }
662
+ function Re() {
663
+ y ? f(!0) : re(!1);
664
+ }
665
+ function re(M) {
666
+ const _ = new Set(C.map((H) => H.uid)), E = {
667
+ timeElapsedSeconds: l,
668
+ wasAutoSubmitted: M,
669
+ answeredCount: r.filter((H) => _.has(H.uid)).length,
670
+ totalQuestions: r.length
671
+ };
672
+ a(C, E);
673
+ }
674
+ return /* @__PURE__ */ t("div", { className: F(U), style: N, children: [
675
+ d && /* @__PURE__ */ e("p", { className: "text-xl font-bold mb-2 text-foreground", children: d }),
676
+ m && D > 0 && D <= i && /* @__PURE__ */ e(ve, { variant: "warning", className: "mb-2", children: /* @__PURE__ */ t(we, { children: [
677
+ Math.ceil(D / 60),
678
+ " minute",
679
+ Math.ceil(D / 60) !== 1 ? "s" : "",
680
+ " remaining"
681
+ ] }) }),
682
+ /* @__PURE__ */ e(
683
+ be,
684
+ {
685
+ currentQuestionIndex: z,
686
+ totalQuestions: r.length,
687
+ hasNext: z < r.length - 1,
688
+ hasPrevious: w && z > 0,
689
+ onNext: () => x((M) => Math.min(M + 1, r.length - 1)),
690
+ onPrevious: () => w && x((M) => Math.max(M - 1, 0)),
691
+ onSubmit: Re,
692
+ timeElapsedSeconds: l,
693
+ timeLimitSeconds: p,
694
+ questions: P,
695
+ onNavigateToQuestion: O,
696
+ onToggleFlag: B,
697
+ currentQuestionUid: k == null ? void 0 : k.uid,
698
+ isSubmitting: T,
699
+ readOnly: u
700
+ }
701
+ ),
702
+ b && z === 0 && /* @__PURE__ */ e(L, { className: "mb-2", children: /* @__PURE__ */ e(Q, { className: "pt-6", children: b }) }),
703
+ k && /* @__PURE__ */ e(L, { className: "mt-3", children: /* @__PURE__ */ e(Q, { className: "pt-6", children: /* @__PURE__ */ e(
704
+ X,
705
+ {
706
+ question: k,
707
+ sessionAnswers: C.filter((M) => M.uid === k.uid),
708
+ onAnswer: j,
709
+ readOnly: u
710
+ }
711
+ ) }) }),
712
+ /* @__PURE__ */ e(
713
+ Ve,
714
+ {
715
+ open: S,
716
+ title: "Submit Exam?",
717
+ message: `You have answered ${P.filter((M) => M.isAnswered).length} of ${r.length} questions. Once submitted, you cannot change your answers.`,
718
+ confirmLabel: "Submit Exam",
719
+ cancelLabel: "Continue Exam",
720
+ confirmColor: "primary",
721
+ onConfirm: () => {
722
+ f(!1), re(!1);
723
+ },
724
+ onCancel: () => f(!1),
725
+ isLoading: T
726
+ }
727
+ )
728
+ ] });
729
+ }
730
+ function Mt({
731
+ title: r,
732
+ description: s,
733
+ questions: a,
734
+ initialAnswers: c = [],
735
+ onSubmit: p,
736
+ onAnswerChange: l,
737
+ showProgress: h = !0,
738
+ requireAll: i = !1,
739
+ submitLabel: w = "Submit Survey",
740
+ isSubmitting: y = !1,
741
+ readOnly: d = !1,
742
+ className: b,
743
+ style: T
744
+ }) {
745
+ const [u, U] = I(c), N = $(() => {
746
+ const n = new Set(u.map((o) => o.questionUid));
747
+ return a.filter((o) => n.has(o.uid)).length;
748
+ }, [a, u]), z = !i || N === a.length;
749
+ function x(n, o) {
750
+ U((g) => {
751
+ const f = [...g.filter((m) => m.questionUid !== n), { questionUid: n, value: o }];
752
+ return l == null || l(f), f;
753
+ });
754
+ }
755
+ function C(n) {
756
+ return u.find((o) => o.questionUid === n);
757
+ }
758
+ return /* @__PURE__ */ t("div", { className: b, style: T, children: [
759
+ /* @__PURE__ */ e("p", { className: "text-xl font-bold text-foreground mb-1", children: r }),
760
+ s && /* @__PURE__ */ e("div", { className: "mb-2 text-muted-foreground text-sm", children: typeof s == "string" ? /* @__PURE__ */ e("span", { children: s }) : s }),
761
+ h && /* @__PURE__ */ t("div", { className: "mb-3", children: [
762
+ /* @__PURE__ */ e(ne, { value: N / a.length * 100 }),
763
+ /* @__PURE__ */ t("span", { className: "block text-xs text-muted-foreground mt-0.5", children: [
764
+ N,
765
+ " of ",
766
+ a.length,
767
+ " answered"
768
+ ] })
769
+ ] }),
770
+ a.map((n, o) => {
771
+ var S, f;
772
+ const g = C(n.uid);
773
+ return /* @__PURE__ */ e(L, { className: "mb-2", children: /* @__PURE__ */ t(Q, { className: "pt-6", children: [
774
+ /* @__PURE__ */ t("p", { className: "font-medium text-foreground mb-2", children: [
775
+ o + 1,
776
+ ". ",
777
+ n.content,
778
+ n.required && /* @__PURE__ */ e("span", { className: "text-destructive ml-0.5", children: "*" })
779
+ ] }),
780
+ n.type === "likert" && /* @__PURE__ */ e(
781
+ Ye,
782
+ {
783
+ value: g ? Number(g.value) : null,
784
+ onChange: (m) => x(n.uid, m),
785
+ points: n.scalePoints,
786
+ lowLabel: (S = n.scaleLabels) == null ? void 0 : S.low,
787
+ highLabel: (f = n.scaleLabels) == null ? void 0 : f.high,
788
+ readOnly: d
789
+ }
790
+ ),
791
+ n.type === "rating" && /* @__PURE__ */ e(
792
+ Ze,
793
+ {
794
+ value: g ? Number(g.value) : 0,
795
+ onChange: (m) => x(n.uid, m),
796
+ readOnly: d
797
+ }
798
+ ),
799
+ n.type === "open_text" && /* @__PURE__ */ e(
800
+ te,
801
+ {
802
+ placeholder: "Type your response...",
803
+ value: (g == null ? void 0 : g.value) ?? "",
804
+ onChange: (m) => x(n.uid, m.target.value),
805
+ disabled: d,
806
+ className: "min-h-24"
807
+ }
808
+ ),
809
+ n.type === "choice" && n.answers && /* @__PURE__ */ e("div", { className: "flex flex-col gap-2", children: n.answers.map((m) => /* @__PURE__ */ t("label", { className: "flex items-center gap-2 cursor-pointer py-1 text-sm text-foreground has-[input:disabled]:cursor-default has-[input:disabled]:opacity-60", children: [
810
+ /* @__PURE__ */ e(
811
+ "input",
812
+ {
813
+ type: "radio",
814
+ className: "accent-primary m-0 shrink-0",
815
+ name: `survey-q-${n.uid}`,
816
+ value: m.uid,
817
+ checked: (g == null ? void 0 : g.value) === m.uid,
818
+ onChange: () => x(n.uid, m.uid),
819
+ disabled: d
820
+ }
821
+ ),
822
+ /* @__PURE__ */ e("span", { children: m.content })
823
+ ] }, m.uid)) }),
824
+ n.type === "multiple_choice" && n.answers && /* @__PURE__ */ e("div", { className: "flex flex-col gap-2", children: n.answers.map((m) => {
825
+ const v = u.filter((A) => A.questionUid === n.uid).map((A) => String(A.value));
826
+ return /* @__PURE__ */ t("label", { className: "flex items-center gap-2 cursor-pointer py-1 text-sm text-foreground has-[input:disabled]:cursor-default has-[input:disabled]:opacity-60", children: [
827
+ /* @__PURE__ */ e(
828
+ "input",
829
+ {
830
+ type: "checkbox",
831
+ className: "accent-primary m-0 shrink-0",
832
+ checked: v.includes(m.uid),
833
+ disabled: d,
834
+ onChange: (A) => {
835
+ const k = u.filter((P) => P.questionUid === n.uid);
836
+ let D;
837
+ A.target.checked ? D = [...k, { questionUid: n.uid, value: m.uid }] : D = k.filter((P) => String(P.value) !== m.uid), U((P) => [
838
+ ...P.filter((j) => j.questionUid !== n.uid),
839
+ ...D
840
+ ]), l == null || l([
841
+ ...u.filter((P) => P.questionUid !== n.uid),
842
+ ...D
843
+ ]);
844
+ }
845
+ }
846
+ ),
847
+ /* @__PURE__ */ e("span", { children: m.content })
848
+ ] }, m.uid);
849
+ }) })
850
+ ] }) }, n.uid);
851
+ }),
852
+ /* @__PURE__ */ t("div", { className: "flex justify-between items-center mt-2", children: [
853
+ /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
854
+ N,
855
+ " of ",
856
+ a.length,
857
+ " answered"
858
+ ] }),
859
+ /* @__PURE__ */ e(
860
+ R,
861
+ {
862
+ onClick: () => p(u),
863
+ disabled: !z || y || d,
864
+ children: y ? "Submitting..." : w
865
+ }
866
+ )
867
+ ] })
868
+ ] });
869
+ }
870
+ function Rt({
871
+ title: r,
872
+ blocks: s,
873
+ isCompleted: a = !1,
874
+ onMarkComplete: c,
875
+ onNextLesson: p,
876
+ nextLessonTitle: l,
877
+ estimatedDuration: h,
878
+ showDuration: i = !0,
879
+ readOnly: w = !1,
880
+ className: y,
881
+ style: d
882
+ }) {
883
+ const [b, T] = I(a), [, u] = I(/* @__PURE__ */ new Map());
884
+ function U(z, x) {
885
+ u((C) => new Map(C).set(z, x));
886
+ }
887
+ function N() {
888
+ T(!0), c == null || c();
889
+ }
890
+ return /* @__PURE__ */ t("div", { className: F(y), style: d, children: [
891
+ /* @__PURE__ */ t("div", { className: "mb-3", children: [
892
+ /* @__PURE__ */ e("p", { className: "text-2xl font-bold mb-0.5 text-foreground", children: r }),
893
+ i && h != null && /* @__PURE__ */ t("div", { className: "flex items-center gap-0.5 text-muted-foreground", children: [
894
+ /* @__PURE__ */ e(De, { size: 16 }),
895
+ /* @__PURE__ */ e("span", { className: "text-sm", children: ye(h) })
896
+ ] })
897
+ ] }),
898
+ /* @__PURE__ */ e(V, { className: "mb-3" }),
899
+ /* @__PURE__ */ e("div", { className: "flex flex-col gap-3", children: s.map((z, x) => /* @__PURE__ */ e(
900
+ Je,
901
+ {
902
+ block: z,
903
+ onQuestionAnswer: U,
904
+ readOnly: w
905
+ },
906
+ x
907
+ )) }),
908
+ /* @__PURE__ */ e("div", { className: "border border-border rounded-md px-4 py-3 mt-4 sticky bottom-0 bg-background z-10", children: /* @__PURE__ */ t("div", { className: "flex justify-between items-center", children: [
909
+ b ? /* @__PURE__ */ t("div", { className: "flex items-center gap-1 text-success", children: [
910
+ /* @__PURE__ */ e(fe, { size: 20 }),
911
+ /* @__PURE__ */ e("span", { className: "text-sm font-semibold", children: "Lesson Complete" })
912
+ ] }) : /* @__PURE__ */ t(
913
+ R,
914
+ {
915
+ onClick: N,
916
+ disabled: w,
917
+ children: [
918
+ /* @__PURE__ */ e(fe, { size: 18 }),
919
+ " Mark Complete"
920
+ ]
921
+ }
922
+ ),
923
+ p && /* @__PURE__ */ t(
924
+ R,
925
+ {
926
+ variant: b ? "default" : "outline",
927
+ onClick: p,
928
+ children: [
929
+ l ? `Next: ${l}` : "Next Lesson",
930
+ " ",
931
+ /* @__PURE__ */ e(nt, { size: 18 })
932
+ ]
933
+ }
934
+ )
935
+ ] }) })
936
+ ] });
937
+ }
938
+ function pe(r) {
939
+ return r < 1024 ? `${r} B` : r < 1024 * 1024 ? `${(r / 1024).toFixed(1)} KB` : `${(r / (1024 * 1024)).toFixed(1)} MB`;
940
+ }
941
+ const xe = {
942
+ pdf: "document",
943
+ document: "document",
944
+ video: "video",
945
+ link: "link",
946
+ image: "document",
947
+ archive: "document",
948
+ other: "document"
949
+ };
950
+ function Pt({
951
+ resources: r,
952
+ categories: s,
953
+ onResourceClick: a,
954
+ onDownload: c,
955
+ viewMode: p = "list",
956
+ allowViewToggle: l = !0,
957
+ showSearch: h = !0,
958
+ emptyMessage: i = "No resources found",
959
+ readOnly: w = !1,
960
+ className: y,
961
+ style: d
962
+ }) {
963
+ const [b, T] = I(""), [u, U] = I(null), [N, z] = I(p), x = $(() => {
964
+ let n = r;
965
+ if (u && (n = n.filter((o) => o.categoryUid === u)), b.trim()) {
966
+ const o = b.toLowerCase();
967
+ n = n.filter(
968
+ (g) => {
969
+ var S;
970
+ return g.name.toLowerCase().includes(o) || ((S = g.description) == null ? void 0 : S.toLowerCase().includes(o));
971
+ }
972
+ );
973
+ }
974
+ return n;
975
+ }, [r, u, b]);
976
+ function C(n) {
977
+ const o = xe[n.type] ?? "document";
978
+ return /* @__PURE__ */ t(
979
+ "div",
980
+ {
981
+ className: F(
982
+ "flex items-center gap-3 px-3 py-2",
983
+ !w && "cursor-pointer hover:bg-muted",
984
+ w && "opacity-70"
985
+ ),
986
+ onClick: () => !w && a(n),
987
+ children: [
988
+ /* @__PURE__ */ e("div", { className: "min-w-10", children: /* @__PURE__ */ e(ue, { type: o, size: 20 }) }),
989
+ /* @__PURE__ */ t("div", { className: "flex-1 min-w-0", children: [
990
+ /* @__PURE__ */ e("span", { className: "text-sm text-foreground", children: n.name }),
991
+ (n.description || n.fileSize != null) && /* @__PURE__ */ e("span", { className: "text-sm text-muted-foreground", children: [
992
+ n.description,
993
+ n.fileSize != null && pe(n.fileSize)
994
+ ].filter(Boolean).join(" · ") })
995
+ ] }),
996
+ c && /* @__PURE__ */ t(Z, { children: [
997
+ /* @__PURE__ */ e(
998
+ J,
999
+ {
1000
+ render: /* @__PURE__ */ e(
1001
+ R,
1002
+ {
1003
+ variant: "ghost",
1004
+ size: "icon-xs",
1005
+ "aria-label": "Download",
1006
+ onClick: (g) => {
1007
+ g.stopPropagation(), c(n);
1008
+ },
1009
+ children: /* @__PURE__ */ e(Te, { size: 16 })
1010
+ }
1011
+ )
1012
+ }
1013
+ ),
1014
+ /* @__PURE__ */ e(K, { children: "Download" })
1015
+ ] })
1016
+ ]
1017
+ },
1018
+ n.uid
1019
+ );
1020
+ }
1021
+ return /* @__PURE__ */ t("div", { className: y, style: d, children: [
1022
+ /* @__PURE__ */ t("div", { className: "flex gap-2 items-center mb-2", children: [
1023
+ h && /* @__PURE__ */ e("div", { className: "flex-1 max-w-80", children: /* @__PURE__ */ e(
1024
+ Ke,
1025
+ {
1026
+ value: b,
1027
+ onChange: T,
1028
+ placeholder: "Search resources...",
1029
+ size: "small"
1030
+ }
1031
+ ) }),
1032
+ l && /* @__PURE__ */ t("div", { className: "flex gap-0.5", children: [
1033
+ /* @__PURE__ */ t(Z, { children: [
1034
+ /* @__PURE__ */ e(
1035
+ J,
1036
+ {
1037
+ render: /* @__PURE__ */ e(
1038
+ R,
1039
+ {
1040
+ variant: "ghost",
1041
+ size: "icon-xs",
1042
+ "aria-label": "List view",
1043
+ className: F(N === "list" && "text-primary"),
1044
+ onClick: () => z("list"),
1045
+ children: /* @__PURE__ */ e(rt, { size: 18 })
1046
+ }
1047
+ )
1048
+ }
1049
+ ),
1050
+ /* @__PURE__ */ e(K, { children: "List view" })
1051
+ ] }),
1052
+ /* @__PURE__ */ t(Z, { children: [
1053
+ /* @__PURE__ */ e(
1054
+ J,
1055
+ {
1056
+ render: /* @__PURE__ */ e(
1057
+ R,
1058
+ {
1059
+ variant: "ghost",
1060
+ size: "icon-xs",
1061
+ "aria-label": "Grid view",
1062
+ className: F(N === "grid" && "text-primary"),
1063
+ onClick: () => z("grid"),
1064
+ children: /* @__PURE__ */ e(st, { size: 18 })
1065
+ }
1066
+ )
1067
+ }
1068
+ ),
1069
+ /* @__PURE__ */ e(K, { children: "Grid view" })
1070
+ ] })
1071
+ ] })
1072
+ ] }),
1073
+ s && s.length > 0 && /* @__PURE__ */ e(
1074
+ Se,
1075
+ {
1076
+ value: u ?? "all",
1077
+ onValueChange: (n) => U(n === "all" ? null : n),
1078
+ className: "mb-2",
1079
+ children: /* @__PURE__ */ t(ke, { children: [
1080
+ /* @__PURE__ */ e(W, { value: "all", children: "All" }),
1081
+ s.map((n) => /* @__PURE__ */ e(W, { value: n.uid, children: n.label }, n.uid))
1082
+ ] })
1083
+ }
1084
+ ),
1085
+ x.length === 0 ? /* @__PURE__ */ e(ze, { title: i, description: "Try adjusting your search or filter." }) : N === "list" ? /* @__PURE__ */ e(L, { children: x.map(C) }) : /* @__PURE__ */ e("div", { className: "grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] gap-2", children: x.map((n) => /* @__PURE__ */ e(
1086
+ L,
1087
+ {
1088
+ className: F(
1089
+ "transition-colors",
1090
+ !w && "cursor-pointer hover:border-primary"
1091
+ ),
1092
+ onClick: () => !w && a(n),
1093
+ children: /* @__PURE__ */ t(Q, { className: "pt-4 pb-4", children: [
1094
+ /* @__PURE__ */ t("div", { className: "flex gap-1 items-center mb-1", children: [
1095
+ /* @__PURE__ */ e(ue, { type: xe[n.type] ?? "document", size: 20 }),
1096
+ /* @__PURE__ */ e("span", { className: "font-semibold text-sm text-foreground truncate", children: n.name })
1097
+ ] }),
1098
+ n.description && /* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground mb-1 truncate", children: n.description }),
1099
+ n.fileSize != null && /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children: pe(n.fileSize) })
1100
+ ] })
1101
+ },
1102
+ n.uid
1103
+ )) })
1104
+ ] });
1105
+ }
1106
+ function bt(r) {
1107
+ const s = new Date(r), c = (/* @__PURE__ */ new Date()).getTime() - s.getTime(), p = Math.floor(c / 6e4);
1108
+ if (p < 1) return "Just now";
1109
+ if (p < 60) return `${p}m ago`;
1110
+ const l = Math.floor(p / 60);
1111
+ if (l < 24) return `${l}h ago`;
1112
+ const h = Math.floor(l / 24);
1113
+ return h < 7 ? `${h}d ago` : s.toLocaleDateString();
1114
+ }
1115
+ function Qt({
1116
+ announcements: r,
1117
+ onMarkRead: s,
1118
+ onSelect: a,
1119
+ showAvatars: c = !0,
1120
+ previewLines: p = 3,
1121
+ emptyMessage: l = "No announcements yet",
1122
+ readOnly: h = !1,
1123
+ className: i,
1124
+ style: w
1125
+ }) {
1126
+ const [y, d] = I(/* @__PURE__ */ new Set()), b = $(() => {
1127
+ const u = r.filter((N) => N.isPinned), U = r.filter((N) => !N.isPinned);
1128
+ return [...u, ...U];
1129
+ }, [r]);
1130
+ function T(u) {
1131
+ d((N) => {
1132
+ const z = new Set(N);
1133
+ return z.has(u) ? z.delete(u) : z.add(u), z;
1134
+ });
1135
+ const U = r.find((N) => N.uid === u);
1136
+ U && !U.isRead && (s == null || s(u));
1137
+ }
1138
+ return b.length === 0 ? /* @__PURE__ */ e("div", { className: i, style: w, children: /* @__PURE__ */ e(ze, { title: l }) }) : /* @__PURE__ */ e("div", { className: F("flex flex-col gap-2", i), style: w, children: b.map((u) => {
1139
+ const U = y.has(u.uid);
1140
+ return /* @__PURE__ */ e(
1141
+ L,
1142
+ {
1143
+ className: F(
1144
+ u.isRead && "opacity-85",
1145
+ a && "cursor-pointer",
1146
+ u.isPinned && "border-l-4 border-l-warning"
1147
+ ),
1148
+ onClick: () => a && !h ? a(u) : T(u.uid),
1149
+ children: /* @__PURE__ */ e(Q, { className: "pt-4 pb-4", children: /* @__PURE__ */ t("div", { className: "flex gap-1.5 items-start", children: [
1150
+ c && /* @__PURE__ */ e(
1151
+ We,
1152
+ {
1153
+ displayName: u.author.displayName,
1154
+ avatarUrl: u.author.avatarUrl,
1155
+ role: u.author.role,
1156
+ size: "medium"
1157
+ }
1158
+ ),
1159
+ /* @__PURE__ */ t("div", { className: "flex-1 min-w-0", children: [
1160
+ /* @__PURE__ */ t("div", { className: "flex items-center gap-1 mb-0.5", children: [
1161
+ u.isPinned && /* @__PURE__ */ e(lt, { size: 14 }),
1162
+ /* @__PURE__ */ e(
1163
+ "span",
1164
+ {
1165
+ className: F("text-foreground", u.isRead ? "font-normal" : "font-semibold"),
1166
+ children: u.title
1167
+ }
1168
+ ),
1169
+ !u.isRead && /* @__PURE__ */ e(Ne, { variant: "destructive", className: "text-[10px] px-1.5 py-0", children: "New" })
1170
+ ] }),
1171
+ /* @__PURE__ */ t("span", { className: "block text-xs text-muted-foreground mb-1", children: [
1172
+ u.author.displayName,
1173
+ " · ",
1174
+ bt(u.createdAt)
1175
+ ] }),
1176
+ /* @__PURE__ */ e(
1177
+ "span",
1178
+ {
1179
+ className: F(
1180
+ "text-sm text-foreground",
1181
+ !U && "line-clamp-(--preview-lines) overflow-hidden"
1182
+ ),
1183
+ style: U ? void 0 : { "--preview-lines": p },
1184
+ children: u.content
1185
+ }
1186
+ ),
1187
+ !U && u.content.length > 200 && /* @__PURE__ */ e(
1188
+ R,
1189
+ {
1190
+ variant: "link",
1191
+ size: "xs",
1192
+ className: "px-0 mt-0.5 h-auto",
1193
+ onClick: (N) => {
1194
+ N.stopPropagation(), T(u.uid);
1195
+ },
1196
+ children: "Read more"
1197
+ }
1198
+ )
1199
+ ] })
1200
+ ] }) })
1201
+ },
1202
+ u.uid
1203
+ );
1204
+ }) });
1205
+ }
1206
+ function Bt({
1207
+ title: r,
1208
+ rootPost: s,
1209
+ replies: a,
1210
+ currentUser: c,
1211
+ onReply: p,
1212
+ onToggleLike: l,
1213
+ onMarkAnswer: h,
1214
+ maxDepth: i = 3,
1215
+ allowReplies: w = !0,
1216
+ sortOrder: y = "oldest",
1217
+ readOnly: d = !1,
1218
+ className: b,
1219
+ style: T
1220
+ }) {
1221
+ const [u, U] = I(null), [N, z] = I(""), x = $(() => {
1222
+ const o = /* @__PURE__ */ new Map();
1223
+ for (const g of a) {
1224
+ const S = g.parentUid ?? s.uid, f = o.get(S) ?? [];
1225
+ f.push(g), o.set(S, f);
1226
+ }
1227
+ for (const [, g] of o)
1228
+ g.sort((S, f) => y === "newest" ? new Date(f.createdAt).getTime() - new Date(S.createdAt).getTime() : y === "most_liked" ? f.likeCount - S.likeCount : new Date(S.createdAt).getTime() - new Date(f.createdAt).getTime());
1229
+ return o;
1230
+ }, [a, s.uid, y]);
1231
+ function C(o) {
1232
+ N.trim() && (p(o, N.trim()), z(""), U(null));
1233
+ }
1234
+ function n(o, g) {
1235
+ const S = x.get(o.uid) ?? [], f = Math.min(g, i), m = /* @__PURE__ */ t("div", { className: "flex items-center gap-1", children: [
1236
+ l && !d && /* @__PURE__ */ t(Z, { children: [
1237
+ /* @__PURE__ */ e(
1238
+ J,
1239
+ {
1240
+ render: /* @__PURE__ */ t(
1241
+ R,
1242
+ {
1243
+ variant: "ghost",
1244
+ size: "sm",
1245
+ "aria-label": o.isLikedByCurrentUser ? "Unlike" : "Like",
1246
+ className: F(o.isLikedByCurrentUser && "text-destructive"),
1247
+ onClick: () => l(o.uid),
1248
+ children: [
1249
+ /* @__PURE__ */ e(it, { size: 14, fill: o.isLikedByCurrentUser ? "currentColor" : "none" }),
1250
+ o.likeCount > 0 ? o.likeCount : "Like"
1251
+ ]
1252
+ }
1253
+ )
1254
+ }
1255
+ ),
1256
+ /* @__PURE__ */ e(K, { children: o.isLikedByCurrentUser ? "Unlike" : "Like" })
1257
+ ] }),
1258
+ w && !d && /* @__PURE__ */ t(Z, { children: [
1259
+ /* @__PURE__ */ e(
1260
+ J,
1261
+ {
1262
+ render: /* @__PURE__ */ t(
1263
+ R,
1264
+ {
1265
+ variant: "ghost",
1266
+ size: "sm",
1267
+ "aria-label": "Reply",
1268
+ onClick: () => U(o.uid),
1269
+ children: [
1270
+ /* @__PURE__ */ e(dt, { size: 14 }),
1271
+ "Reply"
1272
+ ]
1273
+ }
1274
+ )
1275
+ }
1276
+ ),
1277
+ /* @__PURE__ */ e(K, { children: "Reply" })
1278
+ ] }),
1279
+ h && !d && c.role !== "student" && !o.isAnswer && /* @__PURE__ */ t(Z, { children: [
1280
+ /* @__PURE__ */ e(
1281
+ J,
1282
+ {
1283
+ render: /* @__PURE__ */ t(
1284
+ R,
1285
+ {
1286
+ variant: "ghost",
1287
+ size: "sm",
1288
+ "aria-label": "Mark as answer",
1289
+ className: "text-success",
1290
+ onClick: () => h(o.uid),
1291
+ children: [
1292
+ /* @__PURE__ */ e(G, { size: 14 }),
1293
+ "Mark Answer"
1294
+ ]
1295
+ }
1296
+ )
1297
+ }
1298
+ ),
1299
+ /* @__PURE__ */ e(K, { children: "Mark as answer" })
1300
+ ] })
1301
+ ] });
1302
+ return /* @__PURE__ */ t("div", { children: [
1303
+ /* @__PURE__ */ e(
1304
+ Xe,
1305
+ {
1306
+ author: o.author,
1307
+ content: o.content,
1308
+ createdAt: o.createdAt,
1309
+ updatedAt: o.updatedAt,
1310
+ actions: m,
1311
+ highlight: o.isAnswer ? "answer" : "none",
1312
+ indentLevel: f,
1313
+ className: "mb-1"
1314
+ }
1315
+ ),
1316
+ u === o.uid && /* @__PURE__ */ e(
1317
+ L,
1318
+ {
1319
+ className: "mb-1",
1320
+ style: { marginLeft: `${(f + 1) * 16}px` },
1321
+ children: /* @__PURE__ */ t(Q, { className: "pt-4 pb-4", children: [
1322
+ /* @__PURE__ */ e(
1323
+ te,
1324
+ {
1325
+ className: "min-h-15 mb-1",
1326
+ placeholder: "Write a reply...",
1327
+ value: N,
1328
+ onChange: (v) => z(v.target.value)
1329
+ }
1330
+ ),
1331
+ /* @__PURE__ */ t("div", { className: "flex items-center gap-1", children: [
1332
+ /* @__PURE__ */ e(
1333
+ R,
1334
+ {
1335
+ size: "sm",
1336
+ onClick: () => C(o.uid),
1337
+ disabled: !N.trim(),
1338
+ children: "Post Reply"
1339
+ }
1340
+ ),
1341
+ /* @__PURE__ */ e(
1342
+ R,
1343
+ {
1344
+ variant: "ghost",
1345
+ size: "sm",
1346
+ onClick: () => {
1347
+ U(null), z("");
1348
+ },
1349
+ children: "Cancel"
1350
+ }
1351
+ )
1352
+ ] })
1353
+ ] })
1354
+ }
1355
+ ),
1356
+ S.map((v) => n(v, g + 1))
1357
+ ] }, o.uid);
1358
+ }
1359
+ return /* @__PURE__ */ t("div", { className: b, style: T, children: [
1360
+ /* @__PURE__ */ t("div", { className: "flex items-center gap-1 mb-2", children: [
1361
+ /* @__PURE__ */ e(at, { size: 20, className: "text-foreground shrink-0" }),
1362
+ /* @__PURE__ */ e("span", { className: "text-lg font-semibold text-foreground", children: r }),
1363
+ /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
1364
+ a.length,
1365
+ " ",
1366
+ a.length === 1 ? "reply" : "replies"
1367
+ ] })
1368
+ ] }),
1369
+ /* @__PURE__ */ e(V, { className: "mb-2" }),
1370
+ n(s, 0)
1371
+ ] });
1372
+ }
1373
+ function $t({
1374
+ title: r,
1375
+ instructions: s,
1376
+ dueDate: a,
1377
+ maxScore: c,
1378
+ status: p,
1379
+ submissionTypes: l,
1380
+ existingSubmission: h,
1381
+ fileConstraints: i,
1382
+ onSubmit: w,
1383
+ onSaveDraft: y,
1384
+ grade: d,
1385
+ isSubmitting: b = !1,
1386
+ readOnly: T = !1,
1387
+ className: u,
1388
+ style: U
1389
+ }) {
1390
+ const [N, z] = I((h == null ? void 0 : h.textContent) ?? ""), [x, C] = I((h == null ? void 0 : h.files) ?? []), [n, o] = I((h == null ? void 0 : h.url) ?? ""), [g, S] = I(l[0]), f = !T && !["submitted", "graded"].includes(p);
1391
+ function m() {
1392
+ return {
1393
+ textContent: l.includes("text") ? N : void 0,
1394
+ files: l.includes("file") ? x : void 0,
1395
+ url: l.includes("url") ? n : void 0
1396
+ };
1397
+ }
1398
+ return /* @__PURE__ */ t("div", { className: u, style: U, children: [
1399
+ /* @__PURE__ */ e("div", { className: "flex justify-between items-start mb-2", children: /* @__PURE__ */ t("div", { children: [
1400
+ /* @__PURE__ */ e("div", { className: "text-xl font-bold text-foreground mb-0.5", children: r }),
1401
+ /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [
1402
+ /* @__PURE__ */ e(Ce, { status: p }),
1403
+ a && /* @__PURE__ */ e(Ue, { dueDate: a, size: "small" }),
1404
+ c != null && /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
1405
+ c,
1406
+ " points"
1407
+ ] })
1408
+ ] })
1409
+ ] }) }),
1410
+ /* @__PURE__ */ e(L, { className: "mb-3", children: /* @__PURE__ */ t(Q, { className: "pt-6", children: [
1411
+ /* @__PURE__ */ e("div", { className: "font-semibold text-sm text-foreground mb-1", children: "Instructions" }),
1412
+ /* @__PURE__ */ e("div", { className: "text-muted-foreground text-sm", children: typeof s == "string" ? /* @__PURE__ */ e("span", { children: s }) : s })
1413
+ ] }) }),
1414
+ d && /* @__PURE__ */ e(ve, { variant: "success", className: "mb-3", children: /* @__PURE__ */ t(we, { children: [
1415
+ /* @__PURE__ */ t("div", { className: "font-semibold text-sm mb-1", children: [
1416
+ "Grade: ",
1417
+ d.score,
1418
+ c != null ? ` / ${c}` : ""
1419
+ ] }),
1420
+ d.feedback && /* @__PURE__ */ e("div", { children: d.feedback })
1421
+ ] }) }),
1422
+ f && /* @__PURE__ */ t(ee, { children: [
1423
+ l.length > 1 ? /* @__PURE__ */ t(Se, { value: g, onValueChange: (v) => S(v), children: [
1424
+ /* @__PURE__ */ t(ke, { children: [
1425
+ l.includes("text") && /* @__PURE__ */ e(W, { value: "text", children: "Text" }),
1426
+ l.includes("file") && /* @__PURE__ */ e(W, { value: "file", children: "File Upload" }),
1427
+ l.includes("url") && /* @__PURE__ */ e(W, { value: "url", children: "URL" })
1428
+ ] }),
1429
+ l.includes("text") && /* @__PURE__ */ e(se, { value: "text", children: /* @__PURE__ */ e(
1430
+ te,
1431
+ {
1432
+ className: "min-h-45",
1433
+ placeholder: "Type your submission...",
1434
+ value: N,
1435
+ onChange: (v) => z(v.target.value)
1436
+ }
1437
+ ) }),
1438
+ l.includes("file") && /* @__PURE__ */ e(se, { value: "file", children: /* @__PURE__ */ e(
1439
+ me,
1440
+ {
1441
+ files: x,
1442
+ onFilesAdded: (v) => C((A) => [...A, ...v]),
1443
+ onFileRemove: (v) => C((A) => A.filter((k, D) => D !== v)),
1444
+ accept: i == null ? void 0 : i.acceptedTypes,
1445
+ maxFiles: i == null ? void 0 : i.maxFiles,
1446
+ maxSizeMB: i == null ? void 0 : i.maxSizeMB
1447
+ }
1448
+ ) }),
1449
+ l.includes("url") && /* @__PURE__ */ e(se, { value: "url", children: /* @__PURE__ */ e(
1450
+ he,
1451
+ {
1452
+ placeholder: "https://...",
1453
+ value: n,
1454
+ onChange: (v) => o(v.target.value)
1455
+ }
1456
+ ) })
1457
+ ] }) : /* @__PURE__ */ t(ee, { children: [
1458
+ l.includes("text") && /* @__PURE__ */ e(
1459
+ te,
1460
+ {
1461
+ className: "min-h-45 mb-2",
1462
+ placeholder: "Type your submission...",
1463
+ value: N,
1464
+ onChange: (v) => z(v.target.value)
1465
+ }
1466
+ ),
1467
+ l.includes("file") && /* @__PURE__ */ e("div", { className: "mb-2", children: /* @__PURE__ */ e(
1468
+ me,
1469
+ {
1470
+ files: x,
1471
+ onFilesAdded: (v) => C((A) => [...A, ...v]),
1472
+ onFileRemove: (v) => C((A) => A.filter((k, D) => D !== v)),
1473
+ accept: i == null ? void 0 : i.acceptedTypes,
1474
+ maxFiles: i == null ? void 0 : i.maxFiles,
1475
+ maxSizeMB: i == null ? void 0 : i.maxSizeMB
1476
+ }
1477
+ ) }),
1478
+ l.includes("url") && /* @__PURE__ */ e(
1479
+ he,
1480
+ {
1481
+ className: "mb-2",
1482
+ placeholder: "https://...",
1483
+ value: n,
1484
+ onChange: (v) => o(v.target.value)
1485
+ }
1486
+ )
1487
+ ] }),
1488
+ /* @__PURE__ */ e(V, { className: "my-2" }),
1489
+ /* @__PURE__ */ t("div", { className: "flex gap-1 justify-end", children: [
1490
+ y && /* @__PURE__ */ t(
1491
+ R,
1492
+ {
1493
+ variant: "outline",
1494
+ onClick: () => y(m()),
1495
+ disabled: b,
1496
+ children: [
1497
+ /* @__PURE__ */ e(ct, { size: 16 }),
1498
+ "Save Draft"
1499
+ ]
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ t(
1503
+ R,
1504
+ {
1505
+ onClick: () => w(m()),
1506
+ disabled: b,
1507
+ children: [
1508
+ /* @__PURE__ */ e(Ie, { size: 16 }),
1509
+ b ? "Submitting..." : "Submit"
1510
+ ]
1511
+ }
1512
+ )
1513
+ ] })
1514
+ ] })
1515
+ ] });
1516
+ }
1517
+ function q({
1518
+ label: r,
1519
+ field: s,
1520
+ sortField: a,
1521
+ sortDir: c,
1522
+ onSort: p,
1523
+ textAlign: l
1524
+ }) {
1525
+ const h = a === s;
1526
+ return /* @__PURE__ */ e(
1527
+ Ae,
1528
+ {
1529
+ className: F(
1530
+ "cursor-pointer select-none hover:bg-muted",
1531
+ l === "right" && "text-right"
1532
+ ),
1533
+ onClick: () => p(s),
1534
+ children: /* @__PURE__ */ t("div", { className: F("flex items-center gap-1", l === "right" && "justify-end"), children: [
1535
+ /* @__PURE__ */ e("span", { className: F(h ? "text-foreground" : "text-muted-foreground"), children: r }),
1536
+ h && (c === "asc" ? /* @__PURE__ */ e(ot, { size: 14 }) : /* @__PURE__ */ e(ut, { size: 14 }))
1537
+ ] })
1538
+ }
1539
+ );
1540
+ }
1541
+ function jt({
1542
+ items: r,
1543
+ categories: s,
1544
+ overallGrade: a,
1545
+ showWeights: c = !0,
1546
+ showCategoryTotals: p = !0,
1547
+ onItemClick: l,
1548
+ readOnly: h = !1,
1549
+ className: i,
1550
+ style: w
1551
+ }) {
1552
+ const [y, d] = I("dueDate"), [b, T] = I("asc");
1553
+ function u(x) {
1554
+ y === x ? T((C) => C === "asc" ? "desc" : "asc") : (d(x), T("asc"));
1555
+ }
1556
+ const U = $(() => {
1557
+ const x = [...r];
1558
+ return x.sort((C, n) => {
1559
+ let o = 0;
1560
+ switch (y) {
1561
+ case "name":
1562
+ o = C.name.localeCompare(n.name);
1563
+ break;
1564
+ case "score":
1565
+ o = (C.score ?? -1) - (n.score ?? -1);
1566
+ break;
1567
+ case "dueDate":
1568
+ o = (C.dueDate ?? "").localeCompare(n.dueDate ?? "");
1569
+ break;
1570
+ case "status":
1571
+ o = C.status.localeCompare(n.status);
1572
+ break;
1573
+ }
1574
+ return b === "asc" ? o : -o;
1575
+ }), x;
1576
+ }, [r, y, b]), N = $(() => {
1577
+ if (!s || s.length === 0) return [{ category: null, items: U }];
1578
+ const x = s.map((n) => ({
1579
+ category: n,
1580
+ items: U.filter((o) => o.categoryUid === n.uid)
1581
+ })), C = U.filter((n) => !n.categoryUid);
1582
+ return C.length > 0 && x.push({ category: null, items: C }), x;
1583
+ }, [U, s]), z = c ? 5 : 4;
1584
+ return /* @__PURE__ */ t("div", { className: i, style: w, children: [
1585
+ a && /* @__PURE__ */ e(L, { className: "mb-3", children: /* @__PURE__ */ e(Q, { className: "pt-6", children: /* @__PURE__ */ t("div", { className: "flex items-center gap-3", children: [
1586
+ /* @__PURE__ */ e(
1587
+ Ge,
1588
+ {
1589
+ percentage: a.percentage,
1590
+ letterGrade: a.letterGrade,
1591
+ size: "large",
1592
+ passingThreshold: 60
1593
+ }
1594
+ ),
1595
+ /* @__PURE__ */ t("div", { children: [
1596
+ /* @__PURE__ */ e("div", { className: "text-lg font-semibold text-foreground", children: "Overall Grade" }),
1597
+ /* @__PURE__ */ t("span", { className: "text-sm text-muted-foreground", children: [
1598
+ a.pointsEarned,
1599
+ " / ",
1600
+ a.pointsPossible,
1601
+ " points"
1602
+ ] })
1603
+ ] })
1604
+ ] }) }) }),
1605
+ /* @__PURE__ */ e(L, { children: /* @__PURE__ */ t(Oe, { children: [
1606
+ /* @__PURE__ */ e(qe, { children: /* @__PURE__ */ t(le, { children: [
1607
+ /* @__PURE__ */ e(
1608
+ q,
1609
+ {
1610
+ label: "Assignment",
1611
+ field: "name",
1612
+ sortField: y,
1613
+ sortDir: b,
1614
+ onSort: u
1615
+ }
1616
+ ),
1617
+ /* @__PURE__ */ e(
1618
+ q,
1619
+ {
1620
+ label: "Status",
1621
+ field: "status",
1622
+ sortField: y,
1623
+ sortDir: b,
1624
+ onSort: u
1625
+ }
1626
+ ),
1627
+ /* @__PURE__ */ e(
1628
+ q,
1629
+ {
1630
+ label: "Due Date",
1631
+ field: "dueDate",
1632
+ sortField: y,
1633
+ sortDir: b,
1634
+ onSort: u
1635
+ }
1636
+ ),
1637
+ /* @__PURE__ */ e(
1638
+ q,
1639
+ {
1640
+ label: "Score",
1641
+ field: "score",
1642
+ sortField: y,
1643
+ sortDir: b,
1644
+ onSort: u,
1645
+ textAlign: "right"
1646
+ }
1647
+ ),
1648
+ c && /* @__PURE__ */ e(Ae, { className: "text-right text-muted-foreground", children: "Weight" })
1649
+ ] }) }),
1650
+ /* @__PURE__ */ e(et, { children: N.map((x, C) => /* @__PURE__ */ t(Be, { children: [
1651
+ x.category && p && /* @__PURE__ */ e(le, { className: "bg-muted hover:bg-muted", children: /* @__PURE__ */ e(Y, { colSpan: z, children: /* @__PURE__ */ t("span", { className: "font-semibold text-sm text-foreground", children: [
1652
+ x.category.name,
1653
+ x.category.weight != null && ` (${x.category.weight}%)`
1654
+ ] }) }) }),
1655
+ x.items.map((n) => /* @__PURE__ */ t(
1656
+ le,
1657
+ {
1658
+ className: F(l && !h && "cursor-pointer"),
1659
+ onClick: () => l && !h ? l(n) : void 0,
1660
+ children: [
1661
+ /* @__PURE__ */ e(Y, { children: n.name }),
1662
+ /* @__PURE__ */ e(Y, { children: /* @__PURE__ */ e(Ce, { status: n.status, size: "small" }) }),
1663
+ /* @__PURE__ */ e(Y, { children: n.dueDate ? /* @__PURE__ */ e(
1664
+ Ue,
1665
+ {
1666
+ dueDate: n.dueDate,
1667
+ submittedDate: n.submittedDate,
1668
+ size: "small"
1669
+ }
1670
+ ) : "—" }),
1671
+ /* @__PURE__ */ e(Y, { className: "text-right", children: n.score != null ? /* @__PURE__ */ t("span", { className: "text-sm font-semibold text-foreground", children: [
1672
+ n.score,
1673
+ " / ",
1674
+ n.maxScore
1675
+ ] }) : n.status === "excused" ? /* @__PURE__ */ e("span", { className: "text-sm text-muted-foreground", children: "Excused" }) : /* @__PURE__ */ e("span", { className: "text-sm text-muted-foreground", children: "—" }) }),
1676
+ c && /* @__PURE__ */ e(Y, { className: "text-right", children: n.weight != null ? `${n.weight}%` : "—" })
1677
+ ]
1678
+ },
1679
+ n.uid
1680
+ ))
1681
+ ] }, C)) })
1682
+ ] }) })
1683
+ ] });
1684
+ }
1685
+ const Nt = {
1686
+ lesson_completed: Fe,
1687
+ quiz_passed: G,
1688
+ assignment_submitted: Ie,
1689
+ badge_earned: Le
1690
+ };
1691
+ function Et({
1692
+ overallProgress: r,
1693
+ totalTimeSpent: s,
1694
+ modules: a,
1695
+ recentActivity: c,
1696
+ streak: p,
1697
+ achievements: l,
1698
+ recentActivityLimit: h = 5,
1699
+ onModuleClick: i,
1700
+ className: w,
1701
+ style: y
1702
+ }) {
1703
+ return /* @__PURE__ */ t("div", { className: w, style: y, children: [
1704
+ /* @__PURE__ */ t("div", { className: "grid grid-cols-[repeat(auto-fit,minmax(160px,1fr))] gap-2 mb-3", children: [
1705
+ /* @__PURE__ */ e(L, { className: "p-2 flex justify-center", children: /* @__PURE__ */ e(tt, { value: r, size: 100 }) }),
1706
+ /* @__PURE__ */ e(
1707
+ ae,
1708
+ {
1709
+ icon: /* @__PURE__ */ e(De, { size: 24 }),
1710
+ label: "Time Spent",
1711
+ value: ye(s)
1712
+ }
1713
+ ),
1714
+ p && /* @__PURE__ */ e(
1715
+ ae,
1716
+ {
1717
+ icon: /* @__PURE__ */ e(mt, { size: 24 }),
1718
+ label: "Current Streak",
1719
+ value: `${p.currentDays} days`,
1720
+ subtitle: `Longest: ${p.longestDays} days`
1721
+ }
1722
+ ),
1723
+ /* @__PURE__ */ e(
1724
+ ae,
1725
+ {
1726
+ icon: /* @__PURE__ */ e(Fe, { size: 24 }),
1727
+ label: "Modules",
1728
+ value: `${a.filter((d) => d.completedItems === d.totalItems).length} / ${a.length}`,
1729
+ subtitle: "completed"
1730
+ }
1731
+ )
1732
+ ] }),
1733
+ /* @__PURE__ */ e("p", { className: "text-lg font-semibold mb-2 text-foreground", children: "Module Progress" }),
1734
+ /* @__PURE__ */ e("div", { className: "flex flex-col gap-1.5 mb-3", children: a.map((d) => {
1735
+ const b = d.totalItems > 0 ? d.completedItems / d.totalItems * 100 : 0;
1736
+ return /* @__PURE__ */ t(
1737
+ L,
1738
+ {
1739
+ className: F(
1740
+ "p-2 transition-colors",
1741
+ i && "cursor-pointer hover:border-primary"
1742
+ ),
1743
+ onClick: () => i == null ? void 0 : i(d.uid),
1744
+ children: [
1745
+ /* @__PURE__ */ t("div", { className: "flex justify-between items-center mb-0.5", children: [
1746
+ /* @__PURE__ */ e("span", { className: "font-semibold text-sm text-foreground", children: d.name }),
1747
+ /* @__PURE__ */ t("span", { className: "text-xs text-muted-foreground", children: [
1748
+ d.completedItems,
1749
+ " / ",
1750
+ d.totalItems
1751
+ ] })
1752
+ ] }),
1753
+ /* @__PURE__ */ e(ne, { value: b, size: "sm" })
1754
+ ]
1755
+ },
1756
+ d.uid
1757
+ );
1758
+ }) }),
1759
+ c && c.length > 0 && /* @__PURE__ */ t(ee, { children: [
1760
+ /* @__PURE__ */ e("p", { className: "text-lg font-semibold mb-2 text-foreground", children: "Recent Activity" }),
1761
+ /* @__PURE__ */ e("div", { className: "flex flex-col gap-1 mb-3", children: c.slice(0, h).map((d) => {
1762
+ const b = Nt[d.type] ?? G;
1763
+ return /* @__PURE__ */ t("div", { className: "flex gap-1.5 items-center", children: [
1764
+ /* @__PURE__ */ e(b, { size: 16 }),
1765
+ /* @__PURE__ */ e("span", { className: "flex-1 text-sm text-foreground", children: d.description }),
1766
+ /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children: new Date(d.timestamp).toLocaleDateString() })
1767
+ ] }, d.uid);
1768
+ }) })
1769
+ ] }),
1770
+ l && l.length > 0 && /* @__PURE__ */ t(ee, { children: [
1771
+ /* @__PURE__ */ e("p", { className: "text-lg font-semibold mb-2 text-foreground", children: "Achievements" }),
1772
+ /* @__PURE__ */ e("div", { className: "grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-2", children: l.map((d) => /* @__PURE__ */ t(L, { className: "p-2 text-center", children: [
1773
+ d.iconUrl ? /* @__PURE__ */ e(
1774
+ "img",
1775
+ {
1776
+ src: d.iconUrl,
1777
+ alt: d.name,
1778
+ className: "w-12 h-12 mb-1 mx-auto"
1779
+ }
1780
+ ) : /* @__PURE__ */ e(ht, { size: 32, className: "mx-auto mb-2 text-warning" }),
1781
+ /* @__PURE__ */ e("p", { className: "font-semibold text-sm text-foreground", children: d.name }),
1782
+ /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: d.description })
1783
+ ] }, d.uid)) })
1784
+ ] })
1785
+ ] });
1786
+ }
1787
+ const vt = {
1788
+ classic: "border-[3px] border-double border-warning bg-linear-to-br from-[#fffbe6] to-[#fff8e1]",
1789
+ modern: "border border-primary bg-linear-to-br from-[#fff5f5] to-[#fee2e2]",
1790
+ minimal: "border border-border"
1791
+ };
1792
+ function _t({
1793
+ recipientName: r,
1794
+ courseTitle: s,
1795
+ completionDate: a,
1796
+ organizationName: c,
1797
+ organizationLogo: p,
1798
+ signatory: l,
1799
+ certificateId: h,
1800
+ variant: i = "classic",
1801
+ showActions: w = !0,
1802
+ onPrint: y,
1803
+ onDownload: d,
1804
+ className: b,
1805
+ style: T
1806
+ }) {
1807
+ const u = (() => {
1808
+ try {
1809
+ return new Date(a).toLocaleDateString("en-US", {
1810
+ year: "numeric",
1811
+ month: "long",
1812
+ day: "numeric"
1813
+ });
1814
+ } catch {
1815
+ return a;
1816
+ }
1817
+ })();
1818
+ function U() {
1819
+ y ? y() : window.print();
1820
+ }
1821
+ return /* @__PURE__ */ t("div", { className: b, style: T, children: [
1822
+ /* @__PURE__ */ t(
1823
+ "div",
1824
+ {
1825
+ className: F(
1826
+ "p-3 sm:p-5 md:p-6 text-center max-w-200 mx-auto rounded-md",
1827
+ vt[i]
1828
+ ),
1829
+ children: [
1830
+ p ? /* @__PURE__ */ e(
1831
+ "img",
1832
+ {
1833
+ src: p,
1834
+ alt: c,
1835
+ className: "h-15 mb-2 mx-auto block"
1836
+ }
1837
+ ) : /* @__PURE__ */ e(
1838
+ Le,
1839
+ {
1840
+ size: 48,
1841
+ className: F("mx-auto mb-4", i === "classic" && "text-warning")
1842
+ }
1843
+ ),
1844
+ /* @__PURE__ */ e("p", { className: "uppercase tracking-[3px] text-sm text-foreground/70", children: "Certificate of Completion" }),
1845
+ /* @__PURE__ */ e(V, { className: "my-2 mx-auto max-w-50" }),
1846
+ /* @__PURE__ */ e("p", { className: "text-sm text-foreground mb-1", children: "This is to certify that" }),
1847
+ /* @__PURE__ */ e("p", { className: F("text-2xl font-bold mb-2 text-foreground", i === "classic" && "font-serif"), children: r }),
1848
+ /* @__PURE__ */ e("p", { className: "text-sm text-foreground mb-1", children: "has successfully completed" }),
1849
+ /* @__PURE__ */ e("p", { className: "text-xl font-bold mb-2 text-primary", children: s }),
1850
+ /* @__PURE__ */ t("p", { className: "text-sm text-foreground mb-3", children: [
1851
+ "Issued by ",
1852
+ c,
1853
+ " on ",
1854
+ u
1855
+ ] }),
1856
+ l && /* @__PURE__ */ t("div", { className: "mt-4 mb-2", children: [
1857
+ /* @__PURE__ */ e(V, { className: "my-2 mx-auto max-w-50" }),
1858
+ /* @__PURE__ */ e("p", { className: "font-semibold text-sm text-foreground", children: l.name }),
1859
+ /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: l.title })
1860
+ ] }),
1861
+ h && /* @__PURE__ */ t("span", { className: "block text-xs text-muted-foreground mt-2", children: [
1862
+ "Certificate ID: ",
1863
+ h
1864
+ ] })
1865
+ ]
1866
+ }
1867
+ ),
1868
+ w && /* @__PURE__ */ t("div", { className: "flex justify-center gap-2 mt-3", children: [
1869
+ /* @__PURE__ */ t(R, { variant: "outline", onClick: U, children: [
1870
+ /* @__PURE__ */ e(ft, { size: 16 }),
1871
+ " Print"
1872
+ ] }),
1873
+ d && /* @__PURE__ */ t(R, { variant: "outline", onClick: d, children: [
1874
+ /* @__PURE__ */ e(Te, { size: 16 }),
1875
+ " Download"
1876
+ ] })
1877
+ ] })
1878
+ ] });
1879
+ }
1880
+ export {
1881
+ Qt as AnnouncementFeed,
1882
+ Dt as AssessmentReview,
1883
+ $t as AssignmentSubmission,
1884
+ _t as CertificateViewer,
1885
+ Tt as CourseOutline,
1886
+ Bt as DiscussionThread,
1887
+ Lt as ExamSession,
1888
+ At as FlashcardStudySession,
1889
+ jt as GradebookTable,
1890
+ Ut as LecturePlayer,
1891
+ Rt as LessonPage,
1892
+ Ft as PracticeQuiz,
1893
+ Et as ProgressDashboard,
1894
+ Ct as QuizSession,
1895
+ Pt as ResourceLibrary,
1896
+ It as ScrollableQuiz,
1897
+ Mt as SurveyForm
1898
+ };