@thanh01.pmt/interactive-quiz-kit 1.0.42 → 1.0.44

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.
@@ -72,7 +72,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
72
72
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
73
73
  var init_react_shim = __esm({
74
74
  "react-shim.ts"() {
75
- window.React = React97__namespace.default;
76
75
  }
77
76
  });
78
77
 
@@ -101878,50 +101877,49 @@ init_react_shim();
101878
101877
 
101879
101878
  // src/react-ui/components/app/APIKeyManagerModal.tsx
101880
101879
  init_react_shim();
101881
- var APIKeyManagerModal = ({ isOpen, onClose }) => {
101880
+
101881
+ // src/react-ui/components/settings/APIKeySettings.tsx
101882
+ init_react_shim();
101883
+ function ApiKeySettings() {
101882
101884
  const [geminiApiKey, setGeminiApiKey] = React97.useState("");
101885
+ const [isSaving, startSavingTransition] = React97.useTransition();
101883
101886
  const { toast: toast2 } = useToast();
101884
101887
  React97.useEffect(() => {
101885
- if (isOpen) {
101886
- const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101887
- setGeminiApiKey(existingKey || "");
101888
- }
101889
- }, [isOpen]);
101890
- const handleSave = () => {
101891
- if (geminiApiKey.trim()) {
101892
- APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
101893
- toast2({
101894
- title: "API Key Saved",
101895
- description: "Your Google Gemini API Key has been saved to local storage."
101896
- });
101897
- } else {
101898
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101899
- toast2({
101900
- title: "API Key Cleared",
101901
- description: "Your Google Gemini API Key has been removed."
101902
- });
101903
- }
101904
- onClose();
101905
- };
101906
- const handleClear = () => {
101907
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101908
- setGeminiApiKey("");
101909
- toast2({
101910
- title: "API Key Cleared",
101911
- description: "Your Google Gemini API Key has been removed."
101888
+ const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101889
+ setGeminiApiKey(existingKey || "");
101890
+ }, []);
101891
+ const handleSaveApiKey = () => {
101892
+ startSavingTransition(() => {
101893
+ if (geminiApiKey.trim()) {
101894
+ APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
101895
+ toast2({
101896
+ title: "API Key Saved",
101897
+ description: "Your Gemini API Key has been saved to local storage."
101898
+ });
101899
+ } else {
101900
+ APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101901
+ toast2({
101902
+ title: "API Key Cleared",
101903
+ description: "Your Gemini API Key has been removed."
101904
+ });
101905
+ }
101912
101906
  });
101913
- onClose();
101914
101907
  };
101915
- return /* @__PURE__ */ React97__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React97__namespace.default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React97__namespace.default.createElement(DialogTitle2, { className: "flex items-center" }, /* @__PURE__ */ React97__namespace.default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), "Manage API Keys"), /* @__PURE__ */ React97__namespace.default.createElement(DialogDescription2, null, "Enter and save your API keys here. They will be stored securely in your browser's local storage and will not be sent to any server other than the API provider's.")), /* @__PURE__ */ React97__namespace.default.createElement("div", { className: "py-4 space-y-4" }, /* @__PURE__ */ React97__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React97__namespace.default.createElement(Label2, { htmlFor: "gemini-api-key" }, "Google Gemini API Key"), /* @__PURE__ */ React97__namespace.default.createElement(
101908
+ return /* @__PURE__ */ React97__namespace.default.createElement(Card, null, /* @__PURE__ */ React97__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React97__namespace.default.createElement(CardTitle, { className: "flex items-center" }, /* @__PURE__ */ React97__namespace.default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), " API Keys"), /* @__PURE__ */ React97__namespace.default.createElement(CardDescription, null, "Manage your API keys for third-party services. Keys are obfuscated and stored locally in your browser.")), /* @__PURE__ */ React97__namespace.default.createElement(CardContent, { className: "space-y-4" }, /* @__PURE__ */ React97__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React97__namespace.default.createElement(Label2, { htmlFor: "geminiApiKey" }, "Gemini API Key"), /* @__PURE__ */ React97__namespace.default.createElement(
101916
101909
  Input,
101917
101910
  {
101918
- id: "gemini-api-key",
101911
+ id: "geminiApiKey",
101919
101912
  type: "password",
101920
101913
  value: geminiApiKey,
101921
101914
  onChange: (e2) => setGeminiApiKey(e2.target.value),
101922
101915
  placeholder: "Enter your Gemini API Key"
101923
101916
  }
101924
- ))), /* @__PURE__ */ React97__namespace.default.createElement(DialogFooter, { className: "gap-2 sm:justify-between" }, /* @__PURE__ */ React97__namespace.default.createElement(Button, { type: "button", variant: "destructive", onClick: handleClear }, /* @__PURE__ */ React97__namespace.default.createElement(Trash2, { className: "mr-2 h-4 w-4" }), " Clear Key"), /* @__PURE__ */ React97__namespace.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React97__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React97__namespace.default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React97__namespace.default.createElement(Button, { type: "button", onClick: handleSave }, /* @__PURE__ */ React97__namespace.default.createElement(Save, { className: "mr-2 h-4 w-4" }), " Save Key")))));
101917
+ ), /* @__PURE__ */ React97__namespace.default.createElement("p", { className: "text-xs text-muted-foreground" }, "Used for AI-powered features. Clear the field to remove the key."))), /* @__PURE__ */ React97__namespace.default.createElement(CardFooter, null, /* @__PURE__ */ React97__namespace.default.createElement(Button, { onClick: handleSaveApiKey, disabled: isSaving }, isSaving ? /* @__PURE__ */ React97__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React97__namespace.default.createElement(Save, { className: "mr-2 h-4 w-4" }), "Save API Key")));
101918
+ }
101919
+
101920
+ // src/react-ui/components/app/APIKeyManagerModal.tsx
101921
+ var APIKeyManagerModal = ({ isOpen, onClose }) => {
101922
+ return /* @__PURE__ */ React97__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React97__namespace.default.createElement(DialogContent2, { className: "sm:max-w-xl" }, /* @__PURE__ */ React97__namespace.default.createElement(ApiKeySettings, null)));
101925
101923
  };
101926
101924
 
101927
101925
  // src/react-ui/components/authoring/AIQuestionGeneratorModal.tsx
@@ -105488,7 +105486,7 @@ function Skeleton({
105488
105486
  className,
105489
105487
  ...props
105490
105488
  }) {
105491
- return /* @__PURE__ */ React.createElement(
105489
+ return /* @__PURE__ */ React97__namespace.default.createElement(
105492
105490
  "div",
105493
105491
  {
105494
105492
  className: cn("animate-pulse rounded-md bg-muted", className),
@@ -107268,9 +107266,9 @@ ToastDescription2.displayName = Description3.displayName;
107268
107266
  // src/react-ui/components/elements/toaster.tsx
107269
107267
  function Toaster() {
107270
107268
  const { toasts } = useToast();
107271
- return /* @__PURE__ */ React.createElement(ToastProvider2, null, toasts.map(function({ id: id2, title, description, action, ...props }) {
107272
- return /* @__PURE__ */ React.createElement(Toast2, { key: id2, ...props }, /* @__PURE__ */ React.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React.createElement(ToastClose2, null));
107273
- }), /* @__PURE__ */ React.createElement(ToastViewport2, null));
107269
+ return /* @__PURE__ */ React97__namespace.default.createElement(ToastProvider2, null, toasts.map(function({ id: id2, title, description, action, ...props }) {
107270
+ return /* @__PURE__ */ React97__namespace.default.createElement(Toast2, { key: id2, ...props }, /* @__PURE__ */ React97__namespace.default.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React97__namespace.default.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React97__namespace.default.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React97__namespace.default.createElement(ToastClose2, null));
107271
+ }), /* @__PURE__ */ React97__namespace.default.createElement(ToastViewport2, null));
107274
107272
  }
107275
107273
  /*! Bundled license information:
107276
107274
 
@@ -107332,6 +107330,7 @@ exports.AIQuestionGeneratorModal = AIQuestionGeneratorModal;
107332
107330
  exports.APIKeyManagerModal = APIKeyManagerModal;
107333
107331
  exports.APIKeyService = APIKeyService;
107334
107332
  exports.AchievementService = AchievementService;
107333
+ exports.ApiKeySettings = ApiKeySettings;
107335
107334
  exports.ApproachManager = ApproachManager;
107336
107335
  exports.BloomLevelManager = BloomLevelManager;
107337
107336
  exports.CategoryManager = CategoryManager;
@@ -2,7 +2,7 @@ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion
2
2
  export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, LearningObjectiveMetadata, 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';
3
3
  export { i as Achievement, 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, n as PracticeSession, p as PracticeSessionSummary, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, q as PracticeTopicSummary, g as QuestionReview, Q as QuizResultType, h as QuizReviewContent, R as RoadmapItem, T as TestCaseResult, U as UserAnswerType, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DqFRlFU3.cjs';
4
4
  export { AssessAndMapDocumentClientInput, AssessAndMapDocumentOutput, BloomLevelStringsForAI, GenerateCodingQuestionClientInput, GenerateCodingQuestionOutput, GenerateFillInTheBlanksQuestionClientInput, GenerateFillInTheBlanksQuestionOutput, GenerateLearningAnalysisClientInput, GenerateLearningAnalysisOutput, GenerateMCQQuestionClientInput, GenerateMCQQuestionOutput, GenerateMRQQuestionClientInput, GenerateMRQQuestionOutput, GenerateMatchingQuestionClientInput, GenerateMatchingQuestionOutput, GenerateMotivationalQuoteClientInput, GenerateMotivationalQuoteOutput, GenerateNumericQuestionClientInput, GenerateNumericQuestionOutput, GeneratePracticeSuggestionClientInput, GeneratePracticeSuggestionOutput, GenerateQuestionsFromQuizPlanClientInput, GenerateQuestionsFromQuizPlanOutput, GenerateQuizFromTextClientInput, GenerateQuizFromTextOutput, GenerateQuizPlanClientInput, GenerateQuizPlanOutput, GenerateQuizReviewClientInput, GenerateQuizReviewOutput, GenerateSequenceQuestionClientInput, GenerateSequenceQuestionOutput, GenerateShortAnswerQuestionClientInput, GenerateShortAnswerQuestionOutput, GenerateSingleKnowledgeCardClientInput, GenerateSingleKnowledgeCardOutput, GenerateTrueFalseQuestionClientInput, GenerateTrueFalseQuestionOutput, PlanKnowledgeCardsClientInput, PlanKnowledgeCardsOutput, PlannedQuestion, assessAndMapDocument, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, planKnowledgeCards } from './ai.cjs';
5
- export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, i as ApproachManager, B as BloomLevelManager, C as CategoryManager, h as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, d as QuestionFilters, e as QuestionFormDialog, c as QuestionList, g as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, f as SubjectManager, j as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-JTJ7cUyP.cjs';
5
+ export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, c as ApiKeySettings, j as ApproachManager, B as BloomLevelManager, C as CategoryManager, i as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, e as QuestionFilters, f as QuestionFormDialog, d as QuestionList, h as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, g as SubjectManager, k as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-DfLqsPwa.cjs';
6
6
  import 'clsx';
7
7
  import 'zod';
8
8
  import 'react';
@@ -2,7 +2,7 @@ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion
2
2
  export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, LearningObjectiveMetadata, 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';
3
3
  export { i as Achievement, 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, n as PracticeSession, p as PracticeSessionSummary, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, q as PracticeTopicSummary, g as QuestionReview, Q as QuizResultType, h as QuizReviewContent, R as RoadmapItem, T as TestCaseResult, U as UserAnswerType, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DqVlSO3r.js';
4
4
  export { AssessAndMapDocumentClientInput, AssessAndMapDocumentOutput, BloomLevelStringsForAI, GenerateCodingQuestionClientInput, GenerateCodingQuestionOutput, GenerateFillInTheBlanksQuestionClientInput, GenerateFillInTheBlanksQuestionOutput, GenerateLearningAnalysisClientInput, GenerateLearningAnalysisOutput, GenerateMCQQuestionClientInput, GenerateMCQQuestionOutput, GenerateMRQQuestionClientInput, GenerateMRQQuestionOutput, GenerateMatchingQuestionClientInput, GenerateMatchingQuestionOutput, GenerateMotivationalQuoteClientInput, GenerateMotivationalQuoteOutput, GenerateNumericQuestionClientInput, GenerateNumericQuestionOutput, GeneratePracticeSuggestionClientInput, GeneratePracticeSuggestionOutput, GenerateQuestionsFromQuizPlanClientInput, GenerateQuestionsFromQuizPlanOutput, GenerateQuizFromTextClientInput, GenerateQuizFromTextOutput, GenerateQuizPlanClientInput, GenerateQuizPlanOutput, GenerateQuizReviewClientInput, GenerateQuizReviewOutput, GenerateSequenceQuestionClientInput, GenerateSequenceQuestionOutput, GenerateShortAnswerQuestionClientInput, GenerateShortAnswerQuestionOutput, GenerateSingleKnowledgeCardClientInput, GenerateSingleKnowledgeCardOutput, GenerateTrueFalseQuestionClientInput, GenerateTrueFalseQuestionOutput, PlanKnowledgeCardsClientInput, PlanKnowledgeCardsOutput, PlannedQuestion, assessAndMapDocument, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, planKnowledgeCards } from './ai.js';
5
- export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, i as ApproachManager, B as BloomLevelManager, C as CategoryManager, h as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, d as QuestionFilters, e as QuestionFormDialog, c as QuestionList, g as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, f as SubjectManager, j as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Cgg3CSob.js';
5
+ export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, c as ApiKeySettings, j as ApproachManager, B as BloomLevelManager, C as CategoryManager, i as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, e as QuestionFilters, f as QuestionFormDialog, d as QuestionList, h as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, g as SubjectManager, k as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Z0Qz6kch.js';
6
6
  import 'clsx';
7
7
  import 'zod';
8
8
  import 'react';
@@ -46,7 +46,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
46
46
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
47
47
  var init_react_shim = __esm({
48
48
  "react-shim.ts"() {
49
- window.React = React97__default;
50
49
  }
51
50
  });
52
51
 
@@ -101852,50 +101851,49 @@ init_react_shim();
101852
101851
 
101853
101852
  // src/react-ui/components/app/APIKeyManagerModal.tsx
101854
101853
  init_react_shim();
101855
- var APIKeyManagerModal = ({ isOpen, onClose }) => {
101854
+
101855
+ // src/react-ui/components/settings/APIKeySettings.tsx
101856
+ init_react_shim();
101857
+ function ApiKeySettings() {
101856
101858
  const [geminiApiKey, setGeminiApiKey] = useState("");
101859
+ const [isSaving, startSavingTransition] = useTransition();
101857
101860
  const { toast: toast2 } = useToast();
101858
101861
  useEffect(() => {
101859
- if (isOpen) {
101860
- const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101861
- setGeminiApiKey(existingKey || "");
101862
- }
101863
- }, [isOpen]);
101864
- const handleSave = () => {
101865
- if (geminiApiKey.trim()) {
101866
- APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
101867
- toast2({
101868
- title: "API Key Saved",
101869
- description: "Your Google Gemini API Key has been saved to local storage."
101870
- });
101871
- } else {
101872
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101873
- toast2({
101874
- title: "API Key Cleared",
101875
- description: "Your Google Gemini API Key has been removed."
101876
- });
101877
- }
101878
- onClose();
101879
- };
101880
- const handleClear = () => {
101881
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101882
- setGeminiApiKey("");
101883
- toast2({
101884
- title: "API Key Cleared",
101885
- description: "Your Google Gemini API Key has been removed."
101862
+ const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101863
+ setGeminiApiKey(existingKey || "");
101864
+ }, []);
101865
+ const handleSaveApiKey = () => {
101866
+ startSavingTransition(() => {
101867
+ if (geminiApiKey.trim()) {
101868
+ APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
101869
+ toast2({
101870
+ title: "API Key Saved",
101871
+ description: "Your Gemini API Key has been saved to local storage."
101872
+ });
101873
+ } else {
101874
+ APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
101875
+ toast2({
101876
+ title: "API Key Cleared",
101877
+ description: "Your Gemini API Key has been removed."
101878
+ });
101879
+ }
101886
101880
  });
101887
- onClose();
101888
101881
  };
101889
- return /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), "Manage API Keys"), /* @__PURE__ */ React97__default.createElement(DialogDescription2, null, "Enter and save your API keys here. They will be stored securely in your browser's local storage and will not be sent to any server other than the API provider's.")), /* @__PURE__ */ React97__default.createElement("div", { className: "py-4 space-y-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "gemini-api-key" }, "Google Gemini API Key"), /* @__PURE__ */ React97__default.createElement(
101882
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), " API Keys"), /* @__PURE__ */ React97__default.createElement(CardDescription, null, "Manage your API keys for third-party services. Keys are obfuscated and stored locally in your browser.")), /* @__PURE__ */ React97__default.createElement(CardContent, { className: "space-y-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "geminiApiKey" }, "Gemini API Key"), /* @__PURE__ */ React97__default.createElement(
101890
101883
  Input,
101891
101884
  {
101892
- id: "gemini-api-key",
101885
+ id: "geminiApiKey",
101893
101886
  type: "password",
101894
101887
  value: geminiApiKey,
101895
101888
  onChange: (e2) => setGeminiApiKey(e2.target.value),
101896
101889
  placeholder: "Enter your Gemini API Key"
101897
101890
  }
101898
- ))), /* @__PURE__ */ React97__default.createElement(DialogFooter, { className: "gap-2 sm:justify-between" }, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "destructive", onClick: handleClear }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "mr-2 h-4 w-4" }), " Clear Key"), /* @__PURE__ */ React97__default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React97__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React97__default.createElement(Button, { type: "button", onClick: handleSave }, /* @__PURE__ */ React97__default.createElement(Save, { className: "mr-2 h-4 w-4" }), " Save Key")))));
101891
+ ), /* @__PURE__ */ React97__default.createElement("p", { className: "text-xs text-muted-foreground" }, "Used for AI-powered features. Clear the field to remove the key."))), /* @__PURE__ */ React97__default.createElement(CardFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleSaveApiKey, disabled: isSaving }, isSaving ? /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React97__default.createElement(Save, { className: "mr-2 h-4 w-4" }), "Save API Key")));
101892
+ }
101893
+
101894
+ // src/react-ui/components/app/APIKeyManagerModal.tsx
101895
+ var APIKeyManagerModal = ({ isOpen, onClose }) => {
101896
+ return /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-xl" }, /* @__PURE__ */ React97__default.createElement(ApiKeySettings, null)));
101899
101897
  };
101900
101898
 
101901
101899
  // src/react-ui/components/authoring/AIQuestionGeneratorModal.tsx
@@ -105462,7 +105460,7 @@ function Skeleton({
105462
105460
  className,
105463
105461
  ...props
105464
105462
  }) {
105465
- return /* @__PURE__ */ React.createElement(
105463
+ return /* @__PURE__ */ React97__default.createElement(
105466
105464
  "div",
105467
105465
  {
105468
105466
  className: cn("animate-pulse rounded-md bg-muted", className),
@@ -107242,9 +107240,9 @@ ToastDescription2.displayName = Description3.displayName;
107242
107240
  // src/react-ui/components/elements/toaster.tsx
107243
107241
  function Toaster() {
107244
107242
  const { toasts } = useToast();
107245
- return /* @__PURE__ */ React.createElement(ToastProvider2, null, toasts.map(function({ id: id2, title, description, action, ...props }) {
107246
- return /* @__PURE__ */ React.createElement(Toast2, { key: id2, ...props }, /* @__PURE__ */ React.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React.createElement(ToastClose2, null));
107247
- }), /* @__PURE__ */ React.createElement(ToastViewport2, null));
107243
+ return /* @__PURE__ */ React97__default.createElement(ToastProvider2, null, toasts.map(function({ id: id2, title, description, action, ...props }) {
107244
+ return /* @__PURE__ */ React97__default.createElement(Toast2, { key: id2, ...props }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React97__default.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React97__default.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React97__default.createElement(ToastClose2, null));
107245
+ }), /* @__PURE__ */ React97__default.createElement(ToastViewport2, null));
107248
107246
  }
107249
107247
  /*! Bundled license information:
107250
107248
 
@@ -107301,4 +107299,4 @@ lucide-react/dist/esm/lucide-react.js:
107301
107299
  *)
107302
107300
  */
107303
107301
 
107304
- export { AIFullQuizGeneratorModal, AIQuestionGeneratorModal, APIKeyManagerModal, APIKeyService, AchievementService, ApproachManager, BloomLevelManager, CategoryManager, ContextManager, EditQuestionModal, GEMINI_API_KEY_SERVICE_NAME, GradeLevelManager, ImportQuestionsModal, KnowledgeCardService, LearningObjectiveManager, MetadataService, MetadataTabs, PracticeHistoryService, QuestionBankService, QuestionFilters, QuestionFormDialog, QuestionImportService, QuestionList, QuestionTypeManager, QuizAuthoringTool, QuizEditorService, QuizEngine, QuoteService, SCORMExportModal, SCORMService, SubjectManager, Toaster, TopicManager, UserConfigService, assessAndMapDocument, cn, emptyQuiz, exportQuizAsSCORMZip, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLauncherHTML, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSCORMManifest, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, generateUniqueId, planKnowledgeCards, sampleQuiz, toast, useToast };
107302
+ export { AIFullQuizGeneratorModal, AIQuestionGeneratorModal, APIKeyManagerModal, APIKeyService, AchievementService, ApiKeySettings, ApproachManager, BloomLevelManager, CategoryManager, ContextManager, EditQuestionModal, GEMINI_API_KEY_SERVICE_NAME, GradeLevelManager, ImportQuestionsModal, KnowledgeCardService, LearningObjectiveManager, MetadataService, MetadataTabs, PracticeHistoryService, QuestionBankService, QuestionFilters, QuestionFormDialog, QuestionImportService, QuestionList, QuestionTypeManager, QuizAuthoringTool, QuizEditorService, QuizEngine, QuoteService, SCORMExportModal, SCORMService, SubjectManager, Toaster, TopicManager, UserConfigService, assessAndMapDocument, cn, emptyQuiz, exportQuizAsSCORMZip, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLauncherHTML, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSCORMManifest, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, generateUniqueId, planKnowledgeCards, sampleQuiz, toast, useToast };
package/dist/player.cjs CHANGED
@@ -72,7 +72,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
72
72
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
73
73
  var init_react_shim = __esm({
74
74
  "react-shim.ts"() {
75
- window.React = React73__namespace.default;
76
75
  }
77
76
  });
78
77
 
package/dist/player.mjs CHANGED
@@ -46,7 +46,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
46
46
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
47
47
  var init_react_shim = __esm({
48
48
  "react-shim.ts"() {
49
- window.React = React73__default;
50
49
  }
51
50
  });
52
51
 
package/dist/react-ui.cjs CHANGED
@@ -73,7 +73,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
73
73
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
74
74
  var init_react_shim = __esm({
75
75
  "react-shim.ts"() {
76
- window.React = React163__namespace.default;
77
76
  }
78
77
  });
79
78
 
@@ -128473,50 +128472,49 @@ init_react_shim();
128473
128472
 
128474
128473
  // src/react-ui/components/app/APIKeyManagerModal.tsx
128475
128474
  init_react_shim();
128476
- var APIKeyManagerModal = ({ isOpen, onClose }) => {
128475
+
128476
+ // src/react-ui/components/settings/APIKeySettings.tsx
128477
+ init_react_shim();
128478
+ function ApiKeySettings() {
128477
128479
  const [geminiApiKey, setGeminiApiKey] = React163.useState("");
128480
+ const [isSaving, startSavingTransition] = React163.useTransition();
128478
128481
  const { toast: toast2 } = useToast();
128479
128482
  React163.useEffect(() => {
128480
- if (isOpen) {
128481
- const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128482
- setGeminiApiKey(existingKey || "");
128483
- }
128484
- }, [isOpen]);
128485
- const handleSave = () => {
128486
- if (geminiApiKey.trim()) {
128487
- APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
128488
- toast2({
128489
- title: "API Key Saved",
128490
- description: "Your Google Gemini API Key has been saved to local storage."
128491
- });
128492
- } else {
128493
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128494
- toast2({
128495
- title: "API Key Cleared",
128496
- description: "Your Google Gemini API Key has been removed."
128497
- });
128498
- }
128499
- onClose();
128500
- };
128501
- const handleClear = () => {
128502
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128503
- setGeminiApiKey("");
128504
- toast2({
128505
- title: "API Key Cleared",
128506
- description: "Your Google Gemini API Key has been removed."
128483
+ const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128484
+ setGeminiApiKey(existingKey || "");
128485
+ }, []);
128486
+ const handleSaveApiKey = () => {
128487
+ startSavingTransition(() => {
128488
+ if (geminiApiKey.trim()) {
128489
+ APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
128490
+ toast2({
128491
+ title: "API Key Saved",
128492
+ description: "Your Gemini API Key has been saved to local storage."
128493
+ });
128494
+ } else {
128495
+ APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128496
+ toast2({
128497
+ title: "API Key Cleared",
128498
+ description: "Your Gemini API Key has been removed."
128499
+ });
128500
+ }
128507
128501
  });
128508
- onClose();
128509
128502
  };
128510
- return /* @__PURE__ */ React163__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React163__namespace.default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React163__namespace.default.createElement(DialogTitle2, { className: "flex items-center" }, /* @__PURE__ */ React163__namespace.default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), "Manage API Keys"), /* @__PURE__ */ React163__namespace.default.createElement(DialogDescription2, null, "Enter and save your API keys here. They will be stored securely in your browser's local storage and will not be sent to any server other than the API provider's.")), /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "py-4 space-y-4" }, /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React163__namespace.default.createElement(Label2, { htmlFor: "gemini-api-key" }, "Google Gemini API Key"), /* @__PURE__ */ React163__namespace.default.createElement(
128503
+ return /* @__PURE__ */ React163__namespace.default.createElement(Card, null, /* @__PURE__ */ React163__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React163__namespace.default.createElement(CardTitle, { className: "flex items-center" }, /* @__PURE__ */ React163__namespace.default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), " API Keys"), /* @__PURE__ */ React163__namespace.default.createElement(CardDescription, null, "Manage your API keys for third-party services. Keys are obfuscated and stored locally in your browser.")), /* @__PURE__ */ React163__namespace.default.createElement(CardContent, { className: "space-y-4" }, /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React163__namespace.default.createElement(Label2, { htmlFor: "geminiApiKey" }, "Gemini API Key"), /* @__PURE__ */ React163__namespace.default.createElement(
128511
128504
  Input,
128512
128505
  {
128513
- id: "gemini-api-key",
128506
+ id: "geminiApiKey",
128514
128507
  type: "password",
128515
128508
  value: geminiApiKey,
128516
128509
  onChange: (e3) => setGeminiApiKey(e3.target.value),
128517
128510
  placeholder: "Enter your Gemini API Key"
128518
128511
  }
128519
- ))), /* @__PURE__ */ React163__namespace.default.createElement(DialogFooter, { className: "gap-2 sm:justify-between" }, /* @__PURE__ */ React163__namespace.default.createElement(Button, { type: "button", variant: "destructive", onClick: handleClear }, /* @__PURE__ */ React163__namespace.default.createElement(Trash2, { className: "mr-2 h-4 w-4" }), " Clear Key"), /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React163__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React163__namespace.default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React163__namespace.default.createElement(Button, { type: "button", onClick: handleSave }, /* @__PURE__ */ React163__namespace.default.createElement(Save, { className: "mr-2 h-4 w-4" }), " Save Key")))));
128512
+ ), /* @__PURE__ */ React163__namespace.default.createElement("p", { className: "text-xs text-muted-foreground" }, "Used for AI-powered features. Clear the field to remove the key."))), /* @__PURE__ */ React163__namespace.default.createElement(CardFooter, null, /* @__PURE__ */ React163__namespace.default.createElement(Button, { onClick: handleSaveApiKey, disabled: isSaving }, isSaving ? /* @__PURE__ */ React163__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React163__namespace.default.createElement(Save, { className: "mr-2 h-4 w-4" }), "Save API Key")));
128513
+ }
128514
+
128515
+ // src/react-ui/components/app/APIKeyManagerModal.tsx
128516
+ var APIKeyManagerModal = ({ isOpen, onClose }) => {
128517
+ return /* @__PURE__ */ React163__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React163__namespace.default.createElement(DialogContent2, { className: "sm:max-w-xl" }, /* @__PURE__ */ React163__namespace.default.createElement(ApiKeySettings, null)));
128520
128518
  };
128521
128519
 
128522
128520
  // src/ai/flows/question-gen/generate-true-false-question.ts
@@ -142879,7 +142877,7 @@ function Skeleton({
142879
142877
  className,
142880
142878
  ...props
142881
142879
  }) {
142882
- return /* @__PURE__ */ React.createElement(
142880
+ return /* @__PURE__ */ React163__namespace.default.createElement(
142883
142881
  "div",
142884
142882
  {
142885
142883
  className: cn("animate-pulse rounded-md bg-muted", className),
@@ -169572,9 +169570,9 @@ ToastDescription2.displayName = Description3.displayName;
169572
169570
  // src/react-ui/components/elements/toaster.tsx
169573
169571
  function Toaster() {
169574
169572
  const { toasts } = useToast();
169575
- return /* @__PURE__ */ React.createElement(ToastProvider2, null, toasts.map(function({ id: id3, title, description, action, ...props }) {
169576
- return /* @__PURE__ */ React.createElement(Toast2, { key: id3, ...props }, /* @__PURE__ */ React.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React.createElement(ToastClose2, null));
169577
- }), /* @__PURE__ */ React.createElement(ToastViewport2, null));
169573
+ return /* @__PURE__ */ React163__namespace.default.createElement(ToastProvider2, null, toasts.map(function({ id: id3, title, description, action, ...props }) {
169574
+ return /* @__PURE__ */ React163__namespace.default.createElement(Toast2, { key: id3, ...props }, /* @__PURE__ */ React163__namespace.default.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React163__namespace.default.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React163__namespace.default.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React163__namespace.default.createElement(ToastClose2, null));
169575
+ }), /* @__PURE__ */ React163__namespace.default.createElement(ToastViewport2, null));
169578
169576
  }
169579
169577
  /*! Bundled license information:
169580
169578
 
@@ -171136,6 +171134,7 @@ exports.ActivityCalendar = ActivityCalendar;
171136
171134
  exports.Alert = Alert;
171137
171135
  exports.AlertDescription = AlertDescription;
171138
171136
  exports.AlertTitle = AlertTitle;
171137
+ exports.ApiKeySettings = ApiKeySettings;
171139
171138
  exports.ApproachManager = ApproachManager;
171140
171139
  exports.Badge = Badge2;
171141
171140
  exports.BloomLevelManager = BloomLevelManager;
@@ -5,7 +5,7 @@ import { Q as QuizResultType, U as UserAnswerType, m as PracticeSuggestion, l as
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, n as PracticeSession, q as PracticeTopicSummary, g as QuestionReview, R as RoadmapItem, T as TestCaseResult, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DqFRlFU3.cjs';
6
6
  import * as React$1 from 'react';
7
7
  import React__default, { ReactNode } from 'react';
8
- export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, i as ApproachManager, B as BloomLevelManager, C as CategoryManager, h as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, d as QuestionFilters, e as QuestionFormDialog, c as QuestionList, g as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, f as SubjectManager, j as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-JTJ7cUyP.cjs';
8
+ export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, c as ApiKeySettings, j as ApproachManager, B as BloomLevelManager, C as CategoryManager, i as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, e as QuestionFilters, f as QuestionFormDialog, d as QuestionList, h as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, g as SubjectManager, k as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-DfLqsPwa.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';
@@ -5,7 +5,7 @@ import { Q as QuizResultType, U as UserAnswerType, m as PracticeSuggestion, l as
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, n as PracticeSession, q as PracticeTopicSummary, g as QuestionReview, R as RoadmapItem, T as TestCaseResult, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DqVlSO3r.js';
6
6
  import * as React$1 from 'react';
7
7
  import React__default, { ReactNode } from 'react';
8
- export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, i as ApproachManager, B as BloomLevelManager, C as CategoryManager, h as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, d as QuestionFilters, e as QuestionFormDialog, c as QuestionList, g as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, f as SubjectManager, j as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Cgg3CSob.js';
8
+ export { a as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, b as APIKeyManagerModal, c as ApiKeySettings, j as ApproachManager, B as BloomLevelManager, C as CategoryManager, i as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, M as MetadataTabs, e as QuestionFilters, f as QuestionFormDialog, d as QuestionList, h as QuestionTypeManager, Q as QuizAuthoringTool, S as SCORMExportModal, g as SubjectManager, k as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Z0Qz6kch.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';
package/dist/react-ui.mjs CHANGED
@@ -47,7 +47,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
47
47
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
48
48
  var init_react_shim = __esm({
49
49
  "react-shim.ts"() {
50
- window.React = React163__default;
51
50
  }
52
51
  });
53
52
 
@@ -128447,50 +128446,49 @@ init_react_shim();
128447
128446
 
128448
128447
  // src/react-ui/components/app/APIKeyManagerModal.tsx
128449
128448
  init_react_shim();
128450
- var APIKeyManagerModal = ({ isOpen, onClose }) => {
128449
+
128450
+ // src/react-ui/components/settings/APIKeySettings.tsx
128451
+ init_react_shim();
128452
+ function ApiKeySettings() {
128451
128453
  const [geminiApiKey, setGeminiApiKey] = useState("");
128454
+ const [isSaving, startSavingTransition] = useTransition();
128452
128455
  const { toast: toast2 } = useToast();
128453
128456
  useEffect(() => {
128454
- if (isOpen) {
128455
- const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128456
- setGeminiApiKey(existingKey || "");
128457
- }
128458
- }, [isOpen]);
128459
- const handleSave = () => {
128460
- if (geminiApiKey.trim()) {
128461
- APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
128462
- toast2({
128463
- title: "API Key Saved",
128464
- description: "Your Google Gemini API Key has been saved to local storage."
128465
- });
128466
- } else {
128467
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128468
- toast2({
128469
- title: "API Key Cleared",
128470
- description: "Your Google Gemini API Key has been removed."
128471
- });
128472
- }
128473
- onClose();
128474
- };
128475
- const handleClear = () => {
128476
- APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128477
- setGeminiApiKey("");
128478
- toast2({
128479
- title: "API Key Cleared",
128480
- description: "Your Google Gemini API Key has been removed."
128457
+ const existingKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128458
+ setGeminiApiKey(existingKey || "");
128459
+ }, []);
128460
+ const handleSaveApiKey = () => {
128461
+ startSavingTransition(() => {
128462
+ if (geminiApiKey.trim()) {
128463
+ APIKeyService.saveAPIKey(GEMINI_API_KEY_SERVICE_NAME, geminiApiKey.trim());
128464
+ toast2({
128465
+ title: "API Key Saved",
128466
+ description: "Your Gemini API Key has been saved to local storage."
128467
+ });
128468
+ } else {
128469
+ APIKeyService.removeAPIKey(GEMINI_API_KEY_SERVICE_NAME);
128470
+ toast2({
128471
+ title: "API Key Cleared",
128472
+ description: "Your Gemini API Key has been removed."
128473
+ });
128474
+ }
128481
128475
  });
128482
- onClose();
128483
128476
  };
128484
- return /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), "Manage API Keys"), /* @__PURE__ */ React163__default.createElement(DialogDescription2, null, "Enter and save your API keys here. They will be stored securely in your browser's local storage and will not be sent to any server other than the API provider's.")), /* @__PURE__ */ React163__default.createElement("div", { className: "py-4 space-y-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "gemini-api-key" }, "Google Gemini API Key"), /* @__PURE__ */ React163__default.createElement(
128477
+ return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(KeyRound, { className: "mr-2 h-5 w-5 text-primary" }), " API Keys"), /* @__PURE__ */ React163__default.createElement(CardDescription, null, "Manage your API keys for third-party services. Keys are obfuscated and stored locally in your browser.")), /* @__PURE__ */ React163__default.createElement(CardContent, { className: "space-y-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "geminiApiKey" }, "Gemini API Key"), /* @__PURE__ */ React163__default.createElement(
128485
128478
  Input,
128486
128479
  {
128487
- id: "gemini-api-key",
128480
+ id: "geminiApiKey",
128488
128481
  type: "password",
128489
128482
  value: geminiApiKey,
128490
128483
  onChange: (e3) => setGeminiApiKey(e3.target.value),
128491
128484
  placeholder: "Enter your Gemini API Key"
128492
128485
  }
128493
- ))), /* @__PURE__ */ React163__default.createElement(DialogFooter, { className: "gap-2 sm:justify-between" }, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "destructive", onClick: handleClear }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "mr-2 h-4 w-4" }), " Clear Key"), /* @__PURE__ */ React163__default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React163__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React163__default.createElement(Button, { type: "button", onClick: handleSave }, /* @__PURE__ */ React163__default.createElement(Save, { className: "mr-2 h-4 w-4" }), " Save Key")))));
128486
+ ), /* @__PURE__ */ React163__default.createElement("p", { className: "text-xs text-muted-foreground" }, "Used for AI-powered features. Clear the field to remove the key."))), /* @__PURE__ */ React163__default.createElement(CardFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleSaveApiKey, disabled: isSaving }, isSaving ? /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React163__default.createElement(Save, { className: "mr-2 h-4 w-4" }), "Save API Key")));
128487
+ }
128488
+
128489
+ // src/react-ui/components/app/APIKeyManagerModal.tsx
128490
+ var APIKeyManagerModal = ({ isOpen, onClose }) => {
128491
+ return /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open2) => !open2 && onClose() }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-xl" }, /* @__PURE__ */ React163__default.createElement(ApiKeySettings, null)));
128494
128492
  };
128495
128493
 
128496
128494
  // src/ai/flows/question-gen/generate-true-false-question.ts
@@ -142853,7 +142851,7 @@ function Skeleton({
142853
142851
  className,
142854
142852
  ...props
142855
142853
  }) {
142856
- return /* @__PURE__ */ React.createElement(
142854
+ return /* @__PURE__ */ React163__default.createElement(
142857
142855
  "div",
142858
142856
  {
142859
142857
  className: cn("animate-pulse rounded-md bg-muted", className),
@@ -169546,9 +169544,9 @@ ToastDescription2.displayName = Description3.displayName;
169546
169544
  // src/react-ui/components/elements/toaster.tsx
169547
169545
  function Toaster() {
169548
169546
  const { toasts } = useToast();
169549
- return /* @__PURE__ */ React.createElement(ToastProvider2, null, toasts.map(function({ id: id3, title, description, action, ...props }) {
169550
- return /* @__PURE__ */ React.createElement(Toast2, { key: id3, ...props }, /* @__PURE__ */ React.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React.createElement(ToastClose2, null));
169551
- }), /* @__PURE__ */ React.createElement(ToastViewport2, null));
169547
+ return /* @__PURE__ */ React163__default.createElement(ToastProvider2, null, toasts.map(function({ id: id3, title, description, action, ...props }) {
169548
+ return /* @__PURE__ */ React163__default.createElement(Toast2, { key: id3, ...props }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-1" }, title && /* @__PURE__ */ React163__default.createElement(ToastTitle2, null, title), description && /* @__PURE__ */ React163__default.createElement(ToastDescription2, null, description)), action, /* @__PURE__ */ React163__default.createElement(ToastClose2, null));
169549
+ }), /* @__PURE__ */ React163__default.createElement(ToastViewport2, null));
169552
169550
  }
169553
169551
  /*! Bundled license information:
169554
169552
 
@@ -171098,4 +171096,4 @@ react-tooltip/dist/react-tooltip.min.mjs:
171098
171096
  *)
171099
171097
  */
171100
171098
 
171101
- export { AIFullQuizGeneratorModal, AIQuestionGeneratorModal, APIKeyManagerModal, Accordion2 as Accordion, AccordionContent2 as AccordionContent, AccordionItem2 as AccordionItem, AccordionTrigger2 as AccordionTrigger, Achievements, ActivityCalendar, Alert, AlertDescription, AlertTitle, ApproachManager, Badge2 as Badge, BloomLevelManager, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CategoryManager, Cheatsheet, Checkbox2 as Checkbox, ContextManager, Dialog2 as Dialog, DialogContent2 as DialogContent, DialogDescription2 as DialogDescription, DialogFooter, DialogHeader, DialogTitle2 as DialogTitle, EditQuestionModal, FreestyleQuizzesCard, GeneratedQuizzesCard, GradeLevelManager, ImportQuestionsModal, Input, Label2 as Label, LanguageProvider, LearningObjectiveManager, ManageTopics, MetadataTabs, PerformanceCharts, PersonalPracticeDashboard, PracticeHistoryTable, PracticeModeController, Progress2 as Progress, QuestionFilters, QuestionFormDialog, QuestionList, QuestionRenderer, QuestionTypeManager, QuizAuthoringTool, QuizDataManagement, QuizPlayer, QuizResult, QuizReview, RadioGroup2 as RadioGroup, RadioGroupItem2 as RadioGroupItem, SCORMExportModal, ScrollArea2 as ScrollArea, Select2 as Select, SelectContent2 as SelectContent, SelectItem2 as SelectItem, SelectTrigger2 as SelectTrigger, SelectValue2 as SelectValue, SettingsModal, Skeleton, SubjectManager, SuggestionDialog, Tabs2 as Tabs, TabsContent2 as TabsContent, TabsList2 as TabsList, TabsTrigger2 as TabsTrigger, Toaster, Tooltip2 as Tooltip, TooltipContent2 as TooltipContent, TooltipProvider2 as TooltipProvider, TooltipTrigger2 as TooltipTrigger, TopicManager, UploadResourceModal, toast, useToast };
171099
+ export { AIFullQuizGeneratorModal, AIQuestionGeneratorModal, APIKeyManagerModal, Accordion2 as Accordion, AccordionContent2 as AccordionContent, AccordionItem2 as AccordionItem, AccordionTrigger2 as AccordionTrigger, Achievements, ActivityCalendar, Alert, AlertDescription, AlertTitle, ApiKeySettings, ApproachManager, Badge2 as Badge, BloomLevelManager, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CategoryManager, Cheatsheet, Checkbox2 as Checkbox, ContextManager, Dialog2 as Dialog, DialogContent2 as DialogContent, DialogDescription2 as DialogDescription, DialogFooter, DialogHeader, DialogTitle2 as DialogTitle, EditQuestionModal, FreestyleQuizzesCard, GeneratedQuizzesCard, GradeLevelManager, ImportQuestionsModal, Input, Label2 as Label, LanguageProvider, LearningObjectiveManager, ManageTopics, MetadataTabs, PerformanceCharts, PersonalPracticeDashboard, PracticeHistoryTable, PracticeModeController, Progress2 as Progress, QuestionFilters, QuestionFormDialog, QuestionList, QuestionRenderer, QuestionTypeManager, QuizAuthoringTool, QuizDataManagement, QuizPlayer, QuizResult, QuizReview, RadioGroup2 as RadioGroup, RadioGroupItem2 as RadioGroupItem, SCORMExportModal, ScrollArea2 as ScrollArea, Select2 as Select, SelectContent2 as SelectContent, SelectItem2 as SelectItem, SelectTrigger2 as SelectTrigger, SelectValue2 as SelectValue, SettingsModal, Skeleton, SubjectManager, SuggestionDialog, Tabs2 as Tabs, TabsContent2 as TabsContent, TabsList2 as TabsList, TabsTrigger2 as TabsTrigger, Toaster, Tooltip2 as Tooltip, TooltipContent2 as TooltipContent, TooltipProvider2 as TooltipProvider, TooltipTrigger2 as TooltipTrigger, TopicManager, UploadResourceModal, toast, useToast };
@@ -80,8 +80,14 @@ interface APIKeyManagerModalProps {
80
80
  isOpen: boolean;
81
81
  onClose: () => void;
82
82
  }
83
+ /**
84
+ * A modal component that acts as a wrapper around the ApiKeySettings card.
85
+ * This provides a consistent modal experience for managing API keys within the library.
86
+ */
83
87
  declare const APIKeyManagerModal: React__default.FC<APIKeyManagerModalProps>;
84
88
 
89
+ declare function ApiKeySettings(): React__default.JSX.Element;
90
+
85
91
  declare function MetadataTabs(): React__default.JSX.Element;
86
92
 
87
93
  declare function SubjectManager(): React__default.JSX.Element;
@@ -129,4 +135,4 @@ declare function useToast(): {
129
135
 
130
136
  declare function Toaster(): React.JSX.Element;
131
137
 
132
- export { AIQuestionGeneratorModal as A, BloomLevelManager as B, CategoryManager as C, EditQuestionModal as E, GradeLevelManager as G, ImportQuestionsModal as I, LearningObjectiveManager as L, MetadataTabs as M, QuizAuthoringTool as Q, SCORMExportModal as S, TopicManager as T, AIFullQuizGeneratorModal as a, APIKeyManagerModal as b, QuestionList as c, QuestionFilters as d, QuestionFormDialog as e, SubjectManager as f, QuestionTypeManager as g, ContextManager as h, ApproachManager as i, Toaster as j, toast as t, useToast as u };
138
+ export { AIQuestionGeneratorModal as A, BloomLevelManager as B, CategoryManager as C, EditQuestionModal as E, GradeLevelManager as G, ImportQuestionsModal as I, LearningObjectiveManager as L, MetadataTabs as M, QuizAuthoringTool as Q, SCORMExportModal as S, TopicManager as T, AIFullQuizGeneratorModal as a, APIKeyManagerModal as b, ApiKeySettings as c, QuestionList as d, QuestionFilters as e, QuestionFormDialog as f, SubjectManager as g, QuestionTypeManager as h, ContextManager as i, ApproachManager as j, Toaster as k, toast as t, useToast as u };
@@ -80,8 +80,14 @@ interface APIKeyManagerModalProps {
80
80
  isOpen: boolean;
81
81
  onClose: () => void;
82
82
  }
83
+ /**
84
+ * A modal component that acts as a wrapper around the ApiKeySettings card.
85
+ * This provides a consistent modal experience for managing API keys within the library.
86
+ */
83
87
  declare const APIKeyManagerModal: React__default.FC<APIKeyManagerModalProps>;
84
88
 
89
+ declare function ApiKeySettings(): React__default.JSX.Element;
90
+
85
91
  declare function MetadataTabs(): React__default.JSX.Element;
86
92
 
87
93
  declare function SubjectManager(): React__default.JSX.Element;
@@ -129,4 +135,4 @@ declare function useToast(): {
129
135
 
130
136
  declare function Toaster(): React.JSX.Element;
131
137
 
132
- export { AIQuestionGeneratorModal as A, BloomLevelManager as B, CategoryManager as C, EditQuestionModal as E, GradeLevelManager as G, ImportQuestionsModal as I, LearningObjectiveManager as L, MetadataTabs as M, QuizAuthoringTool as Q, SCORMExportModal as S, TopicManager as T, AIFullQuizGeneratorModal as a, APIKeyManagerModal as b, QuestionList as c, QuestionFilters as d, QuestionFormDialog as e, SubjectManager as f, QuestionTypeManager as g, ContextManager as h, ApproachManager as i, Toaster as j, toast as t, useToast as u };
138
+ export { AIQuestionGeneratorModal as A, BloomLevelManager as B, CategoryManager as C, EditQuestionModal as E, GradeLevelManager as G, ImportQuestionsModal as I, LearningObjectiveManager as L, MetadataTabs as M, QuizAuthoringTool as Q, SCORMExportModal as S, TopicManager as T, AIFullQuizGeneratorModal as a, APIKeyManagerModal as b, ApiKeySettings as c, QuestionList as d, QuestionFilters as e, QuestionFormDialog as f, SubjectManager as g, QuestionTypeManager as h, ContextManager as i, ApproachManager as j, Toaster as k, toast as t, useToast as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thanh01.pmt/interactive-quiz-kit",
3
- "version": "1.0.42",
3
+ "version": "1.0.44",
4
4
  "description": "A comprehensive library for creating, managing, and playing interactive quizzes, with AI generation and SCORM support.",
5
5
  "keywords": [
6
6
  "react",