@hydralms/components 0.1.3 → 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.
- package/dist/ForumBoard-CHXU3mjC.js +2207 -0
- package/dist/ForumBoard-d1w5-r6n.cjs +1 -0
- package/dist/assessment-toolbar/assessment-toolbar.d.ts +1 -1
- package/dist/assessment-toolbar/index.d.ts +5 -1
- package/dist/assessment-toolbar/question-header-bar.d.ts +2 -0
- package/dist/assessment-toolbar/question-materials-drawer.d.ts +2 -0
- package/dist/assessment-toolbar/question-navigator.d.ts +1 -1
- package/dist/assessment-toolbar/types.d.ts +52 -4
- package/dist/assessment-toolbar/use-countdown.d.ts +43 -0
- package/dist/common/index.d.ts +2 -1
- package/dist/common/stepper.d.ts +6 -0
- package/dist/common/types.d.ts +37 -0
- package/dist/components.css +1 -1
- package/dist/content/attachment-list.d.ts +6 -0
- package/dist/content/content-block.d.ts +1 -1
- package/dist/content/index.d.ts +2 -1
- package/dist/content/types.d.ts +39 -0
- package/dist/curriculum/curriculum-item.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +551 -312
- package/dist/modules/AssignmentModule/AssignmentModule.d.ts +8 -0
- package/dist/modules/AssignmentModule/types.d.ts +65 -0
- package/dist/modules/CertificateModule/CertificateModule.d.ts +9 -0
- package/dist/modules/CertificateModule/types.d.ts +49 -0
- package/dist/modules/DiscussionModule/DiscussionModule.d.ts +8 -0
- package/dist/modules/DiscussionModule/types.d.ts +47 -0
- package/dist/modules/ExamModule/ExamModule.d.ts +8 -0
- package/dist/modules/ExamModule/types.d.ts +64 -0
- package/dist/modules/GradeCenterModule/GradeCenterModule.d.ts +9 -0
- package/dist/modules/GradeCenterModule/types.d.ts +54 -0
- package/dist/modules/QuizModule/QuizModule.d.ts +1 -1
- package/dist/modules/QuizModule/types.d.ts +6 -1
- package/dist/modules/SurveyModule/SurveyModule.d.ts +7 -0
- package/dist/modules/SurveyModule/types.d.ts +49 -0
- package/dist/modules/index.d.ts +12 -0
- package/dist/modules.cjs +1 -0
- package/dist/modules.js +1422 -0
- package/dist/progress/achievement-badge.d.ts +6 -0
- package/dist/progress/activity-timeline.d.ts +6 -0
- package/dist/progress/index.d.ts +4 -1
- package/dist/progress/stat-card.d.ts +1 -1
- package/dist/progress/streak-badge.d.ts +6 -0
- package/dist/progress/types.d.ts +97 -0
- package/dist/questions/essay.d.ts +1 -1
- package/dist/questions/hotspot.d.ts +21 -0
- package/dist/questions/index.d.ts +9 -1
- package/dist/questions/inline-choice.d.ts +21 -0
- package/dist/questions/matching.d.ts +22 -0
- package/dist/questions/numeric.d.ts +11 -0
- package/dist/questions/ordering.d.ts +12 -0
- package/dist/questions/scenario.d.ts +23 -0
- package/dist/questions/scoring.d.ts +22 -0
- package/dist/questions/spreadsheet.d.ts +29 -0
- package/dist/questions/types.d.ts +106 -1
- package/dist/questions/use-drag-reorder.d.ts +17 -0
- package/dist/sections/CertificateViewer/types.d.ts +7 -5
- package/dist/sections/ExamSession/ExamSession.d.ts +1 -1
- package/dist/sections/ExamSession/types.d.ts +6 -1
- package/dist/sections/ForumBoard/ForumBoard.d.ts +8 -0
- package/dist/sections/ForumBoard/types.d.ts +64 -0
- package/dist/sections/QuizSession/QuizSession.d.ts +1 -1
- package/dist/sections/QuizSession/types.d.ts +6 -1
- package/dist/sections/RequirementsChecklist/RequirementsChecklist.d.ts +8 -0
- package/dist/sections/RequirementsChecklist/types.d.ts +37 -0
- package/dist/sections/RubricView/RubricView.d.ts +9 -0
- package/dist/sections/RubricView/types.d.ts +50 -0
- package/dist/sections/index.d.ts +7 -1
- package/dist/sections.cjs +1 -1
- package/dist/sections.js +250 -1715
- package/dist/social/post-card.d.ts +1 -1
- package/dist/tabs-DRM2Iq_J.cjs +172 -0
- package/dist/tabs-Wf3h_Cx3.js +21580 -0
- package/dist/ui/alert.d.ts +1 -1
- package/dist/ui/badge.d.ts +1 -1
- package/dist/ui/button.d.ts +1 -1
- package/dist/ui/drawer.d.ts +84 -0
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/progress.d.ts +1 -1
- package/dist/ui/rich-text-editor.d.ts +30 -0
- package/dist/ui/rich-text-toolbar.d.ts +8 -0
- package/dist/utils/array-utils.d.ts +4 -0
- package/dist/utils/flatten-leaves.d.ts +6 -0
- package/dist/utils/format-file-size.d.ts +1 -0
- package/dist/utils/format-timestamp.d.ts +1 -0
- package/dist/utils/is-empty-html.d.ts +5 -0
- package/dist/utils/shuffle.d.ts +1 -0
- package/dist/utils/string-utils.d.ts +12 -0
- package/dist/video/video-bookmark.d.ts +1 -1
- package/dist/video/video-playlist-item.d.ts +1 -1
- package/package.json +92 -3
- package/src/assessment-toolbar/assessment-toolbar.tsx +54 -49
- package/src/assessment-toolbar/index.ts +6 -0
- package/src/assessment-toolbar/question-header-bar.tsx +61 -0
- package/src/assessment-toolbar/question-materials-drawer.tsx +55 -0
- package/src/assessment-toolbar/question-navigator.tsx +3 -31
- package/src/assessment-toolbar/timer-display.tsx +2 -2
- package/src/assessment-toolbar/types.ts +54 -4
- package/src/assessment-toolbar/use-countdown.ts +153 -0
- package/src/common/index.ts +3 -0
- package/src/common/search-input.tsx +7 -6
- package/src/common/stepper.tsx +100 -0
- package/src/common/types.ts +39 -0
- package/src/content/attachment-list.tsx +90 -0
- package/src/content/content-block.tsx +4 -2
- package/src/content/file-upload-zone.tsx +1 -6
- package/src/content/index.ts +3 -0
- package/src/content/types.ts +41 -0
- package/src/curriculum/curriculum-item.tsx +7 -3
- package/src/feedback/feedback-banner.tsx +12 -14
- package/src/flashcards/flashcard-deck.tsx +1 -9
- package/src/flashcards/flashcard.tsx +1 -1
- package/src/modules/AssignmentModule/AssignmentModule.tsx +305 -0
- package/src/modules/AssignmentModule/types.ts +73 -0
- package/src/modules/CertificateModule/CertificateModule.tsx +161 -0
- package/src/modules/CertificateModule/types.ts +47 -0
- package/src/modules/CoursePlayer/CoursePlayer.tsx +44 -48
- package/src/modules/DiscussionModule/DiscussionModule.tsx +110 -0
- package/src/modules/DiscussionModule/types.ts +54 -0
- package/src/modules/ExamModule/ExamModule.tsx +285 -0
- package/src/modules/ExamModule/types.ts +66 -0
- package/src/modules/FlashcardLab/FlashcardLab.tsx +29 -16
- package/src/modules/GradeCenterModule/GradeCenterModule.tsx +169 -0
- package/src/modules/GradeCenterModule/types.ts +63 -0
- package/src/modules/QuizModule/QuizModule.tsx +88 -88
- package/src/modules/QuizModule/types.ts +6 -1
- package/src/modules/SurveyModule/SurveyModule.tsx +180 -0
- package/src/modules/SurveyModule/types.ts +51 -0
- package/src/modules/index.ts +24 -0
- package/src/progress/achievement-badge.tsx +52 -0
- package/src/progress/activity-timeline.tsx +84 -0
- package/src/progress/index.ts +7 -0
- package/src/progress/stat-card.tsx +30 -18
- package/src/progress/streak-badge.tsx +35 -0
- package/src/progress/types.ts +101 -0
- package/src/questions/choice.tsx +7 -9
- package/src/questions/essay.tsx +23 -25
- package/src/questions/fill-in-the-blank.tsx +13 -16
- package/src/questions/hotspot.tsx +154 -0
- package/src/questions/index.ts +16 -0
- package/src/questions/inline-choice.tsx +151 -0
- package/src/questions/matching.tsx +228 -0
- package/src/questions/multiple-choice.tsx +7 -9
- package/src/questions/numeric.tsx +102 -0
- package/src/questions/ordering.tsx +159 -0
- package/src/questions/question-renderer.tsx +21 -0
- package/src/questions/scenario.tsx +140 -0
- package/src/questions/scoring.ts +201 -0
- package/src/questions/spreadsheet.tsx +259 -0
- package/src/questions/true-false.tsx +7 -9
- package/src/questions/types.ts +123 -1
- package/src/questions/use-drag-reorder.ts +80 -0
- package/src/sections/AnnouncementFeed/AnnouncementFeed.tsx +2 -15
- package/src/sections/AssessmentReview/AssessmentReview.tsx +13 -2
- package/src/sections/AssignmentSubmission/AssignmentSubmission.tsx +7 -5
- package/src/sections/CertificateViewer/CertificateViewer.tsx +409 -56
- package/src/sections/CertificateViewer/types.ts +13 -5
- package/src/sections/CourseOutline/CourseOutline.tsx +4 -14
- package/src/sections/DiscussionThread/DiscussionThread.tsx +13 -10
- package/src/sections/ExamSession/ExamSession.tsx +44 -7
- package/src/sections/ExamSession/types.ts +6 -1
- package/src/sections/ForumBoard/ForumBoard.tsx +284 -0
- package/src/sections/ForumBoard/types.ts +67 -0
- package/src/sections/GradebookTable/GradebookTable.tsx +1 -1
- package/src/sections/LecturePlayer/LecturePlayer.tsx +1 -1
- package/src/sections/LessonPage/LessonPage.tsx +5 -9
- package/src/sections/PracticeQuiz/PracticeQuiz.tsx +15 -26
- package/src/sections/ProgressDashboard/ProgressDashboard.tsx +65 -65
- package/src/sections/QuizSession/QuizSession.tsx +67 -8
- package/src/sections/QuizSession/types.ts +6 -1
- package/src/sections/RequirementsChecklist/RequirementsChecklist.tsx +107 -0
- package/src/sections/RequirementsChecklist/types.ts +38 -0
- package/src/sections/ResourceLibrary/ResourceLibrary.tsx +4 -9
- package/src/sections/RubricView/RubricView.tsx +138 -0
- package/src/sections/RubricView/types.ts +52 -0
- package/src/sections/ScrollableQuiz/ScrollableQuiz.tsx +23 -9
- package/src/sections/SurveyForm/SurveyForm.tsx +8 -5
- package/src/sections/index.ts +20 -1
- package/src/social/post-card.tsx +8 -19
- package/src/social/user-avatar.tsx +1 -0
- package/src/styles/globals.css +13 -0
- package/src/ui/drawer.tsx +600 -0
- package/src/ui/index.ts +19 -0
- package/src/ui/rich-text-editor.tsx +109 -0
- package/src/ui/rich-text-toolbar.tsx +156 -0
- package/src/utils/array-utils.ts +17 -0
- package/src/utils/flatten-leaves.ts +17 -0
- package/src/utils/format-file-size.ts +5 -0
- package/src/utils/format-timestamp.ts +13 -0
- package/src/utils/is-empty-html.ts +7 -0
- package/src/utils/shuffle.ts +8 -0
- package/src/utils/string-utils.ts +30 -0
- package/src/video/video-bookmark.tsx +4 -3
- package/src/video/video-chapter-list.tsx +9 -4
- package/src/video/video-player.tsx +11 -4
- package/src/video/video-playlist-item.tsx +8 -3
- package/src/video/video-thumbnail-card.tsx +4 -0
- package/src/video/video-transcript.tsx +8 -5
- package/dist/table-BrS5cDQu.js +0 -2510
- package/dist/table-D6AkBBEo.cjs +0 -1
package/dist/ui/alert.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
declare const alertVariants: (props?: ({
|
|
4
|
-
variant?: "
|
|
4
|
+
variant?: "info" | "warning" | "default" | "destructive" | "success" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
declare function Alert({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>): import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
declare function AlertTitle({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
package/dist/ui/badge.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "
|
|
4
|
+
variant?: "info" | "warning" | "default" | "destructive" | "success" | "muted" | "outline" | "secondary" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
7
7
|
asChild?: boolean;
|
package/dist/ui/button.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
4
|
variant?: "default" | "destructive" | "link" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
|
-
size?: "default" | "
|
|
5
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
7
|
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
8
8
|
asChild?: boolean;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
declare const drawerContentVariants: (props?: ({
|
|
3
|
+
side?: "left" | "right" | null | undefined;
|
|
4
|
+
size?: "default" | "full" | "sm" | "lg" | "xl" | null | undefined;
|
|
5
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
|
+
/**
|
|
7
|
+
* A slide-in side panel for contextual content like navigation, settings, or detail views.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <Drawer open={open} onOpenChange={setOpen} side="right">
|
|
12
|
+
* <DrawerContent>
|
|
13
|
+
* <DrawerHeader><DrawerTitle>Panel</DrawerTitle></DrawerHeader>
|
|
14
|
+
* <DrawerBody>Content</DrawerBody>
|
|
15
|
+
* </DrawerContent>
|
|
16
|
+
* </Drawer>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
interface DrawerProps {
|
|
20
|
+
/** Compound component children (DrawerContent, DrawerTrigger, etc.) */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/** Whether the drawer is open. */
|
|
23
|
+
open: boolean;
|
|
24
|
+
/** Callback fired when the drawer should open or close. */
|
|
25
|
+
onOpenChange: (open: boolean) => void;
|
|
26
|
+
/** Which edge of the viewport the drawer slides in from. */
|
|
27
|
+
side?: "left" | "right";
|
|
28
|
+
}
|
|
29
|
+
declare function Drawer({ children, open, onOpenChange, side }: DrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
declare function DrawerTrigger({ className, onClick, ...props }: React.ComponentProps<"button">): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
declare function DrawerPortal({ children }: {
|
|
32
|
+
children: React.ReactNode;
|
|
33
|
+
}): React.ReactPortal;
|
|
34
|
+
declare function DrawerBackdrop({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
interface DrawerContentProps extends Omit<React.ComponentProps<"div">, "size"> {
|
|
36
|
+
/** Width preset for the drawer panel. */
|
|
37
|
+
size?: "sm" | "default" | "lg" | "xl" | "full";
|
|
38
|
+
/** Whether to lock body scroll when the drawer is open. */
|
|
39
|
+
scrollLock?: boolean;
|
|
40
|
+
}
|
|
41
|
+
declare function DrawerContent({ className, children, size, scrollLock: scrollLockProp, ...props }: DrawerContentProps): import("react/jsx-runtime").JSX.Element | null;
|
|
42
|
+
declare function DrawerHeader({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
declare function DrawerBody({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
declare function DrawerFooter({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
declare function DrawerTitle({ className, ...props }: React.ComponentProps<"h2">): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
declare function DrawerDescription({ className, ...props }: React.ComponentProps<"p">): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
declare function DrawerClose({ className, children, onClick, ...props }: React.ComponentProps<"button">): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
/**
|
|
49
|
+
* A vertical icon rail for switching between views inside a Drawer.
|
|
50
|
+
* Provides controlled navigation state to DrawerNavItem children.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* <DrawerNav value={activeView} onValueChange={setActiveView}>
|
|
55
|
+
* <DrawerNavItem value="notes" icon={<FileText />} label="Notes" />
|
|
56
|
+
* <DrawerNavItem value="bookmarks" icon={<Bookmark />} label="Bookmarks" />
|
|
57
|
+
* </DrawerNav>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
interface DrawerNavProps extends React.ComponentProps<"nav"> {
|
|
61
|
+
/** The value of the currently active nav item. */
|
|
62
|
+
value: string;
|
|
63
|
+
/** Callback fired when the active nav item changes. */
|
|
64
|
+
onValueChange: (value: string) => void;
|
|
65
|
+
}
|
|
66
|
+
declare function DrawerNav({ value, onValueChange, className, children, ...props }: DrawerNavProps): import("react/jsx-runtime").JSX.Element;
|
|
67
|
+
/**
|
|
68
|
+
* An icon button inside a DrawerNav rail. Renders a tooltip on hover.
|
|
69
|
+
*/
|
|
70
|
+
interface DrawerNavItemProps extends Omit<React.ComponentProps<"button">, "value"> {
|
|
71
|
+
/** Unique value identifying this view. Must match a DrawerViewport's conditional content. */
|
|
72
|
+
value: string;
|
|
73
|
+
/** Icon element to render (e.g., `<FileText />`). */
|
|
74
|
+
icon: React.ReactNode;
|
|
75
|
+
/** Accessible label shown in the tooltip. */
|
|
76
|
+
label: string;
|
|
77
|
+
}
|
|
78
|
+
declare function DrawerNavItem({ value, icon, label, className, ...props }: DrawerNavItemProps): import("react/jsx-runtime").JSX.Element;
|
|
79
|
+
/**
|
|
80
|
+
* Content panel paired with a DrawerNav rail. Wraps header/body/footer in the
|
|
81
|
+
* remaining space beside the icon rail.
|
|
82
|
+
*/
|
|
83
|
+
declare function DrawerViewport({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
84
|
+
export { Drawer, DrawerTrigger, DrawerPortal, DrawerBackdrop, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, DrawerTitle, DrawerDescription, DrawerClose, DrawerNav, DrawerNavItem, DrawerViewport, drawerContentVariants, };
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { Alert, AlertTitle, AlertDescription, alertVariants } from './alert';
|
|
|
6
6
|
export { Separator } from './separator';
|
|
7
7
|
export { AlertDialog, AlertDialogTrigger, AlertDialogPortal, AlertDialogBackdrop, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, } from './alert-dialog';
|
|
8
8
|
export { Avatar, AvatarImage, AvatarFallback } from './avatar';
|
|
9
|
+
export { Drawer, DrawerTrigger, DrawerPortal, DrawerBackdrop, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, DrawerTitle, DrawerDescription, DrawerClose, DrawerNav, DrawerNavItem, DrawerViewport, drawerContentVariants, } from './drawer';
|
|
9
10
|
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, } from './card';
|
|
10
11
|
export { Tabs, TabsList, TabsTrigger, TabsContent } from './tabs';
|
|
11
12
|
export { Progress, progressVariants } from './progress';
|
|
@@ -13,3 +14,5 @@ export type { ProgressProps } from './progress';
|
|
|
13
14
|
export { Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption, } from './table';
|
|
14
15
|
export { Skeleton } from './skeleton';
|
|
15
16
|
export { Tooltip, TooltipTrigger, TooltipContent } from './tooltip';
|
|
17
|
+
export { RichTextEditor } from './rich-text-editor';
|
|
18
|
+
export type { RichTextEditorProps, RichTextEditorVariant } from './rich-text-editor';
|
package/dist/ui/progress.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
declare const progressVariants: (props?: ({
|
|
4
|
-
variant?: "
|
|
4
|
+
variant?: "info" | "warning" | "default" | "success" | null | undefined;
|
|
5
5
|
size?: "default" | "sm" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
7
|
interface ProgressProps extends Omit<React.ComponentProps<"div">, "children">, VariantProps<typeof progressVariants> {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type RichTextEditorVariant = "default" | "minimal";
|
|
2
|
+
export interface RichTextEditorProps {
|
|
3
|
+
/** HTML string value */
|
|
4
|
+
value?: string;
|
|
5
|
+
/** Called with the HTML string on every content change */
|
|
6
|
+
onChange?: (html: string) => void;
|
|
7
|
+
/** Placeholder text shown when the editor is empty */
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
/** Makes the editor non-editable (shows content without toolbar) */
|
|
10
|
+
readOnly?: boolean;
|
|
11
|
+
/** Visually disables the editor */
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
/** `"default"` shows full toolbar; `"minimal"` shows only basic formatting */
|
|
14
|
+
variant?: RichTextEditorVariant;
|
|
15
|
+
className?: string;
|
|
16
|
+
style?: React.CSSProperties;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* RichTextEditor wraps Tiptap to provide a rich text editing experience
|
|
20
|
+
* styled to match the HydraLMS design system.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <RichTextEditor
|
|
24
|
+
* value={html}
|
|
25
|
+
* onChange={setHtml}
|
|
26
|
+
* placeholder="Write your response..."
|
|
27
|
+
* variant="default"
|
|
28
|
+
* />
|
|
29
|
+
*/
|
|
30
|
+
export declare function RichTextEditor({ value, onChange, placeholder, readOnly, disabled, variant, className, style, }: RichTextEditorProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/react';
|
|
2
|
+
type RichTextToolbarVariant = "default" | "minimal";
|
|
3
|
+
interface RichTextToolbarProps {
|
|
4
|
+
editor: Editor;
|
|
5
|
+
variant?: RichTextToolbarVariant;
|
|
6
|
+
}
|
|
7
|
+
export declare function RichTextToolbar({ editor, variant, }: RichTextToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatFileSize(bytes: number): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatTimestamp(iso: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function shuffle<T>(array: T[]): T[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truncate text to a maximum length, appending a suffix if truncated.
|
|
3
|
+
*/
|
|
4
|
+
export declare function truncateText(text: string, maxLength: number, suffix?: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Format a decimal value as a percentage string.
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatPercentage(value: number, decimals?: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Return the singular or plural form of a word based on count.
|
|
11
|
+
*/
|
|
12
|
+
export declare function pluralize(count: number, singular: string, plural?: string): string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { VideoBookmarkProps } from './types';
|
|
2
|
-
export declare const VideoBookmark:
|
|
2
|
+
export declare const VideoBookmark: import('react').NamedExoticComponent<VideoBookmarkProps>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { VideoPlaylistItemProps } from './types';
|
|
2
|
-
export declare const VideoPlaylistItem:
|
|
2
|
+
export declare const VideoPlaylistItem: import('react').NamedExoticComponent<VideoPlaylistItemProps>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydralms/components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "React component library for LMS platforms",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "HydraLMS",
|
|
@@ -115,6 +115,18 @@
|
|
|
115
115
|
"types": "./src/sections/CertificateViewer/CertificateViewer.tsx",
|
|
116
116
|
"default": "./src/sections/CertificateViewer/CertificateViewer.tsx"
|
|
117
117
|
},
|
|
118
|
+
"./sections/RubricView": {
|
|
119
|
+
"types": "./src/sections/RubricView/RubricView.tsx",
|
|
120
|
+
"default": "./src/sections/RubricView/RubricView.tsx"
|
|
121
|
+
},
|
|
122
|
+
"./sections/RequirementsChecklist": {
|
|
123
|
+
"types": "./src/sections/RequirementsChecklist/RequirementsChecklist.tsx",
|
|
124
|
+
"default": "./src/sections/RequirementsChecklist/RequirementsChecklist.tsx"
|
|
125
|
+
},
|
|
126
|
+
"./sections/ForumBoard": {
|
|
127
|
+
"types": "./src/sections/ForumBoard/ForumBoard.tsx",
|
|
128
|
+
"default": "./src/sections/ForumBoard/ForumBoard.tsx"
|
|
129
|
+
},
|
|
118
130
|
"./modules": {
|
|
119
131
|
"types": "./src/modules/index.ts",
|
|
120
132
|
"default": "./src/modules/index.ts"
|
|
@@ -131,6 +143,30 @@
|
|
|
131
143
|
"types": "./src/modules/CoursePlayer/CoursePlayer.tsx",
|
|
132
144
|
"default": "./src/modules/CoursePlayer/CoursePlayer.tsx"
|
|
133
145
|
},
|
|
146
|
+
"./modules/ExamModule": {
|
|
147
|
+
"types": "./src/modules/ExamModule/ExamModule.tsx",
|
|
148
|
+
"default": "./src/modules/ExamModule/ExamModule.tsx"
|
|
149
|
+
},
|
|
150
|
+
"./modules/SurveyModule": {
|
|
151
|
+
"types": "./src/modules/SurveyModule/SurveyModule.tsx",
|
|
152
|
+
"default": "./src/modules/SurveyModule/SurveyModule.tsx"
|
|
153
|
+
},
|
|
154
|
+
"./modules/GradeCenterModule": {
|
|
155
|
+
"types": "./src/modules/GradeCenterModule/GradeCenterModule.tsx",
|
|
156
|
+
"default": "./src/modules/GradeCenterModule/GradeCenterModule.tsx"
|
|
157
|
+
},
|
|
158
|
+
"./modules/AssignmentModule": {
|
|
159
|
+
"types": "./src/modules/AssignmentModule/AssignmentModule.tsx",
|
|
160
|
+
"default": "./src/modules/AssignmentModule/AssignmentModule.tsx"
|
|
161
|
+
},
|
|
162
|
+
"./modules/CertificateModule": {
|
|
163
|
+
"types": "./src/modules/CertificateModule/CertificateModule.tsx",
|
|
164
|
+
"default": "./src/modules/CertificateModule/CertificateModule.tsx"
|
|
165
|
+
},
|
|
166
|
+
"./modules/DiscussionModule": {
|
|
167
|
+
"types": "./src/modules/DiscussionModule/DiscussionModule.tsx",
|
|
168
|
+
"default": "./src/modules/DiscussionModule/DiscussionModule.tsx"
|
|
169
|
+
},
|
|
134
170
|
"./provider": {
|
|
135
171
|
"types": "./src/provider/index.ts",
|
|
136
172
|
"default": "./src/provider/index.ts"
|
|
@@ -183,7 +219,6 @@
|
|
|
183
219
|
"types": "./src/provider/HydraProvider.tsx",
|
|
184
220
|
"default": "./src/provider/HydraProvider.tsx"
|
|
185
221
|
},
|
|
186
|
-
"./*": "./src/*",
|
|
187
222
|
"./styles.css": "./src/styles/globals.css",
|
|
188
223
|
"./styles/globals.css": "./src/styles/globals.css",
|
|
189
224
|
"./package.json": "./package.json"
|
|
@@ -203,17 +238,65 @@
|
|
|
203
238
|
"import": "./dist/sections.js",
|
|
204
239
|
"require": "./dist/sections.cjs"
|
|
205
240
|
},
|
|
241
|
+
"./sections/*": {
|
|
242
|
+
"types": "./src/sections/*/index.ts",
|
|
243
|
+
"default": "./src/sections/*/index.ts"
|
|
244
|
+
},
|
|
206
245
|
"./modules": {
|
|
207
246
|
"types": "./dist/modules/index.d.ts",
|
|
208
247
|
"import": "./dist/modules.js",
|
|
209
248
|
"require": "./dist/modules.cjs"
|
|
210
249
|
},
|
|
250
|
+
"./modules/*": {
|
|
251
|
+
"types": "./src/modules/*/index.ts",
|
|
252
|
+
"default": "./src/modules/*/index.ts"
|
|
253
|
+
},
|
|
254
|
+
"./provider": {
|
|
255
|
+
"types": "./src/provider/index.ts",
|
|
256
|
+
"default": "./src/provider/index.ts"
|
|
257
|
+
},
|
|
258
|
+
"./questions": {
|
|
259
|
+
"types": "./src/questions/index.ts",
|
|
260
|
+
"default": "./src/questions/index.ts"
|
|
261
|
+
},
|
|
262
|
+
"./assessment-toolbar": {
|
|
263
|
+
"types": "./src/assessment-toolbar/index.ts",
|
|
264
|
+
"default": "./src/assessment-toolbar/index.ts"
|
|
265
|
+
},
|
|
266
|
+
"./flashcards": {
|
|
267
|
+
"types": "./src/flashcards/index.ts",
|
|
268
|
+
"default": "./src/flashcards/index.ts"
|
|
269
|
+
},
|
|
270
|
+
"./curriculum": {
|
|
271
|
+
"types": "./src/curriculum/index.ts",
|
|
272
|
+
"default": "./src/curriculum/index.ts"
|
|
273
|
+
},
|
|
274
|
+
"./video": {
|
|
275
|
+
"types": "./src/video/index.ts",
|
|
276
|
+
"default": "./src/video/index.ts"
|
|
277
|
+
},
|
|
278
|
+
"./progress": {
|
|
279
|
+
"types": "./src/progress/index.ts",
|
|
280
|
+
"default": "./src/progress/index.ts"
|
|
281
|
+
},
|
|
282
|
+
"./feedback": {
|
|
283
|
+
"types": "./src/feedback/index.ts",
|
|
284
|
+
"default": "./src/feedback/index.ts"
|
|
285
|
+
},
|
|
286
|
+
"./content": {
|
|
287
|
+
"types": "./src/content/index.ts",
|
|
288
|
+
"default": "./src/content/index.ts"
|
|
289
|
+
},
|
|
290
|
+
"./social": {
|
|
291
|
+
"types": "./src/social/index.ts",
|
|
292
|
+
"default": "./src/social/index.ts"
|
|
293
|
+
},
|
|
211
294
|
"./styles.css": "./dist/components.css",
|
|
212
295
|
"./package.json": "./package.json"
|
|
213
296
|
}
|
|
214
297
|
},
|
|
215
298
|
"scripts": {
|
|
216
|
-
"build": "
|
|
299
|
+
"build": "vite build",
|
|
217
300
|
"dev": "vite build --watch",
|
|
218
301
|
"generate-docs": "tsx scripts/generate-docs.ts",
|
|
219
302
|
"check-docs": "tsx scripts/generate-docs.ts --check",
|
|
@@ -228,6 +311,11 @@
|
|
|
228
311
|
"tailwindcss": "^4.0.0"
|
|
229
312
|
},
|
|
230
313
|
"dependencies": {
|
|
314
|
+
"@tiptap/extension-link": "^3.20.1",
|
|
315
|
+
"@tiptap/extension-placeholder": "^3.20.1",
|
|
316
|
+
"@tiptap/extension-underline": "^3.20.1",
|
|
317
|
+
"@tiptap/react": "^3.20.1",
|
|
318
|
+
"@tiptap/starter-kit": "^3.20.1",
|
|
231
319
|
"class-variance-authority": "^0.7.1",
|
|
232
320
|
"clsx": "^2.1.1",
|
|
233
321
|
"lucide-react": "^0.475.0",
|
|
@@ -244,6 +332,7 @@
|
|
|
244
332
|
"jsdom": "^28.1.0",
|
|
245
333
|
"react": "^19.0.0",
|
|
246
334
|
"react-docgen-typescript": "^2.3.0",
|
|
335
|
+
"react-dom": "^19.0.0",
|
|
247
336
|
"tailwindcss": "^4.0.0",
|
|
248
337
|
"tsx": "^4.19.0",
|
|
249
338
|
"typescript": "~5.7.0",
|
|
@@ -2,6 +2,7 @@ import { ChevronLeft, ChevronRight, Send } from "lucide-react";
|
|
|
2
2
|
import { TimerDisplay } from "./timer-display";
|
|
3
3
|
import { QuestionNavigator } from "./question-navigator";
|
|
4
4
|
import { Button } from "../ui/button";
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
5
6
|
import type { AssessmentToolbarProps } from "./types";
|
|
6
7
|
|
|
7
8
|
export const AssessmentToolbar = ({
|
|
@@ -16,7 +17,6 @@ export const AssessmentToolbar = ({
|
|
|
16
17
|
timeLimitSeconds,
|
|
17
18
|
questions,
|
|
18
19
|
onNavigateToQuestion,
|
|
19
|
-
onToggleFlag,
|
|
20
20
|
currentQuestionUid,
|
|
21
21
|
isCompleted = false,
|
|
22
22
|
isSubmitting = false,
|
|
@@ -27,70 +27,75 @@ export const AssessmentToolbar = ({
|
|
|
27
27
|
const showNavigator = questions && questions.length > 0;
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
|
-
<div className="rounded-lg border border-border
|
|
31
|
-
{/*
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
<div className="flex items-center gap-2 rounded-lg border border-border bg-muted px-2 py-1.5 shadow-sm">
|
|
31
|
+
{/* Previous */}
|
|
32
|
+
<Button
|
|
33
|
+
variant="ghost"
|
|
34
|
+
size="icon"
|
|
35
|
+
className="size-8 shrink-0 rounded-md"
|
|
36
|
+
disabled={!hasPrevious || readOnly}
|
|
37
|
+
onClick={onPrevious}
|
|
38
|
+
>
|
|
39
|
+
<ChevronLeft size={16} />
|
|
40
|
+
<span className="sr-only">Previous</span>
|
|
41
|
+
</Button>
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
{/* Question indicator (shown when no navigator) */}
|
|
44
|
+
{!showNavigator && (
|
|
45
|
+
<span className="text-xs font-medium text-muted-foreground whitespace-nowrap">
|
|
46
|
+
<span className="font-bold text-foreground">{currentQuestionIndex + 1}</span>
|
|
47
|
+
<span className="mx-0.5">/</span>
|
|
48
|
+
{totalQuestions}
|
|
49
|
+
</span>
|
|
50
|
+
)}
|
|
46
51
|
|
|
47
|
-
{/* Navigator */}
|
|
52
|
+
{/* Navigator chips */}
|
|
48
53
|
{showNavigator && (
|
|
49
|
-
<div className="
|
|
54
|
+
<div className="min-w-0 flex-1 overflow-x-auto [scrollbar-width:none]">
|
|
50
55
|
<QuestionNavigator
|
|
51
56
|
questions={questions}
|
|
52
57
|
currentQuestionUid={currentQuestionUid}
|
|
53
58
|
onNavigate={onNavigateToQuestion}
|
|
54
|
-
onToggleFlag={onToggleFlag}
|
|
55
59
|
readOnly={readOnly}
|
|
56
60
|
/>
|
|
57
61
|
</div>
|
|
58
62
|
)}
|
|
59
63
|
|
|
60
|
-
{/*
|
|
61
|
-
<div className="flex
|
|
64
|
+
{/* Spacer when no navigator */}
|
|
65
|
+
{!showNavigator && <div className="flex-1" />}
|
|
66
|
+
|
|
67
|
+
{/* Timer */}
|
|
68
|
+
{showTimer && (
|
|
69
|
+
<TimerDisplay
|
|
70
|
+
timeElapsedSeconds={timeElapsedSeconds}
|
|
71
|
+
timeLimitSeconds={timeLimitSeconds}
|
|
72
|
+
/>
|
|
73
|
+
)}
|
|
74
|
+
|
|
75
|
+
{/* Next / Submit */}
|
|
76
|
+
{!hasNext || isCompleted ? (
|
|
62
77
|
<Button
|
|
63
|
-
variant="
|
|
78
|
+
variant={isCompleted ? "secondary" : "default"}
|
|
64
79
|
size="sm"
|
|
65
|
-
className="rounded-
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
className={cn("shrink-0 rounded-md", isSubmitting && "gap-0")}
|
|
81
|
+
onClick={onSubmit}
|
|
82
|
+
disabled={readOnly || isSubmitting}
|
|
68
83
|
>
|
|
69
|
-
|
|
84
|
+
{isSubmitting ? "..." : isCompleted ? "Review" : "Submit"}
|
|
85
|
+
{!isSubmitting && <Send size={14} />}
|
|
70
86
|
</Button>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
) : (
|
|
84
|
-
<Button
|
|
85
|
-
size="sm"
|
|
86
|
-
className="rounded-lg"
|
|
87
|
-
disabled={!hasNext || readOnly}
|
|
88
|
-
onClick={onNext}
|
|
89
|
-
>
|
|
90
|
-
Next <ChevronRight size={16} />
|
|
91
|
-
</Button>
|
|
92
|
-
)}
|
|
93
|
-
</div>
|
|
87
|
+
) : (
|
|
88
|
+
<Button
|
|
89
|
+
variant="ghost"
|
|
90
|
+
size="icon"
|
|
91
|
+
className="size-8 shrink-0 rounded-md"
|
|
92
|
+
disabled={!hasNext || readOnly}
|
|
93
|
+
onClick={onNext}
|
|
94
|
+
>
|
|
95
|
+
<ChevronRight size={16} />
|
|
96
|
+
<span className="sr-only">Next</span>
|
|
97
|
+
</Button>
|
|
98
|
+
)}
|
|
94
99
|
</div>
|
|
95
100
|
);
|
|
96
101
|
};
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
export { AssessmentToolbar } from "./assessment-toolbar";
|
|
2
2
|
export { TimerDisplay } from "./timer-display";
|
|
3
3
|
export { QuestionNavigator } from "./question-navigator";
|
|
4
|
+
export { QuestionHeaderBar } from "./question-header-bar";
|
|
5
|
+
export { QuestionMaterialsDrawer } from "./question-materials-drawer";
|
|
6
|
+
export { useCountdown } from "./use-countdown";
|
|
4
7
|
|
|
5
8
|
export type {
|
|
6
9
|
AssessmentToolbarProps,
|
|
7
10
|
TimerDisplayProps,
|
|
8
11
|
QuestionNavigatorProps,
|
|
9
12
|
QuestionNavigatorItem,
|
|
13
|
+
QuestionHeaderBarProps,
|
|
14
|
+
QuestionMaterialsDrawerProps,
|
|
10
15
|
} from "./types";
|
|
16
|
+
export type { UseCountdownOptions, UseCountdownReturn } from "./use-countdown";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BookOpen, Flag } from "lucide-react";
|
|
2
|
+
import { Button } from "../ui/button";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
import type { QuestionHeaderBarProps } from "./types";
|
|
5
|
+
|
|
6
|
+
export const QuestionHeaderBar = ({
|
|
7
|
+
questionNumber,
|
|
8
|
+
totalQuestions,
|
|
9
|
+
isFlagged,
|
|
10
|
+
onToggleFlag,
|
|
11
|
+
hasMaterials = false,
|
|
12
|
+
onOpenMaterials,
|
|
13
|
+
readOnly = false,
|
|
14
|
+
}: QuestionHeaderBarProps) => {
|
|
15
|
+
return (
|
|
16
|
+
<div className="flex items-center justify-between pb-3 border-b border-border">
|
|
17
|
+
<span className="text-sm font-semibold text-foreground">
|
|
18
|
+
Question {questionNumber}{" "}
|
|
19
|
+
<span className="font-normal text-muted-foreground">
|
|
20
|
+
of {totalQuestions}
|
|
21
|
+
</span>
|
|
22
|
+
</span>
|
|
23
|
+
|
|
24
|
+
{!readOnly && (
|
|
25
|
+
<div className="flex items-center gap-1">
|
|
26
|
+
{hasMaterials && onOpenMaterials && (
|
|
27
|
+
<Button
|
|
28
|
+
variant="ghost"
|
|
29
|
+
size="sm"
|
|
30
|
+
className="gap-1.5 text-muted-foreground hover:text-foreground"
|
|
31
|
+
onClick={onOpenMaterials}
|
|
32
|
+
>
|
|
33
|
+
<BookOpen size={14} />
|
|
34
|
+
Related Material
|
|
35
|
+
</Button>
|
|
36
|
+
)}
|
|
37
|
+
|
|
38
|
+
{onToggleFlag && (
|
|
39
|
+
<Button
|
|
40
|
+
variant="ghost"
|
|
41
|
+
size="icon"
|
|
42
|
+
className={cn(
|
|
43
|
+
"size-8",
|
|
44
|
+
isFlagged
|
|
45
|
+
? "text-warning hover:text-warning/80"
|
|
46
|
+
: "text-muted-foreground hover:text-warning",
|
|
47
|
+
)}
|
|
48
|
+
onClick={onToggleFlag}
|
|
49
|
+
aria-label={isFlagged ? "Unflag question" : "Flag question"}
|
|
50
|
+
>
|
|
51
|
+
<Flag
|
|
52
|
+
size={14}
|
|
53
|
+
fill={isFlagged ? "currentColor" : "none"}
|
|
54
|
+
/>
|
|
55
|
+
</Button>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|