payload-quiz-plugin 1.0.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.
@@ -0,0 +1,303 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { ClassValue } from 'clsx';
4
+
5
+ /**
6
+ * Quiz Plugin Types
7
+ * These types are standalone and don't depend on generated payload-types
8
+ */
9
+ /**
10
+ * Rich text data structure (Lexical format)
11
+ */
12
+ type RichTextData = {
13
+ root: {
14
+ type: string;
15
+ children: unknown[];
16
+ [key: string]: unknown;
17
+ };
18
+ [key: string]: unknown;
19
+ } | null;
20
+ /**
21
+ * Component for rendering rich text content
22
+ * This allows projects to provide their own RichText component
23
+ */
24
+ type RichTextRenderer = React.ComponentType<{
25
+ data: RichTextData;
26
+ enableGutter?: boolean;
27
+ className?: string;
28
+ }>;
29
+ /**
30
+ * Choice option in a question
31
+ */
32
+ type QuizChoice = {
33
+ id?: string | null;
34
+ text: string;
35
+ isCorrect?: boolean | null;
36
+ explanation?: RichTextData;
37
+ };
38
+ /**
39
+ * Question structure for the quiz
40
+ */
41
+ type QuizQuestion = {
42
+ id: number;
43
+ question: string;
44
+ requiredAnswers?: number | null;
45
+ choices?: QuizChoice[] | null;
46
+ explanation?: RichTextData;
47
+ };
48
+ /**
49
+ * Test configuration
50
+ */
51
+ type QuizTest = {
52
+ id?: number;
53
+ title: string;
54
+ slug?: string | null;
55
+ questionCount?: number | null;
56
+ timeLimit?: number | null;
57
+ passMark?: number | null;
58
+ questionsPerPage?: number | null;
59
+ allowGoBack?: boolean | null;
60
+ requireAllAnswered?: boolean | null;
61
+ };
62
+ /**
63
+ * User's answer to a question
64
+ */
65
+ type UserAnswer = {
66
+ questionId: number;
67
+ selectedChoiceIds: string[];
68
+ };
69
+ /**
70
+ * Quiz state for the reducer
71
+ */
72
+ type QuizState = {
73
+ status: 'loading' | 'ready' | 'in_progress' | 'completed';
74
+ questions: QuizQuestion[];
75
+ currentQuestionIndex: number;
76
+ answers: Map<number, string[]>;
77
+ startTime: number | null;
78
+ endTime: number | null;
79
+ timeRemaining: number;
80
+ };
81
+ /**
82
+ * Actions for the quiz reducer
83
+ */
84
+ type QuizAction = {
85
+ type: 'SET_QUESTIONS';
86
+ questions: QuizQuestion[];
87
+ } | {
88
+ type: 'START_QUIZ';
89
+ timeLimit: number;
90
+ } | {
91
+ type: 'SELECT_ANSWER';
92
+ questionId: number;
93
+ choiceId: string;
94
+ isMultiple: boolean;
95
+ } | {
96
+ type: 'DESELECT_ANSWER';
97
+ questionId: number;
98
+ choiceId: string;
99
+ } | {
100
+ type: 'NEXT_QUESTION';
101
+ } | {
102
+ type: 'PREV_QUESTION';
103
+ } | {
104
+ type: 'GO_TO_QUESTION';
105
+ index: number;
106
+ } | {
107
+ type: 'TICK_TIMER';
108
+ } | {
109
+ type: 'FINISH_QUIZ';
110
+ };
111
+ /**
112
+ * Result of the quiz
113
+ */
114
+ type QuizResult = {
115
+ totalQuestions: number;
116
+ correctAnswers: number;
117
+ incorrectAnswers: number;
118
+ unanswered: number;
119
+ score: number;
120
+ passed: boolean;
121
+ passMark: number;
122
+ timeTaken: number;
123
+ questionResults: QuestionResult[];
124
+ };
125
+ /**
126
+ * Result for a single question
127
+ */
128
+ type QuestionResult = {
129
+ questionId: number;
130
+ question: string;
131
+ requiredAnswers: number;
132
+ isCorrect: boolean;
133
+ userAnswers: string[];
134
+ correctAnswers: string[];
135
+ choices: {
136
+ id: string;
137
+ text: string;
138
+ isCorrect: boolean;
139
+ wasSelected: boolean;
140
+ explanation?: RichTextData;
141
+ }[];
142
+ explanation?: RichTextData;
143
+ };
144
+
145
+ type QuizContextType = {
146
+ state: QuizState;
147
+ dispatch: React$1.Dispatch<QuizAction>;
148
+ currentQuestion: QuizQuestion | null;
149
+ isFirstQuestion: boolean;
150
+ isLastQuestion: boolean;
151
+ answeredCount: number;
152
+ selectAnswer: (choiceId: string) => void;
153
+ deselectAnswer: (choiceId: string) => void;
154
+ nextQuestion: () => void;
155
+ prevQuestion: () => void;
156
+ goToQuestion: (index: number) => void;
157
+ finishQuiz: () => void;
158
+ calculateResults: (passMark: number) => QuizResult;
159
+ };
160
+ declare function QuizProvider({ children, questions, timeLimit, }: {
161
+ children: React$1.ReactNode;
162
+ questions: QuizQuestion[];
163
+ timeLimit: number;
164
+ }): react_jsx_runtime.JSX.Element;
165
+ declare function useQuiz(): QuizContextType;
166
+
167
+ type Props$4 = {
168
+ timeRemaining: number;
169
+ className?: string;
170
+ };
171
+ declare function QuizTimer({ timeRemaining, className }: Props$4): react_jsx_runtime.JSX.Element;
172
+
173
+ type Props$3 = {
174
+ currentIndex: number;
175
+ totalQuestions: number;
176
+ answeredQuestions: Set<number>;
177
+ onQuestionClick?: (index: number) => void;
178
+ allowNavigation?: boolean;
179
+ className?: string;
180
+ };
181
+ declare function QuizProgress({ currentIndex, totalQuestions, answeredQuestions, onQuestionClick, allowNavigation, className, }: Props$3): react_jsx_runtime.JSX.Element;
182
+
183
+ type Props$2 = {
184
+ question: QuizQuestion;
185
+ selectedChoiceIds: string[];
186
+ onSelectChoice: (choiceId: string) => void;
187
+ onDeselectChoice: (choiceId: string) => void;
188
+ className?: string;
189
+ };
190
+ declare function QuestionCard({ question, selectedChoiceIds, onSelectChoice, onDeselectChoice, className, }: Props$2): react_jsx_runtime.JSX.Element;
191
+
192
+ type Props$1 = {
193
+ id: string;
194
+ text: string;
195
+ isSelected: boolean;
196
+ isMultiple: boolean;
197
+ onClick: () => void;
198
+ disabled?: boolean;
199
+ showResult?: boolean;
200
+ isCorrect?: boolean;
201
+ className?: string;
202
+ };
203
+ declare function ChoiceOption({ id, text, isSelected, isMultiple, onClick, disabled, showResult, isCorrect, className, }: Props$1): react_jsx_runtime.JSX.Element;
204
+
205
+ type Props = {
206
+ result: QuizResult;
207
+ testSlug: string;
208
+ className?: string;
209
+ /** Optional custom component for rendering rich text explanations */
210
+ RichTextComponent?: RichTextRenderer;
211
+ };
212
+ declare function QuizResults({ result, testSlug, className, RichTextComponent }: Props): react_jsx_runtime.JSX.Element;
213
+
214
+ /**
215
+ * Types for TestCard component
216
+ * These are standalone and don't depend on generated payload-types
217
+ */
218
+ /**
219
+ * Media object structure (simplified)
220
+ */
221
+ type TestCardMedia = {
222
+ url?: string | null;
223
+ alt?: string | null;
224
+ width?: number | null;
225
+ height?: number | null;
226
+ [key: string]: unknown;
227
+ };
228
+ /**
229
+ * Certificate type structure
230
+ */
231
+ type TestCardCertificateType = {
232
+ id?: number | string;
233
+ shortName?: string | null;
234
+ title?: string | null;
235
+ [key: string]: unknown;
236
+ };
237
+ /**
238
+ * Test meta information
239
+ */
240
+ type TestCardMeta = {
241
+ title?: string | null;
242
+ description?: string | null;
243
+ image?: TestCardMedia | number | string | null;
244
+ };
245
+ /**
246
+ * Data structure for a test card
247
+ */
248
+ type TestCardData = {
249
+ id?: number | string;
250
+ slug?: string | null;
251
+ title?: string | null;
252
+ certificateType?: TestCardCertificateType | number | string | null;
253
+ meta?: TestCardMeta | null;
254
+ questionCount?: number | null;
255
+ timeLimit?: number | null;
256
+ passMark?: number | null;
257
+ };
258
+ /**
259
+ * Props for the TestCard component
260
+ */
261
+ type TestCardProps = {
262
+ /** Test data to display */
263
+ doc?: TestCardData;
264
+ /** Override title */
265
+ title?: string;
266
+ /** Additional class names */
267
+ className?: string;
268
+ /** Custom media renderer component */
269
+ MediaComponent?: React.ComponentType<{
270
+ resource: TestCardMedia;
271
+ size?: string;
272
+ fill?: boolean;
273
+ pictureClassName?: string;
274
+ imgClassName?: string;
275
+ }>;
276
+ };
277
+
278
+ /**
279
+ * TestCard component for displaying test information in a card format
280
+ *
281
+ * @example
282
+ * ```tsx
283
+ * import { TestCard } from '@/plugins/quiz/client'
284
+ * import { Media } from '@/components/Media'
285
+ *
286
+ * <TestCard
287
+ * doc={test}
288
+ * MediaComponent={({ resource, size }) => (
289
+ * <Media resource={resource} size={size} />
290
+ * )}
291
+ * />
292
+ * ```
293
+ */
294
+ declare function TestCard({ doc, title: titleFromProps, className, MediaComponent }: TestCardProps): react_jsx_runtime.JSX.Element;
295
+
296
+ /**
297
+ * Utility function for merging Tailwind CSS classes
298
+ * This is a common pattern used with ShadCN/Tailwind
299
+ */
300
+
301
+ declare function cn(...inputs: ClassValue[]): string;
302
+
303
+ export { ChoiceOption, QuestionCard, type QuestionResult, type QuizAction, type QuizChoice, QuizProgress, QuizProvider, type QuizQuestion, type QuizResult, QuizResults, type QuizState, type QuizTest, QuizTimer, type RichTextData, type RichTextRenderer, TestCard, type TestCardCertificateType, type TestCardData, type TestCardMedia, type TestCardMeta, type TestCardProps, type UserAnswer, cn, useQuiz };
@@ -0,0 +1,303 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { ClassValue } from 'clsx';
4
+
5
+ /**
6
+ * Quiz Plugin Types
7
+ * These types are standalone and don't depend on generated payload-types
8
+ */
9
+ /**
10
+ * Rich text data structure (Lexical format)
11
+ */
12
+ type RichTextData = {
13
+ root: {
14
+ type: string;
15
+ children: unknown[];
16
+ [key: string]: unknown;
17
+ };
18
+ [key: string]: unknown;
19
+ } | null;
20
+ /**
21
+ * Component for rendering rich text content
22
+ * This allows projects to provide their own RichText component
23
+ */
24
+ type RichTextRenderer = React.ComponentType<{
25
+ data: RichTextData;
26
+ enableGutter?: boolean;
27
+ className?: string;
28
+ }>;
29
+ /**
30
+ * Choice option in a question
31
+ */
32
+ type QuizChoice = {
33
+ id?: string | null;
34
+ text: string;
35
+ isCorrect?: boolean | null;
36
+ explanation?: RichTextData;
37
+ };
38
+ /**
39
+ * Question structure for the quiz
40
+ */
41
+ type QuizQuestion = {
42
+ id: number;
43
+ question: string;
44
+ requiredAnswers?: number | null;
45
+ choices?: QuizChoice[] | null;
46
+ explanation?: RichTextData;
47
+ };
48
+ /**
49
+ * Test configuration
50
+ */
51
+ type QuizTest = {
52
+ id?: number;
53
+ title: string;
54
+ slug?: string | null;
55
+ questionCount?: number | null;
56
+ timeLimit?: number | null;
57
+ passMark?: number | null;
58
+ questionsPerPage?: number | null;
59
+ allowGoBack?: boolean | null;
60
+ requireAllAnswered?: boolean | null;
61
+ };
62
+ /**
63
+ * User's answer to a question
64
+ */
65
+ type UserAnswer = {
66
+ questionId: number;
67
+ selectedChoiceIds: string[];
68
+ };
69
+ /**
70
+ * Quiz state for the reducer
71
+ */
72
+ type QuizState = {
73
+ status: 'loading' | 'ready' | 'in_progress' | 'completed';
74
+ questions: QuizQuestion[];
75
+ currentQuestionIndex: number;
76
+ answers: Map<number, string[]>;
77
+ startTime: number | null;
78
+ endTime: number | null;
79
+ timeRemaining: number;
80
+ };
81
+ /**
82
+ * Actions for the quiz reducer
83
+ */
84
+ type QuizAction = {
85
+ type: 'SET_QUESTIONS';
86
+ questions: QuizQuestion[];
87
+ } | {
88
+ type: 'START_QUIZ';
89
+ timeLimit: number;
90
+ } | {
91
+ type: 'SELECT_ANSWER';
92
+ questionId: number;
93
+ choiceId: string;
94
+ isMultiple: boolean;
95
+ } | {
96
+ type: 'DESELECT_ANSWER';
97
+ questionId: number;
98
+ choiceId: string;
99
+ } | {
100
+ type: 'NEXT_QUESTION';
101
+ } | {
102
+ type: 'PREV_QUESTION';
103
+ } | {
104
+ type: 'GO_TO_QUESTION';
105
+ index: number;
106
+ } | {
107
+ type: 'TICK_TIMER';
108
+ } | {
109
+ type: 'FINISH_QUIZ';
110
+ };
111
+ /**
112
+ * Result of the quiz
113
+ */
114
+ type QuizResult = {
115
+ totalQuestions: number;
116
+ correctAnswers: number;
117
+ incorrectAnswers: number;
118
+ unanswered: number;
119
+ score: number;
120
+ passed: boolean;
121
+ passMark: number;
122
+ timeTaken: number;
123
+ questionResults: QuestionResult[];
124
+ };
125
+ /**
126
+ * Result for a single question
127
+ */
128
+ type QuestionResult = {
129
+ questionId: number;
130
+ question: string;
131
+ requiredAnswers: number;
132
+ isCorrect: boolean;
133
+ userAnswers: string[];
134
+ correctAnswers: string[];
135
+ choices: {
136
+ id: string;
137
+ text: string;
138
+ isCorrect: boolean;
139
+ wasSelected: boolean;
140
+ explanation?: RichTextData;
141
+ }[];
142
+ explanation?: RichTextData;
143
+ };
144
+
145
+ type QuizContextType = {
146
+ state: QuizState;
147
+ dispatch: React$1.Dispatch<QuizAction>;
148
+ currentQuestion: QuizQuestion | null;
149
+ isFirstQuestion: boolean;
150
+ isLastQuestion: boolean;
151
+ answeredCount: number;
152
+ selectAnswer: (choiceId: string) => void;
153
+ deselectAnswer: (choiceId: string) => void;
154
+ nextQuestion: () => void;
155
+ prevQuestion: () => void;
156
+ goToQuestion: (index: number) => void;
157
+ finishQuiz: () => void;
158
+ calculateResults: (passMark: number) => QuizResult;
159
+ };
160
+ declare function QuizProvider({ children, questions, timeLimit, }: {
161
+ children: React$1.ReactNode;
162
+ questions: QuizQuestion[];
163
+ timeLimit: number;
164
+ }): react_jsx_runtime.JSX.Element;
165
+ declare function useQuiz(): QuizContextType;
166
+
167
+ type Props$4 = {
168
+ timeRemaining: number;
169
+ className?: string;
170
+ };
171
+ declare function QuizTimer({ timeRemaining, className }: Props$4): react_jsx_runtime.JSX.Element;
172
+
173
+ type Props$3 = {
174
+ currentIndex: number;
175
+ totalQuestions: number;
176
+ answeredQuestions: Set<number>;
177
+ onQuestionClick?: (index: number) => void;
178
+ allowNavigation?: boolean;
179
+ className?: string;
180
+ };
181
+ declare function QuizProgress({ currentIndex, totalQuestions, answeredQuestions, onQuestionClick, allowNavigation, className, }: Props$3): react_jsx_runtime.JSX.Element;
182
+
183
+ type Props$2 = {
184
+ question: QuizQuestion;
185
+ selectedChoiceIds: string[];
186
+ onSelectChoice: (choiceId: string) => void;
187
+ onDeselectChoice: (choiceId: string) => void;
188
+ className?: string;
189
+ };
190
+ declare function QuestionCard({ question, selectedChoiceIds, onSelectChoice, onDeselectChoice, className, }: Props$2): react_jsx_runtime.JSX.Element;
191
+
192
+ type Props$1 = {
193
+ id: string;
194
+ text: string;
195
+ isSelected: boolean;
196
+ isMultiple: boolean;
197
+ onClick: () => void;
198
+ disabled?: boolean;
199
+ showResult?: boolean;
200
+ isCorrect?: boolean;
201
+ className?: string;
202
+ };
203
+ declare function ChoiceOption({ id, text, isSelected, isMultiple, onClick, disabled, showResult, isCorrect, className, }: Props$1): react_jsx_runtime.JSX.Element;
204
+
205
+ type Props = {
206
+ result: QuizResult;
207
+ testSlug: string;
208
+ className?: string;
209
+ /** Optional custom component for rendering rich text explanations */
210
+ RichTextComponent?: RichTextRenderer;
211
+ };
212
+ declare function QuizResults({ result, testSlug, className, RichTextComponent }: Props): react_jsx_runtime.JSX.Element;
213
+
214
+ /**
215
+ * Types for TestCard component
216
+ * These are standalone and don't depend on generated payload-types
217
+ */
218
+ /**
219
+ * Media object structure (simplified)
220
+ */
221
+ type TestCardMedia = {
222
+ url?: string | null;
223
+ alt?: string | null;
224
+ width?: number | null;
225
+ height?: number | null;
226
+ [key: string]: unknown;
227
+ };
228
+ /**
229
+ * Certificate type structure
230
+ */
231
+ type TestCardCertificateType = {
232
+ id?: number | string;
233
+ shortName?: string | null;
234
+ title?: string | null;
235
+ [key: string]: unknown;
236
+ };
237
+ /**
238
+ * Test meta information
239
+ */
240
+ type TestCardMeta = {
241
+ title?: string | null;
242
+ description?: string | null;
243
+ image?: TestCardMedia | number | string | null;
244
+ };
245
+ /**
246
+ * Data structure for a test card
247
+ */
248
+ type TestCardData = {
249
+ id?: number | string;
250
+ slug?: string | null;
251
+ title?: string | null;
252
+ certificateType?: TestCardCertificateType | number | string | null;
253
+ meta?: TestCardMeta | null;
254
+ questionCount?: number | null;
255
+ timeLimit?: number | null;
256
+ passMark?: number | null;
257
+ };
258
+ /**
259
+ * Props for the TestCard component
260
+ */
261
+ type TestCardProps = {
262
+ /** Test data to display */
263
+ doc?: TestCardData;
264
+ /** Override title */
265
+ title?: string;
266
+ /** Additional class names */
267
+ className?: string;
268
+ /** Custom media renderer component */
269
+ MediaComponent?: React.ComponentType<{
270
+ resource: TestCardMedia;
271
+ size?: string;
272
+ fill?: boolean;
273
+ pictureClassName?: string;
274
+ imgClassName?: string;
275
+ }>;
276
+ };
277
+
278
+ /**
279
+ * TestCard component for displaying test information in a card format
280
+ *
281
+ * @example
282
+ * ```tsx
283
+ * import { TestCard } from '@/plugins/quiz/client'
284
+ * import { Media } from '@/components/Media'
285
+ *
286
+ * <TestCard
287
+ * doc={test}
288
+ * MediaComponent={({ resource, size }) => (
289
+ * <Media resource={resource} size={size} />
290
+ * )}
291
+ * />
292
+ * ```
293
+ */
294
+ declare function TestCard({ doc, title: titleFromProps, className, MediaComponent }: TestCardProps): react_jsx_runtime.JSX.Element;
295
+
296
+ /**
297
+ * Utility function for merging Tailwind CSS classes
298
+ * This is a common pattern used with ShadCN/Tailwind
299
+ */
300
+
301
+ declare function cn(...inputs: ClassValue[]): string;
302
+
303
+ export { ChoiceOption, QuestionCard, type QuestionResult, type QuizAction, type QuizChoice, QuizProgress, QuizProvider, type QuizQuestion, type QuizResult, QuizResults, type QuizState, type QuizTest, QuizTimer, type RichTextData, type RichTextRenderer, TestCard, type TestCardCertificateType, type TestCardData, type TestCardMedia, type TestCardMeta, type TestCardProps, type UserAnswer, cn, useQuiz };