@thanh01.pmt/interactive-quiz-kit 1.0.72 → 1.0.74
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/ai.cjs +24 -14
- package/dist/ai.mjs +24 -14
- package/dist/authoring.cjs +89 -87
- package/dist/authoring.d.cts +1 -1
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.mjs +89 -87
- package/dist/react-ui.cjs +89 -87
- package/dist/react-ui.d.cts +1 -1
- package/dist/react-ui.d.ts +1 -1
- package/dist/react-ui.mjs +89 -87
- package/dist/{toaster-DAXYZdrz.d.ts → toaster-B2MPZYhi.d.ts} +2 -1
- package/dist/{toaster-6AR8w2TO.d.cts → toaster-Bvhmyef9.d.cts} +2 -1
- package/package.json +1 -1
package/dist/react-ui.mjs
CHANGED
|
@@ -98203,21 +98203,30 @@ var EditableCombobox = ({
|
|
|
98203
98203
|
disabled = false
|
|
98204
98204
|
}) => {
|
|
98205
98205
|
const [open, setOpen] = React169.useState(false);
|
|
98206
|
-
const [inputValue, setInputValue] = React169.useState(
|
|
98206
|
+
const [inputValue, setInputValue] = React169.useState("");
|
|
98207
98207
|
React169.useEffect(() => {
|
|
98208
|
-
|
|
98209
|
-
|
|
98210
|
-
|
|
98211
|
-
|
|
98212
|
-
|
|
98213
|
-
|
|
98208
|
+
if (value) {
|
|
98209
|
+
const selectedOption = options.find((option) => option.value.toLowerCase() === value.toLowerCase());
|
|
98210
|
+
setInputValue(selectedOption ? selectedOption.label : value);
|
|
98211
|
+
} else {
|
|
98212
|
+
setInputValue("");
|
|
98213
|
+
}
|
|
98214
|
+
}, [value, options, open]);
|
|
98215
|
+
const handleSelect = (selectedValue) => {
|
|
98216
|
+
onChange(selectedValue);
|
|
98214
98217
|
setOpen(false);
|
|
98215
98218
|
};
|
|
98216
|
-
const
|
|
98217
|
-
|
|
98219
|
+
const handleOpenChange = (isOpen) => {
|
|
98220
|
+
if (!isOpen) {
|
|
98221
|
+
const match2 = options.find((option) => option.label.toLowerCase() === inputValue.toLowerCase());
|
|
98222
|
+
if (!match2 && inputValue !== (options.find((opt) => opt.value === value)?.label || value)) {
|
|
98223
|
+
onChange(inputValue);
|
|
98224
|
+
}
|
|
98225
|
+
}
|
|
98226
|
+
setOpen(isOpen);
|
|
98218
98227
|
};
|
|
98219
98228
|
const displayLabel = options.find((option) => option.value.toLowerCase() === value?.toLowerCase())?.label || value;
|
|
98220
|
-
return /* @__PURE__ */ React169.createElement(Popover2, { open, onOpenChange:
|
|
98229
|
+
return /* @__PURE__ */ React169.createElement(Popover2, { open, onOpenChange: handleOpenChange }, /* @__PURE__ */ React169.createElement(PopoverTrigger2, { asChild: true }, /* @__PURE__ */ React169.createElement(
|
|
98221
98230
|
Button,
|
|
98222
98231
|
{
|
|
98223
98232
|
variant: "outline",
|
|
@@ -98233,8 +98242,7 @@ var EditableCombobox = ({
|
|
|
98233
98242
|
{
|
|
98234
98243
|
placeholder: searchPlaceholder,
|
|
98235
98244
|
value: inputValue,
|
|
98236
|
-
onValueChange: setInputValue
|
|
98237
|
-
onBlur: handleBlur
|
|
98245
|
+
onValueChange: setInputValue
|
|
98238
98246
|
}
|
|
98239
98247
|
), /* @__PURE__ */ React169.createElement(CommandList, null, /* @__PURE__ */ React169.createElement(CommandEmpty, null, noResultsMessage), /* @__PURE__ */ React169.createElement(CommandGroup, null, options.map((option) => /* @__PURE__ */ React169.createElement(
|
|
98240
98248
|
CommandItem,
|
|
@@ -101171,6 +101179,10 @@ var supportedQuestionTypesForAI = [
|
|
|
101171
101179
|
{ value: "sequence", label: "Sequence" },
|
|
101172
101180
|
{ value: "matching", label: "Matching" }
|
|
101173
101181
|
];
|
|
101182
|
+
var availableLanguages = [
|
|
101183
|
+
{ value: "English", label: "English" },
|
|
101184
|
+
{ value: "Vietnamese", label: "Ti\u1EBFng Vi\u1EC7t" }
|
|
101185
|
+
];
|
|
101174
101186
|
var AIQuestionGeneratorModal = ({
|
|
101175
101187
|
isOpen,
|
|
101176
101188
|
onClose,
|
|
@@ -101180,51 +101192,65 @@ var AIQuestionGeneratorModal = ({
|
|
|
101180
101192
|
subjects = [],
|
|
101181
101193
|
topics = [],
|
|
101182
101194
|
gradeLevels = [],
|
|
101183
|
-
bloomLevels = []
|
|
101195
|
+
bloomLevels = [],
|
|
101196
|
+
categories = []
|
|
101184
101197
|
}) => {
|
|
101185
|
-
const [
|
|
101198
|
+
const [additionalInfo, setAdditionalInfo] = useState("");
|
|
101186
101199
|
const [isLoading, setIsLoading] = useState(false);
|
|
101187
101200
|
const [error, setError] = useState(null);
|
|
101188
101201
|
const { toast: toast2 } = useToast();
|
|
101189
101202
|
const [subjectCode, setSubjectCode] = useState("");
|
|
101203
|
+
const [categoryCode, setCategoryCode] = useState("");
|
|
101190
101204
|
const [topicCode, setTopicCode] = useState("");
|
|
101191
101205
|
const [gradeBand, setGradeBand] = useState("");
|
|
101192
101206
|
const [bloomLevelCode, setBloomLevelCode] = useState("");
|
|
101193
101207
|
const [selectedQuestionType, setSelectedQuestionType] = useState("multiple_choice");
|
|
101208
|
+
const [selectedLanguage, setSelectedLanguage] = useState(language3);
|
|
101194
101209
|
const [numberOfOptions, setNumberOfOptions] = useState(4);
|
|
101195
|
-
const [minCorrectAnswers, setMinCorrectAnswers] = useState(2);
|
|
101196
|
-
const [maxCorrectAnswers, setMaxCorrectAnswers] = useState(3);
|
|
101197
|
-
const [isCaseSensitive, setIsCaseSensitive] = useState(false);
|
|
101198
|
-
const [numberOfBlanks, setNumberOfBlanks] = useState(2);
|
|
101199
|
-
const [numberOfSequenceItems, setNumberOfSequenceItems] = useState(4);
|
|
101200
|
-
const [numberOfMatchingPairs, setNumberOfMatchingPairs] = useState(4);
|
|
101201
101210
|
const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = useState(false);
|
|
101202
101211
|
const [geminiApiKeyExists, setGeminiApiKeyExists] = useState(false);
|
|
101203
101212
|
const finalQuestionType = questionTypeProp || selectedQuestionType;
|
|
101204
101213
|
useEffect(() => {
|
|
101205
101214
|
if (isOpen) {
|
|
101206
|
-
|
|
101215
|
+
setAdditionalInfo("");
|
|
101207
101216
|
setError(null);
|
|
101208
101217
|
setIsLoading(false);
|
|
101209
101218
|
setSubjectCode("");
|
|
101219
|
+
setCategoryCode("");
|
|
101210
101220
|
setTopicCode("");
|
|
101211
101221
|
setGradeBand("");
|
|
101212
101222
|
setBloomLevelCode("");
|
|
101213
101223
|
setSelectedQuestionType(questionTypeProp || "multiple_choice");
|
|
101224
|
+
setSelectedLanguage(language3);
|
|
101214
101225
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
101215
101226
|
}
|
|
101216
|
-
}, [isOpen, questionTypeProp]);
|
|
101227
|
+
}, [isOpen, questionTypeProp, language3]);
|
|
101228
|
+
const filteredCategories = useMemo(() => {
|
|
101229
|
+
return categories;
|
|
101230
|
+
}, [categories]);
|
|
101217
101231
|
const filteredTopics = useMemo(() => {
|
|
101218
|
-
if (!subjectCode) return [];
|
|
101219
|
-
return topics.filter(
|
|
101220
|
-
|
|
101232
|
+
if (!subjectCode || !categoryCode) return [];
|
|
101233
|
+
return topics.filter(
|
|
101234
|
+
(t4) => t4.subjectCode === subjectCode
|
|
101235
|
+
/* && t.categoryCode === categoryCode */
|
|
101236
|
+
);
|
|
101237
|
+
}, [subjectCode, categoryCode, topics]);
|
|
101238
|
+
const handleSubjectChange = (newSubjectCode) => {
|
|
101239
|
+
setSubjectCode(newSubjectCode);
|
|
101240
|
+
setCategoryCode("");
|
|
101241
|
+
setTopicCode("");
|
|
101242
|
+
};
|
|
101243
|
+
const handleCategoryChange = (newCategoryCode) => {
|
|
101244
|
+
setCategoryCode(newCategoryCode);
|
|
101245
|
+
setTopicCode("");
|
|
101246
|
+
};
|
|
101221
101247
|
const handleApiKeyModalClose = () => {
|
|
101222
101248
|
setIsApiKeyManagerModalOpen(false);
|
|
101223
101249
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
101224
101250
|
};
|
|
101225
101251
|
const handleSubmit = async () => {
|
|
101226
|
-
if (!
|
|
101227
|
-
setError("Please
|
|
101252
|
+
if (!subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode) {
|
|
101253
|
+
setError("Please fill in all required metadata fields: Subject, Category, Topic, Grade Level, and Bloom's Level.");
|
|
101228
101254
|
return;
|
|
101229
101255
|
}
|
|
101230
101256
|
const geminiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
@@ -101238,14 +101264,15 @@ var AIQuestionGeneratorModal = ({
|
|
|
101238
101264
|
setIsLoading(true);
|
|
101239
101265
|
try {
|
|
101240
101266
|
const quizContext = {
|
|
101241
|
-
plannedTopic:
|
|
101267
|
+
plannedTopic: additionalInfo.trim() || topicCode,
|
|
101242
101268
|
originalSubject: subjectCode,
|
|
101243
101269
|
originalTopic: topicCode,
|
|
101270
|
+
originalCategory: categoryCode,
|
|
101244
101271
|
gradeBand,
|
|
101245
101272
|
plannedBloomLevel: bloomLevelCode
|
|
101246
101273
|
};
|
|
101247
101274
|
const baseClientInput = {
|
|
101248
|
-
language:
|
|
101275
|
+
language: selectedLanguage,
|
|
101249
101276
|
difficulty: "Medium",
|
|
101250
101277
|
quizContext
|
|
101251
101278
|
};
|
|
@@ -101258,33 +101285,32 @@ var AIQuestionGeneratorModal = ({
|
|
|
101258
101285
|
generatedResult = await generateMCQQuestion({ ...baseClientInput, numberOfOptions }, geminiKey);
|
|
101259
101286
|
break;
|
|
101260
101287
|
case "multiple_response":
|
|
101261
|
-
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions, minCorrectAnswers, maxCorrectAnswers }, geminiKey);
|
|
101288
|
+
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }, geminiKey);
|
|
101262
101289
|
break;
|
|
101263
101290
|
case "short_answer":
|
|
101264
|
-
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive }, geminiKey);
|
|
101291
|
+
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive: false }, geminiKey);
|
|
101265
101292
|
break;
|
|
101266
101293
|
case "numeric":
|
|
101267
101294
|
generatedResult = await generateNumericQuestion({ ...baseClientInput, allowDecimals: true, tolerance: 0 }, geminiKey);
|
|
101268
101295
|
break;
|
|
101269
101296
|
case "fill_in_the_blanks":
|
|
101270
|
-
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks, isCaseSensitive }, geminiKey);
|
|
101297
|
+
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks: 2, isCaseSensitive: false }, geminiKey);
|
|
101271
101298
|
break;
|
|
101272
101299
|
case "sequence":
|
|
101273
|
-
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems:
|
|
101300
|
+
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, geminiKey);
|
|
101274
101301
|
break;
|
|
101275
101302
|
case "matching":
|
|
101276
|
-
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs:
|
|
101303
|
+
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: 4, shuffleOptions: true }, geminiKey);
|
|
101277
101304
|
break;
|
|
101278
101305
|
default:
|
|
101279
101306
|
throw new Error(`AI generation for '${finalQuestionType}' is not implemented in this flow.`);
|
|
101280
101307
|
}
|
|
101281
|
-
if (generatedResult.error)
|
|
101282
|
-
throw new Error(generatedResult.error);
|
|
101283
|
-
}
|
|
101308
|
+
if (generatedResult.error) throw new Error(generatedResult.error);
|
|
101284
101309
|
if (generatedResult.question) {
|
|
101285
101310
|
const completeQuestion = generatedResult.question;
|
|
101286
101311
|
completeQuestion.subject = subjectCode;
|
|
101287
101312
|
completeQuestion.topic = topicCode;
|
|
101313
|
+
completeQuestion.category = categoryCode;
|
|
101288
101314
|
completeQuestion.gradeBand = gradeBand;
|
|
101289
101315
|
completeQuestion.bloomLevel = bloomLevelCode;
|
|
101290
101316
|
if (completeQuestion.points === void 0) completeQuestion.points = 10;
|
|
@@ -101310,47 +101336,13 @@ var AIQuestionGeneratorModal = ({
|
|
|
101310
101336
|
const comboboxOptions = {
|
|
101311
101337
|
subjects: subjects.map((s4) => ({ value: s4.code, label: s4.name })),
|
|
101312
101338
|
topics: filteredTopics.map((t4) => ({ value: t4.code, label: t4.name })),
|
|
101339
|
+
categories: filteredCategories.map((c4) => ({ value: c4.code, label: c4.name })),
|
|
101313
101340
|
gradeLevels: gradeLevels.map((g) => ({ value: g.code, label: g.name })),
|
|
101314
101341
|
bloomLevels: bloomLevels.map((b2) => ({ value: b2.code, label: b2.name }))
|
|
101315
101342
|
};
|
|
101316
|
-
const renderSpecificParams = () => {
|
|
101317
|
-
switch (finalQuestionType) {
|
|
101318
|
-
case "multiple_choice":
|
|
101319
|
-
case "multiple_response":
|
|
101320
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React169__default.createElement(
|
|
101321
|
-
Input,
|
|
101322
|
-
{
|
|
101323
|
-
id: "ai-num-options",
|
|
101324
|
-
type: "number",
|
|
101325
|
-
value: numberOfOptions,
|
|
101326
|
-
onChange: (e3) => setNumberOfOptions(parseInt(e3.target.value, 10)),
|
|
101327
|
-
min: 2,
|
|
101328
|
-
max: 8
|
|
101329
|
-
}
|
|
101330
|
-
), finalQuestionType === "multiple_response" && /* @__PURE__ */ React169__default.createElement(React169__default.Fragment, null, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-min-correct" }, "Min Correct Answers"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-min-correct", type: "number", value: minCorrectAnswers, onChange: (e3) => setMinCorrectAnswers(parseInt(e3.target.value, 10)), min: 1, max: numberOfOptions }), /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-max-correct" }, "Max Correct Answers"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-max-correct", type: "number", value: maxCorrectAnswers, onChange: (e3) => setMaxCorrectAnswers(parseInt(e3.target.value, 10)), min: minCorrectAnswers, max: numberOfOptions })));
|
|
101331
|
-
case "short_answer":
|
|
101332
|
-
case "fill_in_the_blanks":
|
|
101333
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "flex items-center space-x-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement("input", { type: "checkbox", id: "ai-case-sensitive", checked: isCaseSensitive, onChange: (e3) => setIsCaseSensitive(e3.target.checked), className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" }), /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-case-sensitive" }, "Case Sensitive Answers"), finalQuestionType === "fill_in_the_blanks" && /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-1 ml-4" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-blanks" }, "Number of Blanks (1-5)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-blanks", type: "number", value: numberOfBlanks, onChange: (e3) => setNumberOfBlanks(parseInt(e3.target.value, 10)), min: 1, max: 5 })));
|
|
101334
|
-
case "sequence":
|
|
101335
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-seq-items" }, "Number of Items to Sequence (2-10)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-seq-items", type: "number", value: numberOfSequenceItems, onChange: (e3) => setNumberOfSequenceItems(parseInt(e3.target.value, 10)), min: 2, max: 10 }));
|
|
101336
|
-
case "matching":
|
|
101337
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-match-pairs" }, "Number of Pairs to Match (2-8)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-match-pairs", type: "number", value: numberOfMatchingPairs, onChange: (e3) => setNumberOfMatchingPairs(parseInt(e3.target.value, 10)), min: 2, max: 8 }));
|
|
101338
|
-
default:
|
|
101339
|
-
return null;
|
|
101340
|
-
}
|
|
101341
|
-
};
|
|
101342
101343
|
return /* @__PURE__ */ React169__default.createElement(React169__default.Fragment, null, /* @__PURE__ */ React169__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => {
|
|
101343
101344
|
if (!open) onClose();
|
|
101344
|
-
} }, /* @__PURE__ */ React169__default.createElement(DialogContent2, { className: "sm:max-w-[
|
|
101345
|
-
Textarea,
|
|
101346
|
-
{
|
|
101347
|
-
id: "ai-prompt",
|
|
101348
|
-
value: prompt,
|
|
101349
|
-
onChange: (e3) => setPrompt(e3.target.value),
|
|
101350
|
-
placeholder: "e.g., The process of photosynthesis, The causes of World War II, Basic Algebra Equations",
|
|
101351
|
-
className: "min-h-[100px]"
|
|
101352
|
-
}
|
|
101353
|
-
)), /* @__PURE__ */ React169__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Subject"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: setSubjectCode, placeholder: "Select or type a Subject..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Topic"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select or type a Topic...", disabled: !subjectCode })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Grade Level"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select or type a Grade..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Bloom's Level"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select a Bloom's Level..." }))), renderSpecificParams(), error && /* @__PURE__ */ React169__default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React169__default.createElement(DialogFooter, null, /* @__PURE__ */ React169__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React169__default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !prompt.trim() || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React169__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React169__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
101345
|
+
} }, /* @__PURE__ */ React169__default.createElement(DialogContent2, { className: "sm:max-w-[700px]" }, /* @__PURE__ */ React169__default.createElement(DialogHeader, null, /* @__PURE__ */ React169__default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React169__default.createElement(WandSparkles, { className: "mr-2 h-6 w-6 text-primary" }), " AI Question Generator"), /* @__PURE__ */ React169__default.createElement(DialogDescription2, null, "Provide metadata and optional info to generate a '", finalQuestionType, "' question.")), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-4 py-4 max-h-[60vh] overflow-y-auto px-2" }, /* @__PURE__ */ React169__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, !questionTypeProp && /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Question Type"), /* @__PURE__ */ React169__default.createElement(Select2, { value: selectedQuestionType, onValueChange: (v) => setSelectedQuestionType(v) }, /* @__PURE__ */ React169__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React169__default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__default.createElement(SelectContent2, null, supportedQuestionTypesForAI.map((type) => /* @__PURE__ */ React169__default.createElement(SelectItem2, { key: type.value, value: type.value }, type.label))))), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Language"), /* @__PURE__ */ React169__default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage }, /* @__PURE__ */ React169__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React169__default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__default.createElement(SelectContent2, null, availableLanguages.map((lang) => /* @__PURE__ */ React169__default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label)))))), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-additional-info" }, "Additional Info (Optional)"), /* @__PURE__ */ React169__default.createElement(Textarea, { id: "ai-additional-info", value: additionalInfo, onChange: (e3) => setAdditionalInfo(e3.target.value), placeholder: "Provide extra context, a specific topic, or a detailed prompt for the AI...", className: "min-h-[100px]" })), /* @__PURE__ */ React169__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Subject *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: handleSubjectChange, placeholder: "Select Subject..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Category *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.categories, value: categoryCode, onChange: handleCategoryChange, placeholder: "Select Category...", disabled: !subjectCode })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Topic *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select Topic...", disabled: !categoryCode })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Grade Level *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select Grade..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Bloom's Level *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select Bloom's Level..." }))), finalQuestionType === "multiple_choice" && /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-options", type: "number", value: numberOfOptions, onChange: (e3) => setNumberOfOptions(parseInt(e3.target.value, 10)), min: 2, max: 8 })), error && /* @__PURE__ */ React169__default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React169__default.createElement(DialogFooter, null, /* @__PURE__ */ React169__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React169__default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !geminiApiKeyExists || !subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode }, isLoading ? /* @__PURE__ */ React169__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React169__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
101354
101346
|
};
|
|
101355
101347
|
|
|
101356
101348
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
|
@@ -101851,12 +101843,10 @@ init_react_shim();
|
|
|
101851
101843
|
// src/services/TopicDataService.ts
|
|
101852
101844
|
init_react_shim();
|
|
101853
101845
|
var TopicDataService = class {
|
|
101854
|
-
// ... saveData, mergeData, getData, clearData methods remain the same ...
|
|
101855
101846
|
static saveData(data) {
|
|
101856
101847
|
try {
|
|
101857
101848
|
if (typeof window === "undefined") return;
|
|
101858
|
-
|
|
101859
|
-
localStorage.setItem(this.STORAGE_KEY, serializedData);
|
|
101849
|
+
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(data));
|
|
101860
101850
|
} catch (error) {
|
|
101861
101851
|
console.error("Error saving learning objectives to Local Storage:", error);
|
|
101862
101852
|
}
|
|
@@ -101867,8 +101857,7 @@ var TopicDataService = class {
|
|
|
101867
101857
|
newData.forEach((newLo) => {
|
|
101868
101858
|
loMap.set(newLo.code, newLo);
|
|
101869
101859
|
});
|
|
101870
|
-
|
|
101871
|
-
this.saveData(mergedData);
|
|
101860
|
+
this.saveData(Array.from(loMap.values()));
|
|
101872
101861
|
}
|
|
101873
101862
|
static getData() {
|
|
101874
101863
|
try {
|
|
@@ -101883,7 +101872,7 @@ var TopicDataService = class {
|
|
|
101883
101872
|
}
|
|
101884
101873
|
static clearData() {
|
|
101885
101874
|
try {
|
|
101886
|
-
if (typeof window
|
|
101875
|
+
if (typeof window !== "undefined") return;
|
|
101887
101876
|
localStorage.removeItem(this.STORAGE_KEY);
|
|
101888
101877
|
} catch (error) {
|
|
101889
101878
|
console.error("Error clearing learning objectives from Local Storage:", error);
|
|
@@ -101897,6 +101886,12 @@ var TopicDataService = class {
|
|
|
101897
101886
|
const headerLine = lines.shift();
|
|
101898
101887
|
const headers = headerLine.split(" ").map((h3) => h3.trim());
|
|
101899
101888
|
const headerMap = headers.map((h3) => this.HEADER_MAP[h3] || null);
|
|
101889
|
+
const requiredHeaders = ["LO ID", "LO Name", "Subject", "Subject Code", "Category", "Category Code", "Topic", "Topic Code", "Grade", "Grade Code"];
|
|
101890
|
+
const missingHeaders = requiredHeaders.filter((h3) => !headers.includes(h3));
|
|
101891
|
+
if (missingHeaders.length > 0) {
|
|
101892
|
+
const errorMsg = `Invalid TSV header. Missing required columns: ${missingHeaders.join(", ")}`;
|
|
101893
|
+
return { data: [], errors: [errorMsg] };
|
|
101894
|
+
}
|
|
101900
101895
|
const data = [];
|
|
101901
101896
|
const errors2 = [];
|
|
101902
101897
|
lines.forEach((line, index3) => {
|
|
@@ -101905,29 +101900,30 @@ var TopicDataService = class {
|
|
|
101905
101900
|
headerMap.forEach((propName, i2) => {
|
|
101906
101901
|
if (propName) {
|
|
101907
101902
|
const value = values[i2]?.trim() || "";
|
|
101908
|
-
if (
|
|
101903
|
+
if (["keywords", "stemElements", "bloomLevelsGuideline"].includes(propName)) {
|
|
101909
101904
|
rowObject[propName] = value.split(",").map((s4) => s4.trim()).filter(Boolean);
|
|
101910
101905
|
} else {
|
|
101911
101906
|
rowObject[propName] = value;
|
|
101912
101907
|
}
|
|
101913
101908
|
}
|
|
101914
101909
|
});
|
|
101915
|
-
if (!rowObject.code) {
|
|
101916
|
-
errors2.push(`Line ${index3 + 2}: Missing required
|
|
101910
|
+
if (!rowObject.code || !rowObject.name) {
|
|
101911
|
+
errors2.push(`Line ${index3 + 2}: Missing required values for 'LO ID' or 'LO Name'.`);
|
|
101917
101912
|
return;
|
|
101918
101913
|
}
|
|
101919
|
-
if (!rowObject.name) {
|
|
101920
|
-
rowObject.name = rowObject.code;
|
|
101921
|
-
}
|
|
101922
101914
|
const learningObjective = {
|
|
101923
101915
|
id: generateUniqueId("lo_"),
|
|
101924
101916
|
code: rowObject.code,
|
|
101925
101917
|
name: rowObject.name,
|
|
101926
101918
|
description: rowObject.description,
|
|
101927
101919
|
subject: rowObject.subject || "",
|
|
101920
|
+
subjectCode: rowObject.subjectCode,
|
|
101928
101921
|
category: rowObject.category || "",
|
|
101922
|
+
categoryCode: rowObject.categoryCode,
|
|
101929
101923
|
topic: rowObject.topic || "",
|
|
101924
|
+
topicCode: rowObject.topicCode,
|
|
101930
101925
|
grade: rowObject.grade || "",
|
|
101926
|
+
gradeCode: rowObject.gradeCode,
|
|
101931
101927
|
keywords: rowObject.keywords || [],
|
|
101932
101928
|
stemElements: rowObject.stemElements || [],
|
|
101933
101929
|
bloomLevelsGuideline: rowObject.bloomLevelsGuideline || []
|
|
@@ -101958,17 +101954,23 @@ var TopicDataService = class {
|
|
|
101958
101954
|
}
|
|
101959
101955
|
};
|
|
101960
101956
|
TopicDataService.STORAGE_KEY = "interactive_quiz_kit_learning_objectives";
|
|
101961
|
-
// Define a map for flexible header mapping
|
|
101962
101957
|
TopicDataService.HEADER_MAP = {
|
|
101963
101958
|
"LO ID": "code",
|
|
101964
101959
|
"LO Name": "name",
|
|
101965
|
-
// Ready for future addition
|
|
101966
101960
|
"LO Description": "description",
|
|
101967
101961
|
"Subject": "subject",
|
|
101962
|
+
"Subject Code": "subjectCode",
|
|
101963
|
+
// New
|
|
101968
101964
|
"Category": "category",
|
|
101965
|
+
"Category Code": "categoryCode",
|
|
101966
|
+
// New
|
|
101969
101967
|
"Topic": "topic",
|
|
101968
|
+
"Topic Code": "topicCode",
|
|
101969
|
+
// New
|
|
101970
101970
|
"Keywords": "keywords",
|
|
101971
101971
|
"Grade": "grade",
|
|
101972
|
+
"Grade Code": "gradeCode",
|
|
101973
|
+
// New
|
|
101972
101974
|
"STEM Element(s)": "stemElements",
|
|
101973
101975
|
"Bloom\u2019s Level(s) Guideline": "bloomLevelsGuideline"
|
|
101974
101976
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import { s as QuizConfig, g as QuizQuestion, Q as QuestionTypeStrings, r as QuizSettings } from './quiz-config-CwaP-pBs.js';
|
|
4
|
-
import { Subject, Topic, GradeLevel, BloomLevelType, QuestionInBank, QuestionFilters as QuestionFilters$1,
|
|
4
|
+
import { Subject, Topic, GradeLevel, BloomLevelType, Category, QuestionInBank, QuestionFilters as QuestionFilters$1, QuestionTypeType, LearningObjective, Context, Approach } from './index.js';
|
|
5
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
6
6
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
7
7
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -23,6 +23,7 @@ interface AIQuestionGeneratorModalProps {
|
|
|
23
23
|
topics?: Topic[];
|
|
24
24
|
gradeLevels?: GradeLevel[];
|
|
25
25
|
bloomLevels?: BloomLevelType[];
|
|
26
|
+
categories?: Category[];
|
|
26
27
|
}
|
|
27
28
|
declare const AIQuestionGeneratorModal: React__default.FC<AIQuestionGeneratorModalProps>;
|
|
28
29
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import { s as QuizConfig, g as QuizQuestion, Q as QuestionTypeStrings, r as QuizSettings } from './quiz-config-CwaP-pBs.cjs';
|
|
4
|
-
import { Subject, Topic, GradeLevel, BloomLevelType, QuestionInBank, QuestionFilters as QuestionFilters$1,
|
|
4
|
+
import { Subject, Topic, GradeLevel, BloomLevelType, Category, QuestionInBank, QuestionFilters as QuestionFilters$1, QuestionTypeType, LearningObjective, Context, Approach } from './index.cjs';
|
|
5
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
6
6
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
7
7
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -23,6 +23,7 @@ interface AIQuestionGeneratorModalProps {
|
|
|
23
23
|
topics?: Topic[];
|
|
24
24
|
gradeLevels?: GradeLevel[];
|
|
25
25
|
bloomLevels?: BloomLevelType[];
|
|
26
|
+
categories?: Category[];
|
|
26
27
|
}
|
|
27
28
|
declare const AIQuestionGeneratorModal: React__default.FC<AIQuestionGeneratorModalProps>;
|
|
28
29
|
|
package/package.json
CHANGED