@thanh01.pmt/interactive-quiz-kit 1.0.75 → 1.0.76

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/react-ui.cjs CHANGED
@@ -102367,7 +102367,7 @@ var contextOptions = [
102367
102367
  ];
102368
102368
 
102369
102369
  // src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
102370
- var availableQuestionTypesForFullQuiz = [
102370
+ var ALL_AVAILABLE_QUESTION_TYPES = [
102371
102371
  { value: "true_false", label: "True/False" },
102372
102372
  { value: "multiple_choice", label: "Multiple Choice" },
102373
102373
  { value: "multiple_response", label: "Multiple Response" },
@@ -102382,8 +102382,11 @@ var AIFullQuizGeneratorModal = ({
102382
102382
  isOpen,
102383
102383
  onClose,
102384
102384
  onQuizGenerated,
102385
- language: language3
102386
- // <-- NHẬN PROP
102385
+ language: language3,
102386
+ maxQuestions = 100,
102387
+ // Default value
102388
+ allowedQuestionTypes = ALL_AVAILABLE_QUESTION_TYPES.map((qt) => qt.value)
102389
+ // Default value
102387
102390
  }) => {
102388
102391
  const [totalQuestions, setTotalQuestions] = React169.useState(10);
102389
102392
  const [topics, setTopics] = React169.useState([{ id: generateUniqueId("topic_"), topic: "", ratio: 100 }]);
@@ -102394,9 +102397,7 @@ var AIFullQuizGeneratorModal = ({
102394
102397
  ]);
102395
102398
  const [selectedContextIds, setSelectedContextIds] = React169.useState([]);
102396
102399
  const [customContextInput, setCustomContextInput] = React169.useState("");
102397
- const [selectedQuestionTypes, setSelectedQuestionTypes] = React169.useState(
102398
- availableQuestionTypesForFullQuiz.map((qt) => qt.value)
102399
- );
102400
+ const [selectedQuestionTypes, setSelectedQuestionTypes] = React169.useState([]);
102400
102401
  const [authorizeAISkipReview, setAuthorizeAISkipReview] = React169.useState(false);
102401
102402
  const [isLoading, setIsLoading] = React169.useState(false);
102402
102403
  const [error, setError] = React169.useState(null);
@@ -102405,6 +102406,9 @@ var AIFullQuizGeneratorModal = ({
102405
102406
  const { toast: toast2 } = useToast();
102406
102407
  const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = React169.useState(false);
102407
102408
  const [geminiApiKeyExists, setGeminiApiKeyExists] = React169.useState(false);
102409
+ const availableQuestionTypesForFullQuiz = React169.useMemo(() => {
102410
+ return ALL_AVAILABLE_QUESTION_TYPES.filter((qt) => allowedQuestionTypes.includes(qt.value));
102411
+ }, [allowedQuestionTypes]);
102408
102412
  React169.useEffect(() => {
102409
102413
  if (isOpen) {
102410
102414
  setTotalQuestions(10);
@@ -102424,7 +102428,7 @@ var AIFullQuizGeneratorModal = ({
102424
102428
  setAiGeneratedPlan(null);
102425
102429
  setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
102426
102430
  }
102427
- }, [isOpen]);
102431
+ }, [isOpen, availableQuestionTypesForFullQuiz]);
102428
102432
  const handleApiKeyModalClose = () => {
102429
102433
  setIsApiKeyManagerModalOpen(false);
102430
102434
  setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
@@ -102432,7 +102436,7 @@ var AIFullQuizGeneratorModal = ({
102432
102436
  const handleTotalQuestionsChange = (e3) => {
102433
102437
  let num = parseInt(e3.target.value, 10);
102434
102438
  if (isNaN(num) || num < 1) num = 1;
102435
- if (num > 100) num = 100;
102439
+ if (num > maxQuestions) num = maxQuestions;
102436
102440
  setTotalQuestions(num);
102437
102441
  };
102438
102442
  const handleTopicChange = (id3, field, value) => {
@@ -102462,8 +102466,8 @@ var AIFullQuizGeneratorModal = ({
102462
102466
  setError("Gemini API Key is required for AI features. Please set it first.");
102463
102467
  return false;
102464
102468
  }
102465
- if (totalQuestions <= 0 || totalQuestions > 100) {
102466
- setError("Total questions must be between 1 and 100.");
102469
+ if (totalQuestions <= 0 || totalQuestions > maxQuestions) {
102470
+ setError(`Total questions must be between 1 and ${maxQuestions}.`);
102467
102471
  return false;
102468
102472
  }
102469
102473
  if (topics.some((t4) => !t4.topic.trim())) {
@@ -102502,7 +102506,6 @@ var AIFullQuizGeneratorModal = ({
102502
102506
  const stage2Input = {
102503
102507
  quizPlan: plan,
102504
102508
  language: language3,
102505
- // <-- SỬ DỤNG PROP
102506
102509
  imageContexts: []
102507
102510
  };
102508
102511
  const stage2Output = await generateQuestionsFromQuizPlan(stage2Input, apiKey);
@@ -102553,7 +102556,6 @@ var AIFullQuizGeneratorModal = ({
102553
102556
  try {
102554
102557
  const planInput = {
102555
102558
  language: language3,
102556
- // <-- SỬ DỤNG PROP
102557
102559
  totalQuestions,
102558
102560
  numCodingQuestions: 0,
102559
102561
  topics: topics.map((t4) => ({ topic: t4.topic, ratio: t4.ratio })),
@@ -102617,103 +102619,9 @@ var AIFullQuizGeneratorModal = ({
102617
102619
  };
102618
102620
  const renderContent3 = () => {
102619
102621
  if (currentStage === "review") {
102620
- return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 py-4" }, /* @__PURE__ */ React169__namespace.default.createElement("h3", { className: "text-lg font-Medium mb-2 text-primary flex items-center" }, /* @__PURE__ */ React169__namespace.default.createElement(Eye, { className: "mr-2 h-5 w-5" }), " Review & Adjust AI Generated Quiz Plan"), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "The AI has proposed the following plan. You can change question types, reorder, or remove questions before final generation. Note: 'Drag and Drop' type questions in the plan will be created as placeholders and require manual authoring of items/zones/answers."), aiGeneratedPlan && aiGeneratedPlan.length > 0 ? /* @__PURE__ */ React169__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(60vh - 120px)] pr-3" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-3" }, aiGeneratedPlan.map((plannedQ, index3) => /* @__PURE__ */ React169__namespace.default.createElement(Card, { key: `planned-${index3}-${plannedQ.plannedTopic.replace(/\s/g, "")}`, className: "p-3" }, /* @__PURE__ */ React169__namespace.default.createElement(CardContent, { className: "p-0 space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "font-semibold text-sm" }, "Q", index3 + 1, ": ", plannedQ.plannedTopic), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "up"), disabled: index3 === 0 }, /* @__PURE__ */ React169__namespace.default.createElement(ArrowUp, { className: "h-4 w-4" })), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "down"), disabled: index3 === aiGeneratedPlan.length - 1 }, /* @__PURE__ */ React169__namespace.default.createElement(ArrowDown, { className: "h-4 w-4" })), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7 text-destructive", onClick: () => handleRemovePlannedQuestion(index3) }, /* @__PURE__ */ React169__namespace.default.createElement(Trash2, { className: "h-4 w-4" })))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-3 items-end" }, /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `review-qtype-${index3}`, className: "text-xs" }, "Question Type"), /* @__PURE__ */ React169__namespace.default.createElement(
102621
- Select2,
102622
- {
102623
- value: plannedQ.plannedQuestionType,
102624
- onValueChange: (value) => handleChangePlannedQuestionType(index3, value)
102625
- },
102626
- /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: `review-qtype-${index3}`, className: "h-9 text-xs" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, null)),
102627
- /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: qType.value, value: qType.value, className: "text-xs" }, qType.label)))
102628
- )), /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "text-xs block" }, "Bloom Level"), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-xs p-2 h-9 border rounded-md bg-secondary/50 flex items-center capitalize" }, plannedQ.plannedBloomLevel)))))))) : /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-muted-foreground" }, "No quiz plan generated or plan is empty."), error && /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error));
102622
+ return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 py-4" }, /* @__PURE__ */ React169__namespace.default.createElement("h3", { className: "text-lg font-Medium mb-2 text-primary flex items-center" }, /* @__PURE__ */ React169__namespace.default.createElement(Eye, { className: "mr-2 h-5 w-5" }), " Review & Adjust AI Generated Quiz Plan"), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "The AI has proposed the following plan. You can change question types, reorder, or remove questions before final generation. Note: 'Drag and Drop' type questions in the plan will be created as placeholders and require manual authoring of items/zones/answers."), aiGeneratedPlan && aiGeneratedPlan.length > 0 ? /* @__PURE__ */ React169__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(60vh - 120px)] pr-3" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-3" }, aiGeneratedPlan.map((plannedQ, index3) => /* @__PURE__ */ React169__namespace.default.createElement(Card, { key: `planned-${index3}-${plannedQ.plannedTopic.replace(/\s/g, "")}`, className: "p-3" }, /* @__PURE__ */ React169__namespace.default.createElement(CardContent, { className: "p-0 space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "font-semibold text-sm" }, "Q", index3 + 1, ": ", plannedQ.plannedTopic), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "up"), disabled: index3 === 0 }, /* @__PURE__ */ React169__namespace.default.createElement(ArrowUp, { className: "h-4 w-4" })), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "down"), disabled: index3 === aiGeneratedPlan.length - 1 }, /* @__PURE__ */ React169__namespace.default.createElement(ArrowDown, { className: "h-4 w-4" })), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7 text-destructive", onClick: () => handleRemovePlannedQuestion(index3) }, /* @__PURE__ */ React169__namespace.default.createElement(Trash2, { className: "h-4 w-4" })))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-3 items-end" }, /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `review-qtype-${index3}`, className: "text-xs" }, "Question Type"), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: plannedQ.plannedQuestionType, onValueChange: (value) => handleChangePlannedQuestionType(index3, value) }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: `review-qtype-${index3}`, className: "h-9 text-xs" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: qType.value, value: qType.value, className: "text-xs" }, qType.label))))), /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "text-xs block" }, "Bloom Level"), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-xs p-2 h-9 border rounded-md bg-secondary/50 flex items-center capitalize" }, plannedQ.plannedBloomLevel)))))))) : /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-muted-foreground" }, "No quiz plan generated or plan is empty."), error && /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error));
102629
102623
  }
102630
- return /* @__PURE__ */ React169__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(70vh - 100px)] pl-4 pr-3 py-1" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 py-1 px-2" }, !geminiApiKeyExists && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "p-3 mb-4 border border-amber-500 bg-amber-50 rounded-md text-amber-700" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex items-start" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "h-5 w-5 mr-2 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "font-semibold" }, "Gemini API Key Required"), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-xs" }, "To use AI quiz generation, please set your Google Gemini API Key."), /* @__PURE__ */ React169__namespace.default.createElement(
102631
- Button,
102632
- {
102633
- variant: "link",
102634
- className: "p-0 h-auto text-xs text-amber-700 hover:text-amber-800 mt-1",
102635
- onClick: () => setIsApiKeyManagerModalOpen(true)
102636
- },
102637
- /* @__PURE__ */ React169__namespace.default.createElement(Settings, { className: "mr-1 h-3 w-3" }),
102638
- " Set API Key Now"
102639
- )))), /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "total-questions" }, "Total Number of Questions (1-100)"), /* @__PURE__ */ React169__namespace.default.createElement(
102640
- Input,
102641
- {
102642
- id: "total-questions",
102643
- type: "number",
102644
- value: totalQuestions,
102645
- onChange: handleTotalQuestionsChange,
102646
- min: "1",
102647
- max: "100"
102648
- }
102649
- )), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Topic Distribution"), topics.map((topicItem, index3) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: topicItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React169__namespace.default.createElement(
102650
- Input,
102651
- {
102652
- type: "text",
102653
- placeholder: `Topic ${index3 + 1}`,
102654
- value: topicItem.topic,
102655
- onChange: (e3) => handleTopicChange(topicItem.id, "topic", e3.target.value),
102656
- className: "flex-grow"
102657
- }
102658
- ), /* @__PURE__ */ React169__namespace.default.createElement(
102659
- Input,
102660
- {
102661
- type: "number",
102662
- placeholder: "Ratio %",
102663
- value: topicItem.ratio,
102664
- onChange: (e3) => handleTopicChange(topicItem.id, "ratio", parseInt(e3.target.value, 10) || 0),
102665
- className: "w-24",
102666
- min: "0",
102667
- max: "100"
102668
- }
102669
- ), /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeTopic(topicItem.id), disabled: topics.length <= 1 }, /* @__PURE__ */ React169__namespace.default.createElement(Trash2, { className: "h-4 w-4 text-destructive" })))), /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "outline", size: "sm", onClick: addTopic }, /* @__PURE__ */ React169__namespace.default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Bloom Level Distribution"), bloomLevels.map((bloomItem) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: bloomItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "w-32 capitalize flex-shrink-0" }, bloomItem.level), /* @__PURE__ */ React169__namespace.default.createElement(
102670
- Input,
102671
- {
102672
- type: "number",
102673
- placeholder: "Ratio %",
102674
- value: bloomItem.ratio,
102675
- onChange: (e3) => handleBloomRatioChange(bloomItem.id, parseInt(e3.target.value, 10) || 0),
102676
- className: "w-24",
102677
- min: "0",
102678
- max: "100"
102679
- }
102680
- )))), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Relevant Contexts (Optional, Select Multiple)"), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, contextOptions.filter((opt) => opt.contextId !== "__none__" && opt.contextId !== "__custom__").map((opt) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: opt.contextId, className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(
102681
- Checkbox2,
102682
- {
102683
- id: `ctx-full-${opt.contextId}`,
102684
- checked: selectedContextIds.includes(opt.contextId),
102685
- onCheckedChange: () => handleContextToggle(opt.contextId)
102686
- }
102687
- ), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `ctx-full-${opt.contextId}`, className: "text-xs font-normal cursor-pointer" }, opt.contextDescription, " (", opt.shortContextId, ")")))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(
102688
- Checkbox2,
102689
- {
102690
- id: `ctx-full-__custom__`,
102691
- checked: selectedContextIds.includes("__custom__"),
102692
- onCheckedChange: () => handleContextToggle("__custom__")
102693
- }
102694
- ), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `ctx-full-__custom__`, className: "text-xs font-normal cursor-pointer ml-2" }, "Other (Custom Input)")), selectedContextIds.includes("__custom__") && /* @__PURE__ */ React169__namespace.default.createElement(
102695
- Textarea,
102696
- {
102697
- value: customContextInput,
102698
- onChange: (e3) => setCustomContextInput(e3.target.value),
102699
- placeholder: "Enter your specific custom context here...",
102700
- className: "min-h-[60px] mt-2 text-sm"
102701
- }
102702
- )), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Question Types to Use (Select Multiple)"), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: qType.value, className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(
102703
- Checkbox2,
102704
- {
102705
- id: `qtype-full-${qType.value}`,
102706
- checked: selectedQuestionTypes.includes(qType.value),
102707
- onCheckedChange: () => handleQuestionTypeToggle(qType.value)
102708
- }
102709
- ), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `qtype-full-${qType.value}`, className: "text-xs font-normal cursor-pointer" }, qType.label))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex items-center space-x-2 pt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(
102710
- Checkbox2,
102711
- {
102712
- id: "authorize-ai-skip-review",
102713
- checked: authorizeAISkipReview,
102714
- onCheckedChange: (checked) => setAuthorizeAISkipReview(!!checked)
102715
- }
102716
- ), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "authorize-ai-skip-review", className: "text-sm font-normal" }, "Authorize AI (Skip Review & Generate Directly)")), error && /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)));
102624
+ return /* @__PURE__ */ React169__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(70vh - 100px)] pl-4 pr-3 py-1" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 py-1 px-2" }, !geminiApiKeyExists && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "p-3 mb-4 border border-amber-500 bg-amber-50 rounded-md text-amber-700" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex items-start" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "h-5 w-5 mr-2 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "font-semibold" }, "Gemini API Key Required"), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-xs" }, "To use AI quiz generation, please set your Google Gemini API Key."), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "link", className: "p-0 h-auto text-xs text-amber-700 hover:text-amber-800 mt-1", onClick: () => setIsApiKeyManagerModalOpen(true) }, /* @__PURE__ */ React169__namespace.default.createElement(Settings, { className: "mr-1 h-3 w-3" }), " Set API Key Now")))), /* @__PURE__ */ React169__namespace.default.createElement("div", null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "total-questions" }, "Total Number of Questions (1-", maxQuestions, ")"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "total-questions", type: "number", value: totalQuestions, onChange: handleTotalQuestionsChange, min: "1", max: maxQuestions })), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Topic Distribution"), topics.map((topicItem, index3) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: topicItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Input, { type: "text", placeholder: `Topic ${index3 + 1}`, value: topicItem.topic, onChange: (e3) => handleTopicChange(topicItem.id, "topic", e3.target.value), className: "flex-grow" }), /* @__PURE__ */ React169__namespace.default.createElement(Input, { type: "number", placeholder: "Ratio %", value: topicItem.ratio, onChange: (e3) => handleTopicChange(topicItem.id, "ratio", parseInt(e3.target.value, 10) || 0), className: "w-24", min: "0", max: "100" }), /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeTopic(topicItem.id), disabled: topics.length <= 1 }, /* @__PURE__ */ React169__namespace.default.createElement(Trash2, { className: "h-4 w-4 text-destructive" })))), /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "outline", size: "sm", onClick: addTopic }, /* @__PURE__ */ React169__namespace.default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Bloom Level Distribution"), bloomLevels.map((bloomItem) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: bloomItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "w-32 capitalize flex-shrink-0" }, bloomItem.level), /* @__PURE__ */ React169__namespace.default.createElement(Input, { type: "number", placeholder: "Ratio %", value: bloomItem.ratio, onChange: (e3) => handleBloomRatioChange(bloomItem.id, parseInt(e3.target.value, 10) || 0), className: "w-24", min: "0", max: "100" })))), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Relevant Contexts (Optional, Select Multiple)"), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, contextOptions.filter((opt) => opt.contextId !== "__none__" && opt.contextId !== "__custom__").map((opt) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: opt.contextId, className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: `ctx-full-${opt.contextId}`, checked: selectedContextIds.includes(opt.contextId), onCheckedChange: () => handleContextToggle(opt.contextId) }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `ctx-full-${opt.contextId}`, className: "text-xs font-normal cursor-pointer" }, opt.contextDescription, " (", opt.shortContextId, ")"))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: `ctx-full-__custom__`, checked: selectedContextIds.includes("__custom__"), onCheckedChange: () => handleContextToggle("__custom__") }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `ctx-full-__custom__`, className: "text-xs font-normal cursor-pointer ml-2" }, "Other (Custom Input)")), selectedContextIds.includes("__custom__") && /* @__PURE__ */ React169__namespace.default.createElement(Textarea, { value: customContextInput, onChange: (e3) => setCustomContextInput(e3.target.value), placeholder: "Enter your specific custom context here...", className: "min-h-[60px] mt-2 text-sm" }))), /* @__PURE__ */ React169__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React169__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Question Types to Use (Select Multiple)"), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: qType.value, className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: `qtype-full-${qType.value}`, checked: selectedQuestionTypes.includes(qType.value), onCheckedChange: () => handleQuestionTypeToggle(qType.value) }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `qtype-full-${qType.value}`, className: "text-xs font-normal cursor-pointer" }, qType.label))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex items-center space-x-2 pt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: "authorize-ai-skip-review", checked: authorizeAISkipReview, onCheckedChange: (checked) => setAuthorizeAISkipReview(!!checked) }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "authorize-ai-skip-review", className: "text-sm font-normal" }, "Authorize AI (Skip Review & Generate Directly)")), error && /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)));
102717
102625
  };
102718
102626
  return /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => !open && onClose() }, /* @__PURE__ */ React169__namespace.default.createElement(DialogContent2, { className: "sm:max-w-[650px] md:max-w-[750px] lg:max-w-[800px] max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React169__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React169__namespace.default.createElement(FileText, { className: "mr-2 h-6 w-6 text-primary" }), " Generate Full Quiz with AI"), /* @__PURE__ */ React169__namespace.default.createElement(DialogDescription2, null, currentStage === "input" && "Define parameters for AI to generate a quiz plan.", currentStage === "review" && "Review and adjust the AI-generated quiz plan before generating questions.", currentStage === "generating" && "AI is working... Please wait.")), renderContent3(), /* @__PURE__ */ React169__namespace.default.createElement(DialogFooter, { className: "pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "outline", onClick: onClose }, "Cancel")), currentStage === "input" && /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", onClick: handleSubmitPlanGeneration, disabled: isLoading || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), authorizeAISkipReview ? "Generate Quiz Directly" : "Generate Quiz Plan"), currentStage === "review" && !isLoading && /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", onClick: handleGenerateQuestionsFromReviewedPlan, disabled: isLoading || !aiGeneratedPlan || aiGeneratedPlan.length === 0 || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Questions from Plan"), currentStage === "generating" && isLoading && /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", disabled: true }, /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Generating... Please Wait")))), /* @__PURE__ */ React169__namespace.default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
102719
102627
  };
@@ -138319,58 +138227,74 @@ var AVAILABLE_LANGUAGES = [
138319
138227
  { value: "Vietnamese", label: "Ti\u1EBFng Vi\u1EC7t" },
138320
138228
  { value: "English", label: "English" }
138321
138229
  ];
138230
+ var ALL_QUESTION_TYPE_LABELS = {
138231
+ multiple_choice: "Multiple Choice",
138232
+ multiple_response: "Multiple Response",
138233
+ true_false: "True/False",
138234
+ short_answer: "Short Answer",
138235
+ numeric: "Numeric",
138236
+ fill_in_the_blanks: "Fill in the Blanks",
138237
+ sequence: "Sequence",
138238
+ matching: "Matching",
138239
+ drag_and_drop: "Drag & Drop",
138240
+ hotspot: "Hotspot",
138241
+ blockly_programming: "Blockly",
138242
+ scratch_programming: "Scratch",
138243
+ coding: "Coding"
138244
+ };
138322
138245
  var PracticeSetup = ({
138323
138246
  onStartPractice,
138324
138247
  isGenerating,
138325
138248
  initialLOs,
138326
138249
  initialDifficulty,
138327
- initialLanguage
138250
+ initialLanguage,
138251
+ maxQuestions = 20,
138252
+ // Default max questions
138253
+ allowedQuestionTypes = ["true_false", "multiple_choice", "multiple_response"]
138254
+ // Default allowed types
138328
138255
  }) => {
138329
138256
  const { t: t4 } = useTranslation();
138330
138257
  const [subjects, setSubjects] = React169.useState([]);
138331
- const [categories, setCategories] = React169.useState([]);
138332
- const [topics, setTopics] = React169.useState([]);
138258
+ const [categoriesBySubject, setCategoriesBySubject] = React169.useState({});
138259
+ const [topicsByCategory, setTopicsByCategory] = React169.useState({});
138333
138260
  const [hasData, setHasData] = React169.useState(false);
138334
138261
  const [selectedSubject, setSelectedSubject] = React169.useState("");
138335
- const [selectedCategory, setSelectedCategory] = React169.useState("");
138336
138262
  const [selectedTopics, setSelectedTopics] = React169.useState(/* @__PURE__ */ new Set());
138337
138263
  const [selectedLanguage, setSelectedLanguage] = React169.useState(AVAILABLE_LANGUAGES[0].value);
138338
138264
  const [selectedDifficulty, setSelectedDifficulty] = React169.useState("");
138339
- const [includeCodingQuestions, setIncludeCodingQuestions] = React169.useState(false);
138340
- const [numCodingQuestions, setNumCodingQuestions] = React169.useState(1);
138265
+ const [numQuestions, setNumQuestions] = React169.useState(10);
138266
+ const [selectedQuestionTypes, setSelectedQuestionTypes] = React169.useState(new Set(allowedQuestionTypes));
138341
138267
  React169.useEffect(() => {
138342
- const allSubjects = TopicDataService.getSubjects();
138343
- setHasData(allSubjects.length > 0);
138344
- setSubjects(allSubjects);
138268
+ const allLOs = TopicDataService.getData();
138269
+ if (allLOs.length > 0) {
138270
+ setHasData(true);
138271
+ const uniqueSubjects = [...new Set(allLOs.map((lo) => lo.subject))].sort();
138272
+ setSubjects(uniqueSubjects);
138273
+ const catsBySub = {};
138274
+ uniqueSubjects.forEach((sub) => {
138275
+ catsBySub[sub] = [...new Set(allLOs.filter((lo) => lo.subject === sub).map((lo) => lo.category))].sort();
138276
+ });
138277
+ setCategoriesBySubject(catsBySub);
138278
+ const topsByCat = {};
138279
+ allLOs.forEach((lo) => {
138280
+ if (!topsByCat[lo.category]) {
138281
+ topsByCat[lo.category] = [];
138282
+ }
138283
+ topsByCat[lo.category].push(lo.topic);
138284
+ });
138285
+ Object.keys(topsByCat).forEach((cat) => {
138286
+ topsByCat[cat] = [...new Set(topsByCat[cat])].sort();
138287
+ });
138288
+ setTopicsByCategory(topsByCat);
138289
+ }
138345
138290
  if (initialLOs && initialLOs.length > 0) {
138346
138291
  const firstLO = initialLOs[0];
138347
138292
  setSelectedSubject(firstLO.subject);
138348
- setSelectedCategory(firstLO.category);
138349
138293
  setSelectedTopics(new Set(initialLOs.map((lo) => lo.topic)));
138350
138294
  setSelectedDifficulty(initialDifficulty || "Medium");
138351
138295
  setSelectedLanguage(initialLanguage || AVAILABLE_LANGUAGES[0].value);
138352
138296
  }
138353
138297
  }, [initialLOs, initialDifficulty, initialLanguage]);
138354
- React169.useEffect(() => {
138355
- if (selectedSubject) {
138356
- const filteredCategories = TopicDataService.getCategoriesBySubject(selectedSubject);
138357
- setCategories(filteredCategories);
138358
- if (!initialLOs) {
138359
- setSelectedCategory("");
138360
- setTopics([]);
138361
- setSelectedTopics(/* @__PURE__ */ new Set());
138362
- }
138363
- }
138364
- }, [selectedSubject, initialLOs]);
138365
- React169.useEffect(() => {
138366
- if (selectedCategory) {
138367
- const filteredTopics = TopicDataService.getTopicsByCategory(selectedCategory);
138368
- setTopics(filteredTopics);
138369
- if (!initialLOs) {
138370
- setSelectedTopics(/* @__PURE__ */ new Set());
138371
- }
138372
- }
138373
- }, [selectedCategory, initialLOs]);
138374
138298
  const handleTopicToggle = React169.useCallback((topic, checked) => {
138375
138299
  setSelectedTopics((prevSelected) => {
138376
138300
  const newSelected = new Set(prevSelected);
@@ -138379,37 +138303,36 @@ var PracticeSetup = ({
138379
138303
  return newSelected;
138380
138304
  });
138381
138305
  }, []);
138306
+ const handleQuestionTypeToggle = React169.useCallback((type, checked) => {
138307
+ setSelectedQuestionTypes((prev) => {
138308
+ const newSet = new Set(prev);
138309
+ if (checked) newSet.add(type);
138310
+ else newSet.delete(type);
138311
+ return newSet;
138312
+ });
138313
+ }, []);
138382
138314
  const handleStartClick = React169.useCallback(() => {
138383
- if (selectedTopics.size > 0 && selectedDifficulty && selectedLanguage) {
138315
+ if (selectedTopics.size > 0 && selectedDifficulty && selectedLanguage && numQuestions > 0 && selectedQuestionTypes.size > 0) {
138384
138316
  const selectedLOs = TopicDataService.getLearningObjectivesByTopics(Array.from(selectedTopics));
138385
- onStartPractice(selectedLOs, selectedDifficulty, selectedLanguage, includeCodingQuestions, numCodingQuestions);
138317
+ onStartPractice(selectedLOs, selectedDifficulty, selectedLanguage, numQuestions, Array.from(selectedQuestionTypes));
138386
138318
  }
138387
- }, [onStartPractice, selectedDifficulty, selectedLanguage, selectedTopics, includeCodingQuestions, numCodingQuestions]);
138388
- const handleNumCodingChange = (e3) => {
138319
+ }, [onStartPractice, selectedDifficulty, selectedLanguage, selectedTopics, numQuestions, selectedQuestionTypes]);
138320
+ const handleNumQuestionsChange = (e3) => {
138389
138321
  let value = parseInt(e3.target.value, 10);
138390
138322
  if (isNaN(value) || value < 1) value = 1;
138391
- if (value > 3) value = 3;
138392
- setNumCodingQuestions(value);
138323
+ if (value > maxQuestions) value = maxQuestions;
138324
+ setNumQuestions(value);
138393
138325
  };
138394
138326
  const isReadyToStart = React169.useMemo(() => {
138395
- return selectedTopics.size > 0 && !!selectedDifficulty && !!selectedLanguage && !isGenerating;
138396
- }, [selectedTopics, selectedDifficulty, selectedLanguage, isGenerating]);
138327
+ return selectedTopics.size > 0 && !!selectedDifficulty && !!selectedLanguage && numQuestions > 0 && selectedQuestionTypes.size > 0 && !isGenerating;
138328
+ }, [selectedTopics, selectedDifficulty, selectedLanguage, numQuestions, selectedQuestionTypes, isGenerating]);
138397
138329
  if (!hasData) {
138398
138330
  return /* @__PURE__ */ React169__namespace.default.createElement(Card, { className: "w-full max-w-2xl mx-auto" }, /* @__PURE__ */ React169__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(CardTitle, { className: "flex items-center text-2xl font-headline" }, /* @__PURE__ */ React169__namespace.default.createElement(BrainCircuit, { className: "mr-3 h-6 w-6 text-primary" }), t4("practiceFlow.setup.title"))), /* @__PURE__ */ React169__namespace.default.createElement(CardContent, null, /* @__PURE__ */ React169__namespace.default.createElement(Alert, { variant: "destructive" }, /* @__PURE__ */ React169__namespace.default.createElement(CircleAlert, { className: "h-4 w-4" }), /* @__PURE__ */ React169__namespace.default.createElement(AlertTitle, null, "No Learning Objective Data Found"), /* @__PURE__ */ React169__namespace.default.createElement(AlertDescription, null, 'Please import your curriculum data from a TSV file in the "Manage Topics" section before you can start a practice session.'))));
138399
138331
  }
138400
- return /* @__PURE__ */ React169__namespace.default.createElement(Card, { className: "w-full max-w-2xl mx-auto" }, /* @__PURE__ */ React169__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(CardTitle, { className: "flex items-center text-2xl font-headline" }, /* @__PURE__ */ React169__namespace.default.createElement(BrainCircuit, { className: "mr-3 h-6 w-6 text-primary" }), t4("practiceFlow.setup.title")), /* @__PURE__ */ React169__namespace.default.createElement(CardDescription, null, t4("practiceFlow.setup.description"))), /* @__PURE__ */ React169__namespace.default.createElement(CardContent, { className: "space-y-6" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "subject-select", className: "font-semibold" }, t4("practiceFlow.setup.step1_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedSubject, onValueChange: setSelectedSubject, disabled: isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "subject-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step1_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, subjects.map((subject) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: subject, value: subject }, subject))))), selectedSubject && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 animate-in fade-in duration-300" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "category-select", className: "font-semibold" }, t4("practiceFlow.setup.step2_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedCategory, onValueChange: setSelectedCategory, disabled: !selectedSubject || isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "category-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step2_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, categories.map((category) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: category, value: category }, category))))), selectedCategory && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 animate-in fade-in duration-500" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "font-semibold" }, t4("practiceFlow.setup.step3_title")), /* @__PURE__ */ React169__namespace.default.createElement(ScrollArea2, { className: "h-48 w-full rounded-md border p-4" }, topics.length > 0 ? /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, topics.map((topic) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: topic, className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: `topic-${topic.replace(/\s/g, "-")}`, checked: selectedTopics.has(topic), onCheckedChange: (checked) => handleTopicToggle(topic, !!checked), disabled: isGenerating }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `topic-${topic.replace(/\s/g, "-")}`, className: "font-normal cursor-pointer" }, topic)))) : /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, t4("practiceFlow.setup.step3_empty")))), selectedTopics.size > 0 && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 p-4 border rounded-lg animate-in fade-in duration-700" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "language-select", className: "font-semibold" }, t4("practiceFlow.setup.step4_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage, disabled: isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "language-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step4_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, AVAILABLE_LANGUAGES.map((lang) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "difficulty-select", className: "font-semibold" }, t4("practiceFlow.setup.step5_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedDifficulty, onValueChange: (v) => setSelectedDifficulty(v), disabled: isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "difficulty-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step5_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, DIFFICULTY_LEVELS.map((level) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: level, value: level }, level)))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "font-semibold flex items-center" }, /* @__PURE__ */ React169__namespace.default.createElement(Code, { className: "mr-2 h-4 w-4" }), t4("practiceFlow.setup.step6_title")), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: "include-coding", checked: includeCodingQuestions, onCheckedChange: (checked) => setIncludeCodingQuestions(!!checked), disabled: isGenerating }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "include-coding", className: "font-normal cursor-pointer" }, t4("practiceFlow.setup.includeCoding"))), includeCodingQuestions && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "pl-6 animate-in fade-in duration-300" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "num-coding-questions" }, t4("practiceFlow.setup.numCoding")), /* @__PURE__ */ React169__namespace.default.createElement(
138401
- Input,
138402
- {
138403
- id: "num-coding-questions",
138404
- type: "number",
138405
- value: numCodingQuestions,
138406
- onChange: handleNumCodingChange,
138407
- min: "1",
138408
- max: "3",
138409
- className: "w-24 mt-1",
138410
- disabled: isGenerating
138411
- }
138412
- ))))), /* @__PURE__ */ React169__namespace.default.createElement(CardFooter, null, /* @__PURE__ */ React169__namespace.default.createElement(Button, { onClick: handleStartClick, disabled: !isReadyToStart, className: "w-full" }, isGenerating ? /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), t4("practiceFlow.setup.generatingButton")) : /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), t4("practiceFlow.setup.startButton")))));
138332
+ return /* @__PURE__ */ React169__namespace.default.createElement(Card, { className: "w-full max-w-2xl mx-auto" }, /* @__PURE__ */ React169__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(CardTitle, { className: "flex items-center text-2xl font-headline" }, /* @__PURE__ */ React169__namespace.default.createElement(BrainCircuit, { className: "mr-3 h-6 w-6 text-primary" }), t4("practiceFlow.setup.title")), /* @__PURE__ */ React169__namespace.default.createElement(CardDescription, null, t4("practiceFlow.setup.description"))), /* @__PURE__ */ React169__namespace.default.createElement(CardContent, { className: "space-y-6" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "subject-select", className: "font-semibold" }, t4("practiceFlow.setup.step1_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedSubject, onValueChange: (val) => {
138333
+ setSelectedSubject(val);
138334
+ setSelectedTopics(/* @__PURE__ */ new Set());
138335
+ }, disabled: isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "subject-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step1_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, subjects.map((subject) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: subject, value: subject }, subject))))), selectedSubject && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 animate-in fade-in duration-300" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "font-semibold" }, t4("practiceFlow.setup.step2_title_combined")), /* @__PURE__ */ React169__namespace.default.createElement(ScrollArea2, { className: "h-48 w-full rounded-md border p-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Accordion2, { type: "multiple", className: "w-full" }, (categoriesBySubject[selectedSubject] || []).map((category) => /* @__PURE__ */ React169__namespace.default.createElement(AccordionItem2, { value: category, key: category }, /* @__PURE__ */ React169__namespace.default.createElement(AccordionTrigger2, { className: "text-sm font-medium px-2" }, category), /* @__PURE__ */ React169__namespace.default.createElement(AccordionContent2, { className: "pl-4" }, (topicsByCategory[category] || []).map((topic) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: topic, className: "flex items-center space-x-2 py-1" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: `topic-${topic.replace(/\s/g, "-")}`, checked: selectedTopics.has(topic), onCheckedChange: (checked) => handleTopicToggle(topic, !!checked), disabled: isGenerating }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `topic-${topic.replace(/\s/g, "-")}`, className: "font-normal cursor-pointer" }, topic))))))))), selectedTopics.size > 0 && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 p-4 border rounded-lg animate-in fade-in duration-700" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "num-questions", className: "font-semibold" }, t4("practiceFlow.setup.step_num_questions", { max: maxQuestions })), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "num-questions", type: "number", value: numQuestions, onChange: handleNumQuestionsChange, min: "1", max: maxQuestions, disabled: isGenerating })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "difficulty-select", className: "font-semibold" }, t4("practiceFlow.setup.step5_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedDifficulty, onValueChange: (v) => setSelectedDifficulty(v), disabled: isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "difficulty-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step5_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, DIFFICULTY_LEVELS.map((level) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: level, value: level }, level)))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { className: "font-semibold" }, t4("practiceFlow.setup.step_question_types")), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-2" }, allowedQuestionTypes.map((type) => /* @__PURE__ */ React169__namespace.default.createElement("div", { key: type, className: "flex items-center space-x-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Checkbox2, { id: `qtype-${type}`, checked: selectedQuestionTypes.has(type), onCheckedChange: (checked) => handleQuestionTypeToggle(type, !!checked), disabled: isGenerating }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: `qtype-${type}`, className: "font-normal cursor-pointer text-sm" }, ALL_QUESTION_TYPE_LABELS[type] || type))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "language-select", className: "font-semibold" }, t4("practiceFlow.setup.step4_title")), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage, disabled: isGenerating }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, { id: "language-select" }, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, { placeholder: t4("practiceFlow.setup.step4_placeholder") })), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, AVAILABLE_LANGUAGES.map((lang) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label))))))), /* @__PURE__ */ React169__namespace.default.createElement(CardFooter, null, /* @__PURE__ */ React169__namespace.default.createElement(Button, { onClick: handleStartClick, disabled: !isReadyToStart, className: "w-full" }, isGenerating ? /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), t4("practiceFlow.setup.generatingButton")) : /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), t4("practiceFlow.setup.startButton")))));
138413
138336
  };
138414
138337
 
138415
138338
  // src/react-ui/components/practice/PracticeModeController.tsx
@@ -138429,7 +138352,10 @@ var mapDifficultyToBloomDistribution = (difficulty) => {
138429
138352
  return [{ level: "remembering", ratio: 50 }, { level: "understanding", ratio: 50 }];
138430
138353
  }
138431
138354
  };
138432
- var PracticeModeController = () => {
138355
+ var PracticeModeController = ({
138356
+ maxQuestions,
138357
+ allowedQuestionTypes
138358
+ }) => {
138433
138359
  const router = navigation.useRouter();
138434
138360
  const [practiceState, setPracticeState] = React169.useState("initializing");
138435
138361
  const [quizConfig, setQuizConfig] = React169.useState(null);
@@ -138490,7 +138416,7 @@ var PracticeModeController = () => {
138490
138416
  setPracticeState("setup");
138491
138417
  }
138492
138418
  }, [toast2]);
138493
- const handleStartPractice = React169.useCallback(async (selectedLOs, difficulty, language3, includeCoding, numCoding) => {
138419
+ const handleStartPractice = React169.useCallback(async (selectedLOs, difficulty, language3, numQuestions, selectedQuestionTypes) => {
138494
138420
  setPracticeState("loading");
138495
138421
  setErrorMessage("");
138496
138422
  const apiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
@@ -138502,19 +138428,12 @@ var PracticeModeController = () => {
138502
138428
  return;
138503
138429
  }
138504
138430
  try {
138505
- const totalQuestions = 10;
138506
- const numCodingQuestions = includeCoding ? numCoding : 0;
138507
- const standardQuestionTypes = ["multiple_choice", "multiple_response", "true_false", "fill_in_the_blanks", "short_answer", "numeric", "sequence"];
138508
- let selectedQuestionTypes = [...standardQuestionTypes];
138509
- if (includeCoding) {
138510
- selectedQuestionTypes.push("coding");
138511
- }
138512
138431
  const planInput = {
138513
- totalQuestions,
138514
- numCodingQuestions,
138432
+ totalQuestions: numQuestions,
138433
+ numCodingQuestions: selectedQuestionTypes.includes("coding") ? 1 : 0,
138434
+ // Simplified logic for now
138515
138435
  topics: selectedLOs.map((lo) => ({
138516
138436
  topic: lo.name || lo.code,
138517
- // FIX: Provide fallback for name
138518
138437
  ratio: 100 / selectedLOs.length,
138519
138438
  originalLoId: lo.code,
138520
138439
  originalSubject: lo.subject,
@@ -138627,26 +138546,17 @@ var PracticeModeController = () => {
138627
138546
  case "initializing":
138628
138547
  return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-[400px]" }, /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "h-12 w-12 animate-spin text-primary" }), /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "mt-4 text-muted-foreground" }, "Initializing Practice Mode..."));
138629
138548
  case "setup":
138630
- return /* @__PURE__ */ React169__namespace.default.createElement(
138631
- PracticeSetup,
138632
- {
138633
- onStartPractice: handleStartPractice,
138634
- isGenerating: false,
138635
- initialLOs: initialSuggestedLOs,
138636
- initialDifficulty: initialSuggestedDifficulty,
138637
- initialLanguage: initialSuggestedLanguage
138638
- }
138639
- );
138640
138549
  case "loading":
138641
138550
  return /* @__PURE__ */ React169__namespace.default.createElement(
138642
138551
  PracticeSetup,
138643
138552
  {
138644
- onStartPractice: () => {
138645
- },
138646
- isGenerating: true,
138553
+ onStartPractice: handleStartPractice,
138554
+ isGenerating: practiceState === "loading",
138647
138555
  initialLOs: initialSuggestedLOs,
138648
138556
  initialDifficulty: initialSuggestedDifficulty,
138649
- initialLanguage: initialSuggestedLanguage
138557
+ initialLanguage: initialSuggestedLanguage,
138558
+ maxQuestions,
138559
+ allowedQuestionTypes
138650
138560
  }
138651
138561
  );
138652
138562
  case "playing":
@@ -1,11 +1,11 @@
1
- import { s as QuizConfig, g as QuizQuestion } from './quiz-config-CwaP-pBs.cjs';
2
- export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion, D as DragAndDropQuestion, l as DraggableItem, m as DropZone, F as FillInTheBlanksQuestion, n as HotspotArea, H as HotspotQuestion, M as MarkdownString, k as MatchOptionItem, j as MatchPromptItem, d as MatchingQuestion, a as MultipleChoiceQuestion, b as MultipleResponseQuestion, N as NumericQuestion, h as QuestionOption, Q as QuestionTypeStrings, r as QuizSettings, R as RichContentString, q as SCORMSettings, f as ScratchProgrammingQuestion, i as SequenceItem, c as SequenceQuestion, S as ShortAnswerQuestion, p as SupportedCodingLanguage, o as TestCase, T as TrueFalseQuestion } from './quiz-config-CwaP-pBs.cjs';
1
+ import { s as QuizConfig, g as QuizQuestion, Q as QuestionTypeStrings } from './quiz-config-CwaP-pBs.cjs';
2
+ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion, D as DragAndDropQuestion, l as DraggableItem, m as DropZone, F as FillInTheBlanksQuestion, n as HotspotArea, H as HotspotQuestion, M as MarkdownString, k as MatchOptionItem, j as MatchPromptItem, d as MatchingQuestion, a as MultipleChoiceQuestion, b as MultipleResponseQuestion, N as NumericQuestion, h as QuestionOption, r as QuizSettings, R as RichContentString, q as SCORMSettings, f as ScratchProgrammingQuestion, i as SequenceItem, c as SequenceQuestion, S as ShortAnswerQuestion, p as SupportedCodingLanguage, o as TestCase, T as TrueFalseQuestion } from './quiz-config-CwaP-pBs.cjs';
3
3
  export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, MetadataService, PracticeHistoryService, QuestionBankService, QuestionImportService, QuestionInBank, QuestionTypeType, QuizEditorService, QuizEngine, QuizEngineCallbacks, QuizEngineConstructorOptions, QuoteService, SCORMService, StandardDifficulty, Subject, Topic, UserConfigService, cn, emptyQuiz, exportQuizAsSCORMZip, generateLauncherHTML, generateSCORMManifest, generateUniqueId, sampleQuiz } from './index.cjs';
4
4
  import { Q as QuizResultType, U as UserAnswerType, n as PracticeSession, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, i as Achievement, p as PracticeSessionSummary, h as QuizReviewContent } from './ai-ecosystem-DyQYZbyX.cjs';
5
5
  export { j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, q as PracticeTopicSummary, g as QuestionReview, R as RoadmapItem, T as TestCaseResult, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DyQYZbyX.cjs';
6
6
  import * as React$1 from 'react';
7
7
  import React__default, { ReactNode } from 'react';
8
- export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Bvhmyef9.cjs';
8
+ export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-CexT11VU.cjs';
9
9
  import * as class_variance_authority_types from 'class-variance-authority/types';
10
10
  import { VariantProps } from 'class-variance-authority';
11
11
  import * as LabelPrimitive from '@radix-ui/react-label';
@@ -94,7 +94,11 @@ interface UploadResourceModalProps {
94
94
  }
95
95
  declare const UploadResourceModal: React__default.FC<UploadResourceModalProps>;
96
96
 
97
- declare const PracticeModeController: React__default.FC;
97
+ interface PracticeModeControllerProps {
98
+ maxQuestions?: number;
99
+ allowedQuestionTypes?: QuestionTypeStrings[];
100
+ }
101
+ declare const PracticeModeController: React__default.FC<PracticeModeControllerProps>;
98
102
 
99
103
  interface SuggestionDialogProps {
100
104
  isOpen: boolean;
@@ -218,4 +222,4 @@ declare const TabsList: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.Tab
218
222
  declare const TabsTrigger: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
219
223
  declare const TabsContent: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
220
224
 
221
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Achievement, Achievements, ActivityCalendar, Alert, AlertDescription, AlertTitle, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Cheatsheet, Checkbox, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, FreestyleQuizzesCard, GeneratedQuizzesCard, Input, Label, LanguageProvider, ManageTopics, PerformanceCharts, PersonalPracticeDashboard, PracticeHistoryTable, PracticeModeController, PracticeSession, PracticeSessionSummary, PracticeStats, PracticeSuggestion, PracticeSuggestionTopic, Progress, QuestionRenderer, QuizConfig, QuizDataManagement, QuizPlayer, QuizQuestion, QuizResult, QuizResultType, QuizReview, QuizReviewContent, RadioGroup, RadioGroupItem, ScrollArea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, SettingsModal, Skeleton, SuggestionDialog, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadResourceModal, UserAnswerType };
225
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Achievement, Achievements, ActivityCalendar, Alert, AlertDescription, AlertTitle, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Cheatsheet, Checkbox, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, FreestyleQuizzesCard, GeneratedQuizzesCard, Input, Label, LanguageProvider, ManageTopics, PerformanceCharts, PersonalPracticeDashboard, PracticeHistoryTable, PracticeModeController, PracticeSession, PracticeSessionSummary, PracticeStats, PracticeSuggestion, PracticeSuggestionTopic, Progress, QuestionRenderer, QuestionTypeStrings, QuizConfig, QuizDataManagement, QuizPlayer, QuizQuestion, QuizResult, QuizResultType, QuizReview, QuizReviewContent, RadioGroup, RadioGroupItem, ScrollArea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, SettingsModal, Skeleton, SuggestionDialog, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadResourceModal, UserAnswerType };
@@ -1,11 +1,11 @@
1
- import { s as QuizConfig, g as QuizQuestion } from './quiz-config-CwaP-pBs.js';
2
- export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion, D as DragAndDropQuestion, l as DraggableItem, m as DropZone, F as FillInTheBlanksQuestion, n as HotspotArea, H as HotspotQuestion, M as MarkdownString, k as MatchOptionItem, j as MatchPromptItem, d as MatchingQuestion, a as MultipleChoiceQuestion, b as MultipleResponseQuestion, N as NumericQuestion, h as QuestionOption, Q as QuestionTypeStrings, r as QuizSettings, R as RichContentString, q as SCORMSettings, f as ScratchProgrammingQuestion, i as SequenceItem, c as SequenceQuestion, S as ShortAnswerQuestion, p as SupportedCodingLanguage, o as TestCase, T as TrueFalseQuestion } from './quiz-config-CwaP-pBs.js';
1
+ import { s as QuizConfig, g as QuizQuestion, Q as QuestionTypeStrings } from './quiz-config-CwaP-pBs.js';
2
+ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion, D as DragAndDropQuestion, l as DraggableItem, m as DropZone, F as FillInTheBlanksQuestion, n as HotspotArea, H as HotspotQuestion, M as MarkdownString, k as MatchOptionItem, j as MatchPromptItem, d as MatchingQuestion, a as MultipleChoiceQuestion, b as MultipleResponseQuestion, N as NumericQuestion, h as QuestionOption, r as QuizSettings, R as RichContentString, q as SCORMSettings, f as ScratchProgrammingQuestion, i as SequenceItem, c as SequenceQuestion, S as ShortAnswerQuestion, p as SupportedCodingLanguage, o as TestCase, T as TrueFalseQuestion } from './quiz-config-CwaP-pBs.js';
3
3
  export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, MetadataService, PracticeHistoryService, QuestionBankService, QuestionImportService, QuestionInBank, QuestionTypeType, QuizEditorService, QuizEngine, QuizEngineCallbacks, QuizEngineConstructorOptions, QuoteService, SCORMService, StandardDifficulty, Subject, Topic, UserConfigService, cn, emptyQuiz, exportQuizAsSCORMZip, generateLauncherHTML, generateSCORMManifest, generateUniqueId, sampleQuiz } from './index.js';
4
4
  import { Q as QuizResultType, U as UserAnswerType, n as PracticeSession, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, i as Achievement, p as PracticeSessionSummary, h as QuizReviewContent } from './ai-ecosystem-Qa_SdE2T.js';
5
5
  export { j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, q as PracticeTopicSummary, g as QuestionReview, R as RoadmapItem, T as TestCaseResult, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-Qa_SdE2T.js';
6
6
  import * as React$1 from 'react';
7
7
  import React__default, { ReactNode } from 'react';
8
- export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-B2MPZYhi.js';
8
+ export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Bj78wmSz.js';
9
9
  import * as class_variance_authority_types from 'class-variance-authority/types';
10
10
  import { VariantProps } from 'class-variance-authority';
11
11
  import * as LabelPrimitive from '@radix-ui/react-label';
@@ -94,7 +94,11 @@ interface UploadResourceModalProps {
94
94
  }
95
95
  declare const UploadResourceModal: React__default.FC<UploadResourceModalProps>;
96
96
 
97
- declare const PracticeModeController: React__default.FC;
97
+ interface PracticeModeControllerProps {
98
+ maxQuestions?: number;
99
+ allowedQuestionTypes?: QuestionTypeStrings[];
100
+ }
101
+ declare const PracticeModeController: React__default.FC<PracticeModeControllerProps>;
98
102
 
99
103
  interface SuggestionDialogProps {
100
104
  isOpen: boolean;
@@ -218,4 +222,4 @@ declare const TabsList: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.Tab
218
222
  declare const TabsTrigger: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
219
223
  declare const TabsContent: React$1.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
220
224
 
221
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Achievement, Achievements, ActivityCalendar, Alert, AlertDescription, AlertTitle, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Cheatsheet, Checkbox, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, FreestyleQuizzesCard, GeneratedQuizzesCard, Input, Label, LanguageProvider, ManageTopics, PerformanceCharts, PersonalPracticeDashboard, PracticeHistoryTable, PracticeModeController, PracticeSession, PracticeSessionSummary, PracticeStats, PracticeSuggestion, PracticeSuggestionTopic, Progress, QuestionRenderer, QuizConfig, QuizDataManagement, QuizPlayer, QuizQuestion, QuizResult, QuizResultType, QuizReview, QuizReviewContent, RadioGroup, RadioGroupItem, ScrollArea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, SettingsModal, Skeleton, SuggestionDialog, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadResourceModal, UserAnswerType };
225
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Achievement, Achievements, ActivityCalendar, Alert, AlertDescription, AlertTitle, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Cheatsheet, Checkbox, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, FreestyleQuizzesCard, GeneratedQuizzesCard, Input, Label, LanguageProvider, ManageTopics, PerformanceCharts, PersonalPracticeDashboard, PracticeHistoryTable, PracticeModeController, PracticeSession, PracticeSessionSummary, PracticeStats, PracticeSuggestion, PracticeSuggestionTopic, Progress, QuestionRenderer, QuestionTypeStrings, QuizConfig, QuizDataManagement, QuizPlayer, QuizQuestion, QuizResult, QuizResultType, QuizReview, QuizReviewContent, RadioGroup, RadioGroupItem, ScrollArea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, SettingsModal, Skeleton, SuggestionDialog, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UploadResourceModal, UserAnswerType };