@tinyweb_dev/oe-exam-sdk 0.1.28 → 0.1.29

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.
Files changed (796) hide show
  1. package/README.md +4 -4
  2. package/dist/api/contest-rooms.js +54 -1
  3. package/dist/api/contest-rooms.types.js +1 -1
  4. package/dist/api/exam-create.js +179 -1
  5. package/dist/api/exam-create.types.js +1 -1
  6. package/dist/api/exam-entry.js +68 -1
  7. package/dist/api/exam-entry.types.js +1 -1
  8. package/dist/api/exam-questions.js +149 -1
  9. package/dist/api/exam-questions.types.js +1 -1
  10. package/dist/api/exam-taking.js +84 -1
  11. package/dist/api/exam-taking.types.d.ts +7 -0
  12. package/dist/api/exam-taking.types.js +1 -1
  13. package/dist/api/index.js +8 -1
  14. package/dist/api/result-review.js +62 -1
  15. package/dist/api/result-review.types.js +16 -1
  16. package/dist/components/CueCardEditor.js +58 -1
  17. package/dist/components/common/ResolvedImage.js +15 -1
  18. package/dist/components/exams/CompletionDialog.js +8 -1
  19. package/dist/components/exams/CreateExamInfoForm.js +84 -1
  20. package/dist/components/exams/CreateExamPageContainer.js +110 -1
  21. package/dist/components/exams/ExamCreator.js +287 -1
  22. package/dist/components/exams/ExamPartTabs.js +138 -1
  23. package/dist/components/exams/ExamPreviewDialog.d.ts +6 -7
  24. package/dist/components/exams/ExamPreviewDialog.js +121 -1
  25. package/dist/components/exams/ExamPreviewPartContent.d.ts +18 -0
  26. package/dist/components/exams/ExamPreviewPartContent.js +27 -0
  27. package/dist/components/exams/ExamPreviewSidebar.d.ts +17 -0
  28. package/dist/components/exams/ExamPreviewSidebar.js +37 -0
  29. package/dist/components/exams/ExamQuestionGrid.js +37 -1
  30. package/dist/components/exams/ExamQuestionsPageContainer.js +112 -1
  31. package/dist/components/exams/ExamViewDialog.js +61 -1
  32. package/dist/components/exams/PartAudioUploader.js +9 -1
  33. package/dist/components/exams/TemplateSelector.js +76 -1
  34. package/dist/components/exams/UnsavedChangesDialog.js +7 -1
  35. package/dist/components/exams/api.js +3 -1
  36. package/dist/components/exams/create-exam.texts.js +1 -1
  37. package/dist/components/exams/create-exam.validation.js +18 -1
  38. package/dist/components/exams/entry/EntryRestartDialog.js +11 -1
  39. package/dist/components/exams/entry/StudentExamEntryPageContainer.js +358 -1
  40. package/dist/components/exams/entry/exam-entry.states.js +26 -1
  41. package/dist/components/exams/entry/exam-entry.utils.js +55 -1
  42. package/dist/components/exams/entry/fullscreen-loading.js +18 -1
  43. package/dist/components/exams/entry/index.js +4 -1
  44. package/dist/components/exams/exam-preview.types.d.ts +30 -0
  45. package/dist/components/exams/exam-preview.types.js +62 -0
  46. package/dist/components/exams/exam-question-status.js +45 -1
  47. package/dist/components/exams/exam-template.utils.js +18 -1
  48. package/dist/components/exams/index.d.ts +1 -0
  49. package/dist/components/exams/index.js +19 -1
  50. package/dist/components/exams/rooms/StudentContestRoomsPageContainer.js +183 -1
  51. package/dist/components/exams/rooms/contest-rooms.utils.js +93 -1
  52. package/dist/components/exams/rooms/index.js +2 -1
  53. package/dist/components/exams/take/ExamTakingApiContext.js +25 -1
  54. package/dist/components/exams/take/ExamTakingPageContainer.js +955 -1
  55. package/dist/components/exams/take/GenericQuestionRenderer.js +14 -1
  56. package/dist/components/exams/take/components/QuestionRenderer.js +207 -1
  57. package/dist/components/exams/take/components/index.js +11 -1
  58. package/dist/components/exams/take/components/question-renderers/ArticlesViewer.js +8 -1
  59. package/dist/components/exams/take/components/question-renderers/MoversAnswerTheQuestionRenderer.js +30 -1
  60. package/dist/components/exams/take/components/question-renderers/MoversChooseAdjectiveRenderer.js +63 -1
  61. package/dist/components/exams/take/components/question-renderers/MoversChooseBestAnswerRenderer.js +136 -1
  62. package/dist/components/exams/take/components/question-renderers/MoversColoringRenderer.js +379 -1
  63. package/dist/components/exams/take/components/question-renderers/MoversCrossOutWordGroupRenderer.d.ts +20 -0
  64. package/dist/components/exams/take/components/question-renderers/MoversCrossOutWordGroupRenderer.js +141 -0
  65. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js +131 -1
  66. package/dist/components/exams/take/components/question-renderers/MoversGridFillRenderer.js +76 -1
  67. package/dist/components/exams/take/components/question-renderers/MoversLabelThePictureRenderer.js +68 -1
  68. package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +42 -1
  69. package/dist/components/exams/take/components/question-renderers/MoversMatchByWritingAnswerRenderer.js +131 -1
  70. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js +76 -1
  71. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.js +68 -1
  72. package/dist/components/exams/take/components/question-renderers/MoversReadingPassageRenderer.js +62 -1
  73. package/dist/components/exams/take/components/question-renderers/MoversTrueFalseRenderer.d.ts +1 -1
  74. package/dist/components/exams/take/components/question-renderers/MoversTrueFalseRenderer.js +51 -1
  75. package/dist/components/exams/take/components/question-renderers/MoversWordFillParagraphRenderer.js +171 -1
  76. package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +198 -1
  77. package/dist/components/exams/take/components/question-renderers/MoversWordOrderAndMatchGroupRenderer.d.ts +15 -0
  78. package/dist/components/exams/take/components/question-renderers/MoversWordOrderAndMatchGroupRenderer.js +36 -0
  79. package/dist/components/exams/take/components/question-renderers/MoversWordOrderingRenderer.js +92 -1
  80. package/dist/components/exams/take/components/question-renderers/MoversWriteSentencesRenderer.js +11 -1
  81. package/dist/components/exams/take/components/question-renderers/MoversWritingRenderer.js +56 -1
  82. package/dist/components/exams/take/components/question-renderers/index.d.ts +2 -0
  83. package/dist/components/exams/take/components/question-renderers/index.js +25 -1
  84. package/dist/components/exams/take/components/speaking/SpeakingAudioPlayer.js +85 -1
  85. package/dist/components/exams/take/components/speaking/SpeakingContentFrame.js +10 -1
  86. package/dist/components/exams/take/components/speaking/SpeakingExamLayout.js +15 -1
  87. package/dist/components/exams/take/components/speaking/SpeakingHeader.js +6 -1
  88. package/dist/components/exams/take/components/speaking/SpeakingInstructionBar.js +8 -1
  89. package/dist/components/exams/take/components/speaking/SpeakingMicButton.js +59 -1
  90. package/dist/components/exams/take/components/speaking/SpeakingNavButton.js +7 -1
  91. package/dist/components/exams/take/components/speaking/SpeakingPartBadge.js +5 -1
  92. package/dist/components/exams/take/components/speaking/SpeakingReadDisplayedContent.module.css +120 -0
  93. package/dist/components/exams/take/components/speaking/SpeakingRecordingPreview.js +73 -1
  94. package/dist/components/exams/take/components/speaking/SpeakingReportErrorButton.js +8 -1
  95. package/dist/components/exams/take/components/speaking/SpeakingSpontaneousQA.module.css +344 -0
  96. package/dist/components/exams/take/components/speaking/SpeakingVideoIntro.js +32 -1
  97. package/dist/components/exams/take/components/speaking/index.js +1 -1
  98. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseAnswerGroupRenderer.js +63 -1
  99. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseObjectsRenderer.js +95 -1
  100. package/dist/components/exams/take/components/speaking/renderers/SpeakingCompareImagesRenderer.js +35 -1
  101. package/dist/components/exams/take/components/speaking/renderers/SpeakingConversationRenderer.js +147 -1
  102. package/dist/components/exams/take/components/speaking/renderers/SpeakingCueCardRenderer.js +232 -1
  103. package/dist/components/exams/take/components/speaking/renderers/SpeakingDescribeImageRenderer.js +193 -1
  104. package/dist/components/exams/take/components/speaking/renderers/SpeakingDragObjectsRenderer.js +155 -1
  105. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.js +212 -1
  106. package/dist/components/exams/take/components/speaking/renderers/SpeakingInfoExchangeRenderer.js +77 -1
  107. package/dist/components/exams/take/components/speaking/renderers/SpeakingListenAndSpeakAnswerRenderer.js +64 -1
  108. package/dist/components/exams/take/components/speaking/renderers/SpeakingOddOneOutRenderer.js +69 -1
  109. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionListRenderer.js +64 -1
  110. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionRenderer.js +92 -1
  111. package/dist/components/exams/take/components/speaking/renderers/SpeakingReadDisplayedContentRenderer.js +202 -1
  112. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQARenderer.js +339 -1
  113. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQaGroupRenderer.d.ts +19 -0
  114. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQaGroupRenderer.js +76 -0
  115. package/dist/components/exams/take/components/speaking/renderers/SpeakingStoryImagesRenderer.js +56 -1
  116. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQACambridgeLayout.d.ts +24 -0
  117. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQACambridgeLayout.js +120 -0
  118. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQAInlineAudioPlayer.d.ts +8 -0
  119. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQAInlineAudioPlayer.js +94 -0
  120. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQASummerSkyAudioPlayer.d.ts +8 -0
  121. package/dist/components/exams/take/components/speaking/renderers/SpontaneousQASummerSkyAudioPlayer.js +101 -0
  122. package/dist/components/exams/take/components/speaking/renderers/index.d.ts +1 -0
  123. package/dist/components/exams/take/components/speaking/renderers/index.js +14 -1
  124. package/dist/components/exams/take/exam-taking.utils.d.ts +13 -0
  125. package/dist/components/exams/take/exam-taking.utils.js +203 -1
  126. package/dist/components/exams/take/hooks/index.js +2 -1
  127. package/dist/components/exams/take/hooks/useAnswerAutosave.js +71 -1
  128. package/dist/components/exams/take/hooks/useAttemptSubmit.js +38 -1
  129. package/dist/components/exams/take/hooks/useAutoSave.js +83 -1
  130. package/dist/components/exams/take/hooks/useExamCountdown.js +35 -1
  131. package/dist/components/exams/take/hooks/useExamTimer.js +97 -1
  132. package/dist/components/exams/take/hooks/useProctoringCamera.js +118 -1
  133. package/dist/components/exams/take/hooks/useProctoringSnapshot.js +76 -1
  134. package/dist/components/exams/take/hooks/useSpeakingConversationAudio.js +178 -1
  135. package/dist/components/exams/take/hooks/useSpeakingNavigation.js +51 -1
  136. package/dist/components/exams/take/hooks/useSpeakingRecorder.js +406 -1
  137. package/dist/components/exams/take/hooks/useSpeakingRendererSetup.js +136 -1
  138. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRecorder.d.ts +11 -0
  139. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRecorder.js +352 -0
  140. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRendererSetup.d.ts +42 -0
  141. package/dist/components/exams/take/hooks/useSpontaneousQaGroupRendererSetup.js +166 -0
  142. package/dist/components/exams/take/hooks/useToeicAudio.js +35 -1
  143. package/dist/components/exams/take/index.js +6 -1
  144. package/dist/components/exams/take/types/speaking-cue-card.types.js +1 -1
  145. package/dist/components/exams/take/types/speaking.types.js +7 -1
  146. package/dist/components/exams/take/types.js +4 -1
  147. package/dist/components/exams/take/utils/answer-transformers.js +452 -1
  148. package/dist/components/exams/take/utils/cambridge-yle-inline-speaking.d.ts +21 -0
  149. package/dist/components/exams/take/utils/cambridge-yle-inline-speaking.js +44 -0
  150. package/dist/components/exams/take/utils/coloring-assignments.js +40 -1
  151. package/dist/components/exams/take/utils/cross-out-word-group.transformer.d.ts +21 -0
  152. package/dist/components/exams/take/utils/cross-out-word-group.transformer.js +83 -0
  153. package/dist/components/exams/take/utils/question-transformers.d.ts +43 -2
  154. package/dist/components/exams/take/utils/question-transformers.js +1137 -1
  155. package/dist/components/features/exam-entry/entry-state-cards.js +19 -1
  156. package/dist/components/features/exam-entry/index.js +2 -1
  157. package/dist/components/features/exam-entry/themed/CambridgeYleWaitingRoom.js +121 -1
  158. package/dist/components/features/exam-entry/themed/ThemedWaitingRoom.js +37 -1
  159. package/dist/components/features/exam-entry/themed/ToeicWaitingRoom.js +15 -1
  160. package/dist/components/features/exam-entry/themed/cambridge-yle-waiting-parts.js +80 -1
  161. package/dist/components/features/exam-entry/themed/components/CloseButton.js +6 -1
  162. package/dist/components/features/exam-entry/themed/components/ExamInfoPanel.js +17 -1
  163. package/dist/components/features/exam-entry/themed/components/ModeSelector.js +6 -1
  164. package/dist/components/features/exam-entry/themed/components/StartButton.js +12 -1
  165. package/dist/components/features/exam-entry/themed/components/index.js +4 -1
  166. package/dist/components/features/exam-entry/themed/index.js +3 -1
  167. package/dist/components/index.d.ts +1 -0
  168. package/dist/components/index.js +43 -1
  169. package/dist/components/questions/_shared/config/question-types.config.js +362 -1
  170. package/dist/components/questions/_shared/constants/color-palette.js +21 -1
  171. package/dist/components/questions/_shared/hooks/useAnswerGroupQuestionGroup.js +105 -1
  172. package/dist/components/questions/_shared/hooks/useBasicQuestionGroup.js +222 -1
  173. package/dist/components/questions/_shared/hooks/useCompareImagesGroup.js +140 -1
  174. package/dist/components/questions/_shared/hooks/useImageQuestionGroup.js +123 -1
  175. package/dist/components/questions/_shared/hooks/useInfoExchangeGroup.js +50 -1
  176. package/dist/components/questions/_shared/hooks/useQuestionFormState.js +54 -1
  177. package/dist/components/questions/_shared/hooks/useQuestionInitialization.js +123 -1
  178. package/dist/components/questions/_shared/hooks/useQuestionListGroup.js +121 -1
  179. package/dist/components/questions/_shared/hooks/useQuestionOnChange.js +70 -1
  180. package/dist/components/questions/_shared/hooks/useSceneQuestionGroup.js +194 -1
  181. package/dist/components/questions/_shared/index.js +7 -1
  182. package/dist/components/questions/_shared/types/answer-the-question.type.js +1 -1
  183. package/dist/components/questions/_shared/types/arrange-letters-into-words.type.js +1 -1
  184. package/dist/components/questions/_shared/types/choose-correct-adjective.type.js +3 -1
  185. package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.d.ts +1 -0
  186. package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.js +1 -1
  187. package/dist/components/questions/_shared/types/color-region.config.js +1 -1
  188. package/dist/components/questions/_shared/types/cross-out-word-group.type.d.ts +2 -0
  189. package/dist/components/questions/_shared/types/cross-out-word-group.type.js +1 -1
  190. package/dist/components/questions/_shared/types/fill-in-blank.type.js +1 -1
  191. package/dist/components/questions/_shared/types/fill-missing-words-in-grid.type.js +1 -1
  192. package/dist/components/questions/_shared/types/gn-speaking-interview.type.js +1 -1
  193. package/dist/components/questions/_shared/types/index.d.ts +1 -0
  194. package/dist/components/questions/_shared/types/index.js +14 -1
  195. package/dist/components/questions/_shared/types/label-the-picture.type.js +1 -1
  196. package/dist/components/questions/_shared/types/listen-and-choose-from-answer-group.type.js +1 -1
  197. package/dist/components/questions/_shared/types/listen-and-choose-objects-in-scene.type.js +1 -1
  198. package/dist/components/questions/_shared/types/listen-and-drag-objects-into-scene.type.js +1 -1
  199. package/dist/components/questions/_shared/types/listen-and-speak-answer.type.js +1 -1
  200. package/dist/components/questions/_shared/types/listen-and-speak-compare-images.type.js +1 -1
  201. package/dist/components/questions/_shared/types/listen-and-speak-image-group.type.js +1 -1
  202. package/dist/components/questions/_shared/types/listen-and-speak-info-exchange.type.js +1 -1
  203. package/dist/components/questions/_shared/types/listen-and-speak-odd-one-out.type.js +3 -1
  204. package/dist/components/questions/_shared/types/listen-and-speak-question-list.type.js +1 -1
  205. package/dist/components/questions/_shared/types/listen-and-speak-with-story-images.type.js +3 -1
  206. package/dist/components/questions/_shared/types/listen-and-tick-answer.type.js +1 -1
  207. package/dist/components/questions/_shared/types/listening-drawline.type.js +1 -1
  208. package/dist/components/questions/_shared/types/look-and-choose-answer.type.js +1 -1
  209. package/dist/components/questions/_shared/types/look-picture-fill-word-hint.type.js +1 -1
  210. package/dist/components/questions/_shared/types/match-by-writing-answer.type.js +1 -1
  211. package/dist/components/questions/_shared/types/multiple-choice.type.d.ts +5 -0
  212. package/dist/components/questions/_shared/types/multiple-choice.type.js +1 -1
  213. package/dist/components/questions/_shared/types/question-group.type.js +11 -1
  214. package/dist/components/questions/_shared/types/read-and-color-objects.type.js +1 -1
  215. package/dist/components/questions/_shared/types/read-displayed-content.type.js +1 -1
  216. package/dist/components/questions/_shared/types/read-passage-and-answer-questions.type.js +1 -1
  217. package/dist/components/questions/_shared/types/speaking-describe-image.type.js +1 -1
  218. package/dist/components/questions/_shared/types/spontaneous-qa-group.type.d.ts +37 -0
  219. package/dist/components/questions/_shared/types/spontaneous-qa-group.type.js +1 -0
  220. package/dist/components/questions/_shared/types/spontaneous-qa.type.js +1 -1
  221. package/dist/components/questions/_shared/types/true-false-group.type.js +1 -1
  222. package/dist/components/questions/_shared/types/word-fill-paragraph-with-options.type.js +1 -1
  223. package/dist/components/questions/_shared/types/word-fill-paragraph.type.js +1 -1
  224. package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +20 -11
  225. package/dist/components/questions/_shared/types/word-fill-structured-form.type.js +1 -1
  226. package/dist/components/questions/_shared/types/word-order-and-match-group.type.d.ts +38 -0
  227. package/dist/components/questions/_shared/types/word-order-and-match-group.type.js +1 -0
  228. package/dist/components/questions/_shared/types/word-ordering.type.js +1 -1
  229. package/dist/components/questions/_shared/types/write-a-short-letter.type.js +1 -1
  230. package/dist/components/questions/_shared/types/write-correct-verb-form.type.js +3 -1
  231. package/dist/components/questions/_shared/types/write-sentences.type.js +1 -1
  232. package/dist/components/questions/_shared/types/write-short-paragraph.type.js +1 -1
  233. package/dist/components/questions/_shared/utils/answer-builder.js +79 -1
  234. package/dist/components/questions/_shared/utils/createColorRegionRegistration.js +39 -1
  235. package/dist/components/questions/_shared/utils/id-generator.js +3 -1
  236. package/dist/components/questions/_shared/utils/parseFillBlankStem.d.ts +30 -0
  237. package/dist/components/questions/_shared/utils/parseFillBlankStem.js +69 -0
  238. package/dist/components/questions/_shared/utils/question-validation.js +21 -1
  239. package/dist/components/questions/components/ColorNode.js +85 -1
  240. package/dist/components/questions/components/ColorRegionClient.js +545 -1
  241. package/dist/components/questions/components/ColorRegionCreator.js +420 -1
  242. package/dist/components/questions/components/ColorRegionNode.js +59 -1
  243. package/dist/components/questions/components/CreatorGuide.js +103 -1
  244. package/dist/components/questions/components/NameNode.js +26 -1
  245. package/dist/components/questions/components/QuestionBankOption.js +46 -1
  246. package/dist/components/questions/components/QuestionBasicInfoForm.js +9 -1
  247. package/dist/components/questions/components/QuestionCommonFields.js +33 -1
  248. package/dist/components/questions/components/QuestionSearchDropdown.js +258 -1
  249. package/dist/components/questions/components/QuestionTypeSelector.js +32 -1
  250. package/dist/components/questions/components/QuestionTypeSpecificForms.js +6 -1
  251. package/dist/components/questions/components/RegionNode.js +94 -1
  252. package/dist/components/questions/components/index.js +14 -1
  253. package/dist/components/questions/creator/QuestionCreator.js +90 -1
  254. package/dist/components/questions/creator/QuestionGroupCreator.js +119 -1
  255. package/dist/components/questions/creator/dedicated-component-router.js +79 -1
  256. package/dist/components/questions/creator/index.js +3 -1
  257. package/dist/components/questions/creator/question-type-registry.js +90 -1
  258. package/dist/components/questions/groups/ArticlesGroupCard.js +121 -1
  259. package/dist/components/questions/groups/BasicQuestionGroupCard.js +50 -1
  260. package/dist/components/questions/groups/DocumentGroupCard.js +114 -1
  261. package/dist/components/questions/groups/MatchAnswerGroupCard.js +25 -1
  262. package/dist/components/questions/index.d.ts +1 -0
  263. package/dist/components/questions/index.js +11 -1
  264. package/dist/components/questions/question-bank/EditQuestionBankDialog.d.ts +2 -0
  265. package/dist/components/questions/question-bank/EditQuestionBankDialog.js +114 -0
  266. package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +23 -0
  267. package/dist/components/questions/question-bank/QuestionEditorRenderer.js +75 -0
  268. package/dist/components/questions/question-bank/difficulty.d.ts +15 -0
  269. package/dist/components/questions/question-bank/difficulty.js +33 -0
  270. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +5 -0
  271. package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +101 -0
  272. package/dist/components/questions/question-bank/editor-adapters/index.d.ts +5 -0
  273. package/dist/components/questions/question-bank/editor-adapters/index.js +4 -0
  274. package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +6 -0
  275. package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +140 -0
  276. package/dist/components/questions/question-bank/editor-adapters/types.d.ts +1 -0
  277. package/dist/components/questions/question-bank/editor-adapters/types.js +1 -0
  278. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.d.ts +8 -0
  279. package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.js +6 -0
  280. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.d.ts +5 -0
  281. package/dist/components/questions/question-bank/editor-adapters/writing-adapters.js +114 -0
  282. package/dist/components/questions/question-bank/index.d.ts +4 -0
  283. package/dist/components/questions/question-bank/index.js +3 -0
  284. package/dist/components/questions/question-bank/types.d.ts +59 -0
  285. package/dist/components/questions/question-bank/types.js +1 -0
  286. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +37 -1
  287. package/dist/components/questions/types/answer-the-question/AnswerTheQuestionCreator.js +351 -1
  288. package/dist/components/questions/types/answer-the-question/register.js +67 -1
  289. package/dist/components/questions/types/answer-the-question/transform.js +36 -1
  290. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +141 -1
  291. package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsCreator.js +118 -1
  292. package/dist/components/questions/types/arrange-letters-into-words/index.js +2 -1
  293. package/dist/components/questions/types/arrange-letters-into-words/register.js +4 -1
  294. package/dist/components/questions/types/arrange-letters-into-words/transform.js +24 -1
  295. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +74 -1
  296. package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveCreator.js +169 -1
  297. package/dist/components/questions/types/choose-correct-adjective/index.js +2 -1
  298. package/dist/components/questions/types/choose-correct-adjective/register.js +55 -1
  299. package/dist/components/questions/types/choose-correct-adjective/transform.js +16 -1
  300. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +149 -1
  301. package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerCreator.js +568 -1
  302. package/dist/components/questions/types/choose-the-correct-answer/index.js +3 -1
  303. package/dist/components/questions/types/choose-the-correct-answer/normalize.d.ts +9 -0
  304. package/dist/components/questions/types/choose-the-correct-answer/normalize.js +88 -1
  305. package/dist/components/questions/types/choose-the-correct-answer/register.js +99 -1
  306. package/dist/components/questions/types/choose-the-correct-answer/transform.js +70 -1
  307. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +22 -1
  308. package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +163 -1
  309. package/dist/components/questions/types/choose-the-correct-answer-group/index.js +3 -1
  310. package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +94 -1
  311. package/dist/components/questions/types/choose-the-correct-answer-group/register.js +36 -1
  312. package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +55 -1
  313. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +27 -1
  314. package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +231 -1
  315. package/dist/components/questions/types/cross-out-word-group/index.js +5 -1
  316. package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.d.ts +1 -1
  317. package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.js +110 -1
  318. package/dist/components/questions/types/cross-out-word-group/register.js +36 -1
  319. package/dist/components/questions/types/cross-out-word-group/transform.js +67 -1
  320. package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +275 -1
  321. package/dist/components/questions/types/fill-in-blank/FillInBlankCreator.js +464 -1
  322. package/dist/components/questions/types/fill-in-blank/index.js +2 -1
  323. package/dist/components/questions/types/fill-in-blank/register.js +148 -1
  324. package/dist/components/questions/types/fill-in-blank/transform.js +88 -1
  325. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +117 -1
  326. package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridCreator.js +671 -1
  327. package/dist/components/questions/types/fill-missing-words-in-grid/index.js +2 -1
  328. package/dist/components/questions/types/fill-missing-words-in-grid/register.js +37 -1
  329. package/dist/components/questions/types/fill-missing-words-in-grid/transform.js +15 -1
  330. package/dist/components/questions/types/gn-speaking-interview/GNSpeakingInterviewCreator.js +262 -1
  331. package/dist/components/questions/types/gn-speaking-interview/register.js +121 -1
  332. package/dist/components/questions/types/gn-speaking-interview/transform.js +48 -1
  333. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingClient.js +16 -1
  334. package/dist/components/questions/types/image-object-matching/ImageObjectMatchingCreator.js +27 -1
  335. package/dist/components/questions/types/image-object-matching/index.js +2 -1
  336. package/dist/components/questions/types/image-object-matching/register.js +3 -1
  337. package/dist/components/questions/types/image-object-matching/transform.js +2 -1
  338. package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +102 -1
  339. package/dist/components/questions/types/label-the-picture/LabelThePictureCreator.js +344 -1
  340. package/dist/components/questions/types/label-the-picture/index.js +2 -1
  341. package/dist/components/questions/types/label-the-picture/register.js +54 -1
  342. package/dist/components/questions/types/label-the-picture/transform.js +28 -1
  343. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +78 -1
  344. package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupCreator.js +232 -1
  345. package/dist/components/questions/types/listen-and-choose-from-answer-group/index.js +2 -1
  346. package/dist/components/questions/types/listen-and-choose-from-answer-group/register.js +82 -1
  347. package/dist/components/questions/types/listen-and-choose-from-answer-group/transform.js +27 -1
  348. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneClient.js +70 -1
  349. package/dist/components/questions/types/listen-and-choose-objects-in-scene/ListenAndChooseObjectsInSceneCreator.js +386 -1
  350. package/dist/components/questions/types/listen-and-choose-objects-in-scene/index.js +2 -1
  351. package/dist/components/questions/types/listen-and-choose-objects-in-scene/register.js +100 -1
  352. package/dist/components/questions/types/listen-and-choose-objects-in-scene/transform.js +33 -1
  353. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneClient.js +106 -1
  354. package/dist/components/questions/types/listen-and-drag-objects-into-scene/ListenAndDragObjectsIntoSceneCreator.js +457 -1
  355. package/dist/components/questions/types/listen-and-drag-objects-into-scene/index.js +2 -1
  356. package/dist/components/questions/types/listen-and-drag-objects-into-scene/register.js +110 -1
  357. package/dist/components/questions/types/listen-and-drag-objects-into-scene/transform.js +35 -1
  358. package/dist/components/questions/types/listen-and-speak-answer/ArrowIndicator.js +8 -1
  359. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +22 -1
  360. package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerCreator.js +291 -1
  361. package/dist/components/questions/types/listen-and-speak-answer/index.js +2 -1
  362. package/dist/components/questions/types/listen-and-speak-answer/register.js +84 -1
  363. package/dist/components/questions/types/listen-and-speak-answer/transform.js +27 -1
  364. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +32 -1
  365. package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesCreator.js +295 -1
  366. package/dist/components/questions/types/listen-and-speak-compare-images/register.js +79 -1
  367. package/dist/components/questions/types/listen-and-speak-compare-images/transform.js +27 -1
  368. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +34 -1
  369. package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupCreator.js +285 -1
  370. package/dist/components/questions/types/listen-and-speak-image-group/register.js +81 -1
  371. package/dist/components/questions/types/listen-and-speak-image-group/transform.js +26 -1
  372. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +38 -1
  373. package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeCreator.js +385 -1
  374. package/dist/components/questions/types/listen-and-speak-info-exchange/register.js +87 -1
  375. package/dist/components/questions/types/listen-and-speak-info-exchange/transform.js +32 -1
  376. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +26 -1
  377. package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutCreator.js +247 -1
  378. package/dist/components/questions/types/listen-and-speak-odd-one-out/register.js +59 -1
  379. package/dist/components/questions/types/listen-and-speak-odd-one-out/transform.js +18 -1
  380. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +26 -1
  381. package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListCreator.js +256 -1
  382. package/dist/components/questions/types/listen-and-speak-question-list/register.js +81 -1
  383. package/dist/components/questions/types/listen-and-speak-question-list/transform.js +26 -1
  384. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +26 -1
  385. package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesCreator.js +230 -1
  386. package/dist/components/questions/types/listen-and-speak-with-story-images/register.js +56 -1
  387. package/dist/components/questions/types/listen-and-speak-with-story-images/transform.js +16 -1
  388. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerClient.js +72 -1
  389. package/dist/components/questions/types/look-picture-choose-correct-answer/LookPictureChooseCorrectAnswerCreator.js +230 -1
  390. package/dist/components/questions/types/look-picture-choose-correct-answer/index.js +1 -1
  391. package/dist/components/questions/types/look-picture-choose-correct-answer/register.js +66 -1
  392. package/dist/components/questions/types/look-picture-choose-correct-answer/transform.js +42 -1
  393. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerClient.js +96 -1
  394. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/LookPictureFillBlankChooseAnswerCreator.js +238 -1
  395. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/index.js +2 -1
  396. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/register.js +76 -1
  397. package/dist/components/questions/types/look-picture-fill-blank-choose-answer/transform.js +19 -1
  398. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintClient.js +134 -1
  399. package/dist/components/questions/types/look-picture-fill-word-hint/LookPictureFillWordHintCreator.js +617 -1
  400. package/dist/components/questions/types/look-picture-fill-word-hint/index.js +2 -1
  401. package/dist/components/questions/types/look-picture-fill-word-hint/register.js +82 -1
  402. package/dist/components/questions/types/look-picture-fill-word-hint/transform.js +29 -1
  403. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +38 -1
  404. package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerCreator.js +359 -1
  405. package/dist/components/questions/types/match-by-writing-answer/index.js +3 -1
  406. package/dist/components/questions/types/match-by-writing-answer/register.js +58 -1
  407. package/dist/components/questions/types/match-by-writing-answer/transform.js +61 -1
  408. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsClient.js +16 -1
  409. package/dist/components/questions/types/read-and-color-objects/ReadAndColorObjectsCreator.js +23 -1
  410. package/dist/components/questions/types/read-and-color-objects/index.js +2 -1
  411. package/dist/components/questions/types/read-and-color-objects/register.js +3 -1
  412. package/dist/components/questions/types/read-and-color-objects/transform.js +36 -1
  413. package/dist/components/questions/types/read-displayed-content/ReadDisplayedContentCreator.js +125 -1
  414. package/dist/components/questions/types/read-displayed-content/register.js +64 -1
  415. package/dist/components/questions/types/read-displayed-content/transform.js +12 -1
  416. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +65 -1
  417. package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsCreator.js +511 -1
  418. package/dist/components/questions/types/read-passage-and-answer-questions/index.js +2 -1
  419. package/dist/components/questions/types/read-passage-and-answer-questions/register.js +58 -1
  420. package/dist/components/questions/types/read-passage-and-answer-questions/transform.js +28 -1
  421. package/dist/components/questions/types/speaking-conversation/SpeakingConversationCreator.js +373 -1
  422. package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +41 -1
  423. package/dist/components/questions/types/speaking-conversation/register.js +110 -1
  424. package/dist/components/questions/types/speaking-conversation/transform.js +34 -1
  425. package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardCreator.js +74 -1
  426. package/dist/components/questions/types/speaking-cue-card/register.js +52 -1
  427. package/dist/components/questions/types/speaking-cue-card/transform.js +12 -1
  428. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +10 -1
  429. package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageCreator.js +161 -1
  430. package/dist/components/questions/types/speaking-describe-image/index.js +2 -1
  431. package/dist/components/questions/types/speaking-describe-image/register.js +69 -1
  432. package/dist/components/questions/types/speaking-describe-image/transform.js +16 -1
  433. package/dist/components/questions/types/spontaneous-qa/SpontaneousQACreator.js +234 -1
  434. package/dist/components/questions/types/spontaneous-qa/register.js +93 -1
  435. package/dist/components/questions/types/spontaneous-qa/transform.js +34 -1
  436. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.d.ts +2 -0
  437. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +9 -0
  438. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.d.ts +2 -0
  439. package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +179 -0
  440. package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.d.ts +5 -0
  441. package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.js +43 -0
  442. package/dist/components/questions/types/spontaneous-qa-group/flatten.d.ts +14 -0
  443. package/dist/components/questions/types/spontaneous-qa-group/flatten.js +69 -0
  444. package/dist/components/questions/types/spontaneous-qa-group/index.d.ts +2 -0
  445. package/dist/components/questions/types/spontaneous-qa-group/index.js +2 -0
  446. package/dist/components/questions/types/spontaneous-qa-group/register.d.ts +2 -0
  447. package/dist/components/questions/types/spontaneous-qa-group/register.js +139 -0
  448. package/dist/components/questions/types/spontaneous-qa-group/transform.d.ts +2 -0
  449. package/dist/components/questions/types/spontaneous-qa-group/transform.js +52 -0
  450. package/dist/components/questions/types/true-false/TrueFalseClient.js +75 -1
  451. package/dist/components/questions/types/true-false/TrueFalseCreator.js +244 -1
  452. package/dist/components/questions/types/true-false/index.js +2 -1
  453. package/dist/components/questions/types/true-false/register.js +77 -1
  454. package/dist/components/questions/types/true-false/transform.js +32 -1
  455. package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +25 -1
  456. package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +129 -1
  457. package/dist/components/questions/types/true-false-group/index.js +5 -1
  458. package/dist/components/questions/types/true-false-group/map-true-false-group-data.js +69 -1
  459. package/dist/components/questions/types/true-false-group/register.js +36 -1
  460. package/dist/components/questions/types/true-false-group/transform.js +43 -1
  461. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +233 -1
  462. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphCreator.js +631 -1
  463. package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphWrapper.js +28 -1
  464. package/dist/components/questions/types/word-fill-paragraph/index.js +2 -1
  465. package/dist/components/questions/types/word-fill-paragraph/register.js +136 -1
  466. package/dist/components/questions/types/word-fill-paragraph/transform.js +56 -1
  467. package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.js +86 -1
  468. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +246 -1
  469. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.d.ts +2 -0
  470. package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +484 -1
  471. package/dist/components/questions/types/word-fill-structured-form/index.js +3 -1
  472. package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.js +113 -1
  473. package/dist/components/questions/types/word-fill-structured-form/register.js +36 -1
  474. package/dist/components/questions/types/word-fill-structured-form/transform.js +77 -1
  475. package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.js +110 -1
  476. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.d.ts +3 -0
  477. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +190 -0
  478. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.d.ts +3 -0
  479. package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupCreator.js +182 -0
  480. package/dist/components/questions/types/word-order-and-match-group/index.d.ts +4 -0
  481. package/dist/components/questions/types/word-order-and-match-group/index.js +4 -0
  482. package/dist/components/questions/types/word-order-and-match-group/register.d.ts +2 -0
  483. package/dist/components/questions/types/word-order-and-match-group/register.js +121 -0
  484. package/dist/components/questions/types/word-order-and-match-group/transform.d.ts +2 -0
  485. package/dist/components/questions/types/word-order-and-match-group/transform.js +70 -0
  486. package/dist/components/questions/types/word-ordering/WordOrderingClient.js +84 -1
  487. package/dist/components/questions/types/word-ordering/WordOrderingCreator.js +192 -1
  488. package/dist/components/questions/types/word-ordering/index.js +2 -1
  489. package/dist/components/questions/types/word-ordering/register.js +46 -1
  490. package/dist/components/questions/types/word-ordering/transform.js +24 -1
  491. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterClient.js +99 -1
  492. package/dist/components/questions/types/write-a-short-letter/WriteAShortLetterCreator.js +320 -1
  493. package/dist/components/questions/types/write-a-short-letter/index.js +2 -1
  494. package/dist/components/questions/types/write-a-short-letter/register.js +68 -1
  495. package/dist/components/questions/types/write-a-short-letter/transform.js +25 -1
  496. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +61 -1
  497. package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormCreator.js +196 -1
  498. package/dist/components/questions/types/write-correct-verb-form/index.js +2 -1
  499. package/dist/components/questions/types/write-correct-verb-form/register.js +62 -1
  500. package/dist/components/questions/types/write-correct-verb-form/transform.js +17 -1
  501. package/dist/components/questions/types/write-sentences/WriteSentencesClient.js +22 -1
  502. package/dist/components/questions/types/write-sentences/WriteSentencesCreator.js +174 -1
  503. package/dist/components/questions/types/write-sentences/index.js +2 -1
  504. package/dist/components/questions/types/write-sentences/register.js +58 -1
  505. package/dist/components/questions/types/write-sentences/transform.js +28 -1
  506. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphClient.js +96 -1
  507. package/dist/components/questions/types/write-short-paragraph/WriteShortParagraphCreator.js +161 -1
  508. package/dist/components/questions/types/write-short-paragraph/index.js +2 -1
  509. package/dist/components/questions/types/write-short-paragraph/register.js +4 -1
  510. package/dist/components/questions/types/write-short-paragraph/transform.js +21 -1
  511. package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.js +11 -1
  512. package/dist/components/questions/viewer/CrossOutWordGroupViewer.js +8 -1
  513. package/dist/components/questions/viewer/QuestionGroupViewer.js +36 -1
  514. package/dist/components/questions/viewer/QuestionViewer.js +692 -1
  515. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.d.ts +2 -1
  516. package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +82 -1
  517. package/dist/components/questions/viewer/TrueFalseGroupViewer.js +11 -1
  518. package/dist/components/questions/viewer/WordFillStructuredFormViewer.js +14 -1
  519. package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.d.ts +3 -1
  520. package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.js +95 -1
  521. package/dist/components/questions/viewer/index.js +8 -1
  522. package/dist/components/results/ResultReviewPageContainer.js +220 -1
  523. package/dist/components/results/ReviewQuestionRenderer.js +55 -1
  524. package/dist/components/results/hooks/useResultReviewPolling.js +76 -1
  525. package/dist/components/results/index.js +22 -1
  526. package/dist/components/results/renderers/QuestionExplanations.js +19 -1
  527. package/dist/components/results/renderers/ReviewChooseAdjectiveRenderer.js +94 -1
  528. package/dist/components/results/renderers/ReviewChooseBestAnswerRenderer.js +75 -1
  529. package/dist/components/results/renderers/ReviewColoringRenderer.js +110 -1
  530. package/dist/components/results/renderers/ReviewListenAndWriteRenderer.js +48 -1
  531. package/dist/components/results/renderers/ReviewListenChooseAnswerGroupRenderer.js +87 -1
  532. package/dist/components/results/renderers/ReviewListenChooseObjectsRenderer.js +104 -1
  533. package/dist/components/results/renderers/ReviewListenDragObjectsRenderer.js +123 -1
  534. package/dist/components/results/renderers/ReviewListeningHeader.js +104 -1
  535. package/dist/components/results/renderers/ReviewSpeakingAIPanel.js +116 -1
  536. package/dist/components/results/renderers/ReviewSpeakingMedia.js +48 -1
  537. package/dist/components/results/renderers/ReviewSpeakingQuestionItem.js +42 -1
  538. package/dist/components/results/renderers/ReviewSpeakingRenderer.js +12 -1
  539. package/dist/components/results/renderers/ReviewSpeakingRenderer.types.js +85 -1
  540. package/dist/components/results/renderers/review-question-body-dedicated.js +104 -1
  541. package/dist/components/results/renderers/review-question-body-movers.js +148 -1
  542. package/dist/components/results/renderers/review-speaking-map.js +226 -1
  543. package/dist/components/results/renderers/review-spontaneous-qa-group.d.ts +4 -0
  544. package/dist/components/results/renderers/review-spontaneous-qa-group.js +74 -0
  545. package/dist/components/results/report/BadgeTitle.js +5 -1
  546. package/dist/components/results/report/ExamSkillRow.js +20 -1
  547. package/dist/components/results/report/OceanEduExamReport.js +58 -1
  548. package/dist/components/results/report/OceanEduSpeakingReport.js +62 -1
  549. package/dist/components/results/report/OverallAssessmentSection.js +17 -1
  550. package/dist/components/results/report/ResultErrorState.js +18 -1
  551. package/dist/components/results/report/ResultLoadingState.js +10 -1
  552. package/dist/components/results/report/ResultNotPublicState.js +27 -1
  553. package/dist/components/results/report/SpeakingReportParts.js +14 -1
  554. package/dist/components/results/report/SpeakingReportShared.js +86 -1
  555. package/dist/components/results/report/SpeakingRubricSection.js +171 -1
  556. package/dist/components/results/report/speaking-report.utils.js +198 -1
  557. package/dist/components/results/result-review.utils.js +6 -1
  558. package/dist/components/results/review-data.js +222 -1
  559. package/dist/components/results/review-renderer.utils.js +97 -1
  560. package/dist/components/results/review-status.utils.js +36 -1
  561. package/dist/components/results/review-types.js +1 -1
  562. package/dist/components/results/speaking/SpeakingResultAudioPlayer.js +77 -1
  563. package/dist/components/results/speaking/SpeakingReviewResult.js +48 -1
  564. package/dist/components/results/utils/review-score.utils.js +72 -1
  565. package/dist/components/results/utils/speaking-summary.js +224 -1
  566. package/dist/components/results/utils/transform-speaking-review.js +183 -1
  567. package/dist/components/shared/RichTextEditor.d.ts +9 -0
  568. package/dist/components/shared/RichTextEditor.js +47 -0
  569. package/dist/components/shared/audio/SpeakingAudioPlayer.js +100 -1
  570. package/dist/components/themes/cambridge-yle/CambridgeYleAudioPlayer.js +140 -1
  571. package/dist/components/themes/cambridge-yle/CambridgeYleBottomNav.js +10 -1
  572. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.d.ts +1 -1
  573. package/dist/components/themes/cambridge-yle/CambridgeYleExamLayout.js +18 -1
  574. package/dist/components/themes/cambridge-yle/CambridgeYleExampleText.js +11 -1
  575. package/dist/components/themes/cambridge-yle/CambridgeYleHeader.js +11 -1
  576. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.d.ts +2 -1
  577. package/dist/components/themes/cambridge-yle/CambridgeYleInstructionBanner.js +19 -1
  578. package/dist/components/themes/cambridge-yle/CambridgeYleNavButton.js +13 -1
  579. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.d.ts +1 -1
  580. package/dist/components/themes/cambridge-yle/CambridgeYlePartBanner.js +3 -1
  581. package/dist/components/themes/cambridge-yle/CambridgeYleProgressBar.js +6 -1
  582. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCard.js +5 -1
  583. package/dist/components/themes/cambridge-yle/CambridgeYleQuestionCardFullWidth.js +9 -1
  584. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.d.ts +2 -1
  585. package/dist/components/themes/cambridge-yle/CambridgeYleSidebar.js +61 -1
  586. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.d.ts +1 -1
  587. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +25 -1
  588. package/dist/components/themes/cambridge-yle/index.js +13 -1
  589. package/dist/components/themes/english-certification/EcAnswerTheQuestion.js +25 -1
  590. package/dist/components/themes/english-certification/EcMatchByWritingAnswer.js +89 -1
  591. package/dist/components/themes/english-certification/EcWordFillParagraph.js +56 -1
  592. package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +192 -1
  593. package/dist/components/themes/english-certification/EcWritingTask.js +60 -1
  594. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +108 -1
  595. package/dist/components/themes/english-certification/EnglishCertificationBrand.js +11 -1
  596. package/dist/components/themes/english-certification/EnglishCertificationExamLayout.js +34 -1
  597. package/dist/components/themes/english-certification/EnglishCertificationFlagButton.js +15 -1
  598. package/dist/components/themes/english-certification/EnglishCertificationFooterBar.js +19 -1
  599. package/dist/components/themes/english-certification/EnglishCertificationGroupedQuestion.js +166 -1
  600. package/dist/components/themes/english-certification/EnglishCertificationHeader.js +31 -1
  601. package/dist/components/themes/english-certification/EnglishCertificationInstructionBanner.js +79 -1
  602. package/dist/components/themes/english-certification/EnglishCertificationNavigationPanel.js +71 -1
  603. package/dist/components/themes/english-certification/EnglishCertificationOptionSelector.js +79 -1
  604. package/dist/components/themes/english-certification/EnglishCertificationPartHeader.js +47 -1
  605. package/dist/components/themes/english-certification/EnglishCertificationPassagePanel.js +77 -1
  606. package/dist/components/themes/english-certification/EnglishCertificationQuestionCard.js +25 -1
  607. package/dist/components/themes/english-certification/EnglishCertificationQuestionItem.js +36 -1
  608. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +81 -1
  609. package/dist/components/themes/english-certification/EnglishCertificationReadingSection.js +95 -1
  610. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestion.js +18 -1
  611. package/dist/components/themes/english-certification/EnglishCertificationSingleQuestionList.js +32 -1
  612. package/dist/components/themes/english-certification/english-cert-scroll.js +163 -1
  613. package/dist/components/themes/english-certification/english-certification-theme.js +58 -1
  614. package/dist/components/themes/english-certification/grouped-question-utils.js +243 -1
  615. package/dist/components/themes/english-certification/index.js +24 -1
  616. package/dist/components/themes/index.js +25 -1
  617. package/dist/components/themes/summer-sky/SummerSkyAudioPlayer.js +170 -1
  618. package/dist/components/themes/summer-sky/SummerSkyExitModal.js +21 -1
  619. package/dist/components/themes/summer-sky/SummerSkyLayout.js +221 -1
  620. package/dist/components/themes/summer-sky/SummerSkySubmitModal.js +18 -1
  621. package/dist/components/themes/summer-sky/SummerSkyWaitingRoom.js +193 -1
  622. package/dist/components/themes/types.js +1 -1
  623. package/dist/components/ui/alert-dialog.js +26 -1
  624. package/dist/components/ui/alert.js +22 -1
  625. package/dist/components/ui/avatar.js +12 -1
  626. package/dist/components/ui/badge.js +38 -1
  627. package/dist/components/ui/button.js +35 -1
  628. package/dist/components/ui/calendar.js +76 -1
  629. package/dist/components/ui/card.js +16 -1
  630. package/dist/components/ui/carousel.js +91 -1
  631. package/dist/components/ui/checkbox.js +9 -1
  632. package/dist/components/ui/collapsible.js +13 -1
  633. package/dist/components/ui/command.js +34 -1
  634. package/dist/components/ui/confirm-dialog.js +49 -1
  635. package/dist/components/ui/dialog.js +23 -1
  636. package/dist/components/ui/drawer.js +35 -1
  637. package/dist/components/ui/dropdown-menu.js +33 -1
  638. package/dist/components/ui/file-upload.js +155 -1
  639. package/dist/components/ui/form.js +62 -1
  640. package/dist/components/ui/hover-card.js +10 -1
  641. package/dist/components/ui/image-preview.js +29 -1
  642. package/dist/components/ui/input.js +8 -1
  643. package/dist/components/ui/label.js +9 -1
  644. package/dist/components/ui/language-switcher.js +15 -1
  645. package/dist/components/ui/multi-select.js +90 -1
  646. package/dist/components/ui/points-input.js +33 -1
  647. package/dist/components/ui/popover.js +26 -1
  648. package/dist/components/ui/progress.js +16 -1
  649. package/dist/components/ui/radio-group.js +12 -1
  650. package/dist/components/ui/scroll-area.js +11 -1
  651. package/dist/components/ui/select.js +38 -1
  652. package/dist/components/ui/separator.js +8 -1
  653. package/dist/components/ui/sheet.js +40 -1
  654. package/dist/components/ui/single-select.js +76 -1
  655. package/dist/components/ui/skeleton.js +6 -1
  656. package/dist/components/ui/switch.js +8 -1
  657. package/dist/components/ui/table.js +20 -1
  658. package/dist/components/ui/tabs.js +17 -1
  659. package/dist/components/ui/textarea.js +8 -1
  660. package/dist/components/ui/tooltip.js +11 -1
  661. package/dist/index.d.ts +3 -0
  662. package/dist/index.js +24 -1
  663. package/dist/shared/constants/ApiConstant.d.ts +1 -0
  664. package/dist/shared/constants/ApiConstant.js +278 -1
  665. package/dist/shared/constants/QueryKeyConstant.js +112 -1
  666. package/dist/shared/constants/exam-level.enum.js +41 -1
  667. package/dist/shared/constants/landings/placement-test.constants.js +431 -1
  668. package/dist/shared/constants/question-skills.js +277 -1
  669. package/dist/shared/constants/routes.js +81 -1
  670. package/dist/shared/index.js +10 -1
  671. package/dist/shared/lib/hooks/index.js +10 -1
  672. package/dist/shared/lib/hooks/useAlertDialog.js +57 -1
  673. package/dist/shared/lib/hooks/useAudioPlayCounter.js +30 -1
  674. package/dist/shared/lib/hooks/useAudioPreview.js +81 -1
  675. package/dist/shared/lib/hooks/useAudioUpload.js +24 -1
  676. package/dist/shared/lib/hooks/useConfirmDialog.js +89 -1
  677. package/dist/shared/lib/hooks/useDebouncedCallback.js +32 -1
  678. package/dist/shared/lib/hooks/useDelayedAutoPlay.js +12 -1
  679. package/dist/shared/lib/hooks/useFileUpload.js +24 -1
  680. package/dist/shared/lib/hooks/useImageUrl.js +5 -1
  681. package/dist/shared/lib/hooks/usePresignedFileUrl.js +108 -1
  682. package/dist/shared/lib/hooks/useReactHookForm.js +31 -1
  683. package/dist/shared/lib/hooks/useToast.js +62 -1
  684. package/dist/shared/lib/html-content.js +22 -1
  685. package/dist/shared/lib/i18n/index.js +54 -1
  686. package/dist/shared/lib/i18n/messages/en/admin.d.ts +11 -4
  687. package/dist/shared/lib/i18n/messages/en/admin.js +2111 -1
  688. package/dist/shared/lib/i18n/messages/en/auth.js +86 -1
  689. package/dist/shared/lib/i18n/messages/en/common.js +140 -1
  690. package/dist/shared/lib/i18n/messages/en/file-upload.js +18 -1
  691. package/dist/shared/lib/i18n/messages/en/student.js +133 -1
  692. package/dist/shared/lib/i18n/messages/en/terms.js +37 -1
  693. package/dist/shared/lib/i18n/messages/en.d.ts +11 -4
  694. package/dist/shared/lib/i18n/messages/en.js +15 -1
  695. package/dist/shared/lib/i18n/messages/vi/admin.d.ts +11 -4
  696. package/dist/shared/lib/i18n/messages/vi/admin.js +2111 -1
  697. package/dist/shared/lib/i18n/messages/vi/auth.js +86 -1
  698. package/dist/shared/lib/i18n/messages/vi/common.js +140 -1
  699. package/dist/shared/lib/i18n/messages/vi/file-upload.js +18 -1
  700. package/dist/shared/lib/i18n/messages/vi/student.js +133 -1
  701. package/dist/shared/lib/i18n/messages/vi/terms.js +37 -1
  702. package/dist/shared/lib/i18n/messages/vi.d.ts +11 -4
  703. package/dist/shared/lib/i18n/messages/vi.js +15 -1
  704. package/dist/shared/lib/i18n/types.js +1 -1
  705. package/dist/shared/lib/stores/examQuestionStore.js +212 -1
  706. package/dist/shared/lib/stores/examTakingStore.js +240 -1
  707. package/dist/shared/lib/stores/gradingTransientStore.js +39 -1
  708. package/dist/shared/lib/stores/localeStore.js +10 -1
  709. package/dist/shared/lib/themes/config/starters.config.js +71 -1
  710. package/dist/shared/lib/themes/index.js +49 -1
  711. package/dist/shared/lib/themes/types.js +2 -1
  712. package/dist/shared/lib/toast.js +43 -1
  713. package/dist/shared/lib/utils/public-page.js +44 -1
  714. package/dist/shared/lib/utils/question-reverse-transform.js +438 -1
  715. package/dist/shared/lib/utils/question-transform-types.js +1 -1
  716. package/dist/shared/lib/utils/question-transform-validation.js +194 -1
  717. package/dist/shared/lib/utils/question-transform.js +199 -1
  718. package/dist/shared/lib/utils.js +168 -1
  719. package/dist/shared/lib/validation/choose-correct-answer.validation.js +111 -1
  720. package/dist/shared/lib/validation/label-the-picture.validation.js +19 -1
  721. package/dist/shared/lib/validation/listen-and-choose-from-answer-group.validation.js +46 -1
  722. package/dist/shared/lib/validation/listen-and-choose-objects-in-scene.validation.js +21 -1
  723. package/dist/shared/lib/validation/listen-and-drag-objects-into-scene.validation.js +34 -1
  724. package/dist/shared/lib/validation/listen-and-speak-answer.validation.js +40 -1
  725. package/dist/shared/lib/validation/listen-and-speak-compare-images.validation.js +45 -1
  726. package/dist/shared/lib/validation/listen-and-speak-image-group.validation.js +19 -1
  727. package/dist/shared/lib/validation/listen-and-speak-info-exchange.validation.js +39 -1
  728. package/dist/shared/lib/validation/listen-and-speak-odd-one-out.validation.js +32 -1
  729. package/dist/shared/lib/validation/listen-and-speak-question-list.validation.js +19 -1
  730. package/dist/shared/lib/validation/listen-and-speak-with-story-images.validation.js +28 -1
  731. package/dist/shared/lib/validation/look-picture-choose-correct-answer.validation.js +12 -1
  732. package/dist/shared/lib/validation/look-picture-fill-blank-choose-answer.validation.js +47 -1
  733. package/dist/shared/lib/validation/read-and-color-objects.validation.js +29 -1
  734. package/dist/shared/lib/validation/read-displayed-content.validation.js +28 -1
  735. package/dist/shared/lib/validation/speaking-conversation.validation.js +75 -1
  736. package/dist/shared/lib/validation/speaking-describe-image.validation.js +31 -1
  737. package/dist/shared/lib/validation/spontaneous-qa.validation.js +48 -1
  738. package/dist/shared/lib/validation/word-fill-paragraph-default.validation.js +38 -1
  739. package/dist/shared/lib/validation/word-fill-paragraph-with-options.validation.js +39 -1
  740. package/dist/shared/lib/validation/word-fill-paragraph.validation.js +43 -1
  741. package/dist/shared/lib/validation/word-ordering.validation.js +33 -1
  742. package/dist/shared/types/branch.types.js +6 -1
  743. package/dist/shared/types/common.types.js +49 -1
  744. package/dist/shared/types/entities/exam-schedule.types.js +5 -1
  745. package/dist/shared/types/entities/exam.types.js +1 -1
  746. package/dist/shared/types/entities/question.types.js +4 -1
  747. package/dist/shared/types/entities/result.types.js +4 -1
  748. package/dist/shared/types/entities/user.types.js +4 -1
  749. package/dist/shared/types/exam-taking.types.js +2 -1
  750. package/dist/shared/types/history.types.js +34 -1
  751. package/dist/shared/types/index.js +1 -1
  752. package/dist/shared/types/questions/choose-correct-adjective.js +4 -1
  753. package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +1 -0
  754. package/dist/shared/types/questions/choose-the-correct-answer-group.js +1 -1
  755. package/dist/shared/types/questions/choose-the-correct-answer.js +9 -1
  756. package/dist/shared/types/questions/cross-out-word-group.d.ts +2 -0
  757. package/dist/shared/types/questions/cross-out-word-group.js +1 -1
  758. package/dist/shared/types/questions/fill-missing-words-in-grid.js +11 -1
  759. package/dist/shared/types/questions/index.d.ts +1 -0
  760. package/dist/shared/types/questions/index.js +46 -1
  761. package/dist/shared/types/questions/listen-and-speak-answer.js +1 -1
  762. package/dist/shared/types/questions/listen-and-speak-compare-images.js +1 -1
  763. package/dist/shared/types/questions/listen-and-speak-image-group.js +1 -1
  764. package/dist/shared/types/questions/listen-and-speak-info-exchange.js +3 -1
  765. package/dist/shared/types/questions/listen-and-speak-odd-one-out.js +3 -1
  766. package/dist/shared/types/questions/listen-and-speak-question-list.js +1 -1
  767. package/dist/shared/types/questions/listen-and-speak-with-story-images.js +3 -1
  768. package/dist/shared/types/questions/look-picture-choose-correct-answer.js +5 -1
  769. package/dist/shared/types/questions/look-picture-fill-blank-choose-answer.js +9 -1
  770. package/dist/shared/types/questions/look-picture-fill-word-hint.js +7 -1
  771. package/dist/shared/types/questions/read-displayed-content.js +1 -1
  772. package/dist/shared/types/questions/speaking-conversation.js +7 -1
  773. package/dist/shared/types/questions/speaking-describe-image.js +1 -1
  774. package/dist/shared/types/questions/spontaneous-qa.js +1 -1
  775. package/dist/shared/types/questions/word-order-and-match-group.d.ts +33 -0
  776. package/dist/shared/types/questions/word-order-and-match-group.js +1 -0
  777. package/dist/shared/types/questions/write-correct-verb-form.js +12 -1
  778. package/dist/shared/types/role.types.js +1 -1
  779. package/dist/shared/types/structure-management.js +28 -1
  780. package/dist/shared/types/student.types.js +57 -1
  781. package/dist/shared/types/teacher-dashboard-rooms.js +2 -1
  782. package/package.json +184 -166
  783. package/dist/mcp/config.d.ts +0 -12
  784. package/dist/mcp/config.js +0 -1
  785. package/dist/mcp/http-client.d.ts +0 -6
  786. package/dist/mcp/http-client.js +0 -1
  787. package/dist/mcp/index.d.ts +0 -6
  788. package/dist/mcp/index.js +0 -2
  789. package/dist/mcp/tools/_helpers.d.ts +0 -4
  790. package/dist/mcp/tools/_helpers.js +0 -1
  791. package/dist/mcp/tools/exams.d.ts +0 -2
  792. package/dist/mcp/tools/exams.js +0 -1
  793. package/dist/mcp/tools/index.d.ts +0 -2
  794. package/dist/mcp/tools/index.js +0 -1
  795. package/dist/mcp/tools/results.d.ts +0 -2
  796. package/dist/mcp/tools/results.js +0 -1
@@ -4,6 +4,7 @@ interface CambridgeYleInstructionBannerProps {
4
4
  hasExample?: boolean;
5
5
  children?: React.ReactNode;
6
6
  isReviewMode?: boolean;
7
+ compact?: boolean;
7
8
  }
8
- export default function CambridgeYleInstructionBanner({ instruction, instructions, hasExample, children, isReviewMode, }: CambridgeYleInstructionBannerProps): import("react").JSX.Element;
9
+ export default function CambridgeYleInstructionBanner({ instruction, instructions, hasExample, children, isReviewMode, compact, }: CambridgeYleInstructionBannerProps): import("react").JSX.Element;
9
10
  export {};
@@ -1 +1,19 @@
1
- "use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{Info as t,Megaphone as l}from"lucide-react";export default function a({instruction:a,instructions:i,hasExample:r=!1,children:n,isReviewMode:d=!1}){if(d)return null;const c=i&&i.length>0;return s("div",{className:"shrink-0 space-y-3 px-2 sm:px-6 mb-2 sm:mb-4",children:[a&&s("div",{className:"flex w-full items-center gap-4 sm:gap-5 rounded-[24px] bg-[#F8FBFF] border-2 border-dashed border-blue-300 px-5 py-4 transition-all hover:bg-blue-50/50",children:[e("div",{className:"flex items-center justify-center w-12 h-12 sm:w-14 sm:h-14 rounded-[16px] bg-[#0070FF] shadow-[4px_4px_0px_rgba(191,219,254,1)] shrink-0 -rotate-6 transition-transform hover:rotate-0",children:e(l,{className:"h-6 w-6 sm:h-7 sm:w-7 text-white",strokeWidth:2.5})}),e("div",{className:"flex-1 flex flex-col justify-center",children:s("p",{className:"text-[15px] sm:text-[18px] font-black uppercase tracking-wide text-[#002868] leading-snug",style:{fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif'},children:[a,r&&e("span",{className:"inline-block text-[#0070FF] ml-2 text-[14px] sm:text-[16px] font-bold tracking-normal bg-blue-100 px-3 py-0.5 rounded-full align-middle -mt-1",children:"THERE IS ONE EXAMPLE"})]})})]}),n,c&&e("div",{className:"rounded-lg border border-blue-200 bg-white p-4 shadow-sm",children:s("div",{className:"space-y-3",children:[s("h4",{className:"flex items-center gap-2 font-semibold text-blue-900",children:[e(t,{className:"h-4 w-4"}),"Instructions"]}),e("ol",{className:"list-inside list-decimal space-y-1.5 text-sm text-gray-700",children:i.map((s,t)=>e("li",{className:"leading-relaxed",children:s},t))})]})})]})}
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Info, Megaphone } from 'lucide-react';
4
+ export default function CambridgeYleInstructionBanner({ instruction, instructions, hasExample = false, children, isReviewMode = false, compact = false, }) {
5
+ if (isReviewMode)
6
+ return null;
7
+ const hasInstructionsList = instructions && instructions.length > 0;
8
+ return (_jsxs("div", { className: compact
9
+ ? 'mb-1 shrink-0 space-y-1.5 px-1 xl:mb-4 xl:space-y-3 xl:px-6'
10
+ : 'mb-2 shrink-0 space-y-3 px-2 sm:mb-4 sm:px-6', children: [instruction && (_jsxs("div", { className: compact
11
+ ? 'flex w-full items-center gap-2 rounded-[14px] border-2 border-dashed border-blue-300 bg-[#F8FBFF] px-3 py-2 transition-all hover:bg-blue-50/50 lg:gap-3 lg:px-4 lg:py-2.5 xl:gap-5 xl:rounded-[24px] xl:px-5 xl:py-4'
12
+ : 'flex w-full items-center gap-4 rounded-[24px] border-2 border-dashed border-blue-300 bg-[#F8FBFF] px-5 py-4 transition-all hover:bg-blue-50/50 sm:gap-5', children: [_jsx("div", { className: compact
13
+ ? 'flex h-8 w-8 shrink-0 -rotate-6 items-center justify-center rounded-[10px] bg-[#0070FF] shadow-[3px_3px_0px_rgba(191,219,254,1)] transition-transform hover:rotate-0 lg:h-9 lg:w-9 xl:h-14 xl:w-14 xl:rounded-[16px] xl:shadow-[4px_4px_0px_rgba(191,219,254,1)]'
14
+ : 'flex h-12 w-12 shrink-0 -rotate-6 items-center justify-center rounded-[16px] bg-[#0070FF] shadow-[4px_4px_0px_rgba(191,219,254,1)] transition-transform hover:rotate-0 sm:h-14 sm:w-14', children: _jsx(Megaphone, { className: compact ? 'h-4 w-4 text-white lg:h-5 lg:w-5 xl:h-7 xl:w-7' : 'h-6 w-6 text-white sm:h-7 sm:w-7', strokeWidth: 2.5 }) }), _jsx("div", { className: "flex flex-1 flex-col justify-center", children: _jsxs("p", { className: compact
15
+ ? 'text-[12px] font-black uppercase leading-tight tracking-wide text-[#002868] lg:text-[13px] xl:text-[18px] xl:leading-snug'
16
+ : 'text-[15px] font-black uppercase leading-snug tracking-wide text-[#002868] sm:text-[18px]', style: { fontFamily: '"SVN-Volte Rounded", "Quicksand", sans-serif' }, children: [instruction, hasExample && (_jsx("span", { className: compact
17
+ ? 'ml-1 inline-block rounded-full bg-blue-100 px-1.5 py-0.5 align-middle text-[10px] font-bold tracking-normal text-[#0070FF] xl:-mt-1 xl:ml-2 xl:px-3 xl:text-[16px]'
18
+ : 'ml-2 -mt-1 inline-block rounded-full bg-blue-100 px-3 py-0.5 align-middle text-[14px] font-bold tracking-normal text-[#0070FF] sm:text-[16px]', children: "THERE IS ONE EXAMPLE" }))] }) })] })), children, hasInstructionsList && (_jsx("div", { className: "rounded-lg border border-blue-200 bg-white p-4 shadow-sm", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("h4", { className: "flex items-center gap-2 font-semibold text-blue-900", children: [_jsx(Info, { className: "h-4 w-4" }), "Instructions"] }), _jsx("ol", { className: "list-inside list-decimal space-y-1.5 text-sm text-gray-700", children: instructions.map((item, index) => (_jsx("li", { className: "leading-relaxed", children: item }, index))) })] }) }))] }));
19
+ }
@@ -1 +1,13 @@
1
- import{jsx as e}from"react/jsx-runtime";import t from"next/image";import n from"../summer-sky/assets/images/prev-question-btn.png";import r from"../summer-sky/assets/images/next-question-btn.png";export function CambridgeYleNavButton({direction:s,onClick:o,disabled:i=!1}){const a="prev"===s?"Câu trước":"Câu tiếp theo";return e("button",{onClick:o,disabled:i,className:`flex items-center justify-center transition-transform outline-none bg-transparent border-none\n ${i?"cursor-not-allowed opacity-45 grayscale pointer-events-none":"cursor-pointer hover:scale-[1.05] active:scale-[0.95]"}\n `,"aria-label":a,title:i?"Không thể chuyển câu":void 0,children:e(t,{src:"prev"===s?n:r,alt:a,className:"w-16 h-auto sm:w-20"})})}
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import Image from 'next/image';
3
+ import prevBtnImg from '../summer-sky/assets/images/prev-question-btn.png';
4
+ import nextBtnImg from '../summer-sky/assets/images/next-question-btn.png';
5
+ export function CambridgeYleNavButton({ direction, onClick, disabled = false, }) {
6
+ const imgSrc = direction === 'prev' ? prevBtnImg : nextBtnImg;
7
+ const altText = direction === 'prev' ? 'Câu trước' : 'Câu tiếp theo';
8
+ return (_jsx("button", { onClick: onClick, disabled: disabled, className: `flex items-center justify-center transition-transform outline-none bg-transparent border-none
9
+ ${disabled
10
+ ? 'cursor-not-allowed opacity-45 grayscale pointer-events-none'
11
+ : 'cursor-pointer hover:scale-[1.05] active:scale-[0.95]'}
12
+ `, "aria-label": altText, title: disabled ? 'Không thể chuyển câu' : undefined, children: _jsx(Image, { src: imgSrc, alt: altText, className: "w-16 h-auto sm:w-20" }) }));
13
+ }
@@ -4,5 +4,5 @@ interface CambridgeYlePartBannerProps {
4
4
  partName?: string;
5
5
  isReviewMode?: boolean;
6
6
  }
7
- export default function CambridgeYlePartBanner({ partName, isReviewMode, }: CambridgeYlePartBannerProps): import("react").JSX.Element;
7
+ export default function CambridgeYlePartBanner(_props: CambridgeYlePartBannerProps): any;
8
8
  export {};
@@ -1 +1,3 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import s from"next/image";import a from"../summer-sky/assets/images/background_title.png";export default function r({partName:r,isReviewMode:m=!1}){return!r||m?null:t("div",{className:"relative mx-auto flex shrink-0 items-center justify-center w-[260px] sm:w-[320px] h-[55px] sm:h-[70px] drop-shadow-[0_4px_6px_rgba(0,0,0,0.3)] mb-1 sm:mb-2 mt-0",children:[e(s,{src:a,alt:"Part Badge",fill:!0,className:"object-fill pointer-events-none"}),e("span",{className:"relative z-10 text-yellow-300 font-black uppercase text-[24px] sm:text-[30px] tracking-[0.08em] -translate-y-0.5 sm:-translate-y-1",style:{textShadow:"0px 2px 4px rgba(0,0,0,0.8)",fontFamily:'"SVN-Volte Rounded", "Quicksand", sans-serif'},children:r})]})}
1
+ export default function CambridgeYlePartBanner(_props) {
2
+ return null;
3
+ }
@@ -1 +1,6 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Trophy as s}from"lucide-react";export function CambridgeYleProgressBar({progress:a,className:l=""}){const t=Math.min(100,Math.max(0,a));return r("div",{className:`flex items-center gap-2 sm:gap-3 ${l}`,children:[e("div",{className:"relative h-2 w-full max-w-md overflow-hidden rounded-full bg-gray-200 sm:h-3",children:e("div",{className:"h-full rounded-full bg-gradient-to-r from-orange-400 via-red-400 to-red-500 transition-all duration-300 ease-out",style:{width:`${t}%`}})}),e("div",{className:"flex h-6 w-6 flex-shrink-0 items-center justify-center sm:h-8 sm:w-8",children:e(s,{className:"h-5 w-5 text-yellow-500 sm:h-6 sm:w-6"})})]})}
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Trophy } from 'lucide-react';
3
+ export function CambridgeYleProgressBar({ progress, className = '', }) {
4
+ const clampedProgress = Math.min(100, Math.max(0, progress));
5
+ return (_jsxs("div", { className: `flex items-center gap-2 sm:gap-3 ${className}`, children: [_jsx("div", { className: "relative h-2 w-full max-w-md overflow-hidden rounded-full bg-gray-200 sm:h-3", children: _jsx("div", { className: "h-full rounded-full bg-gradient-to-r from-orange-400 via-red-400 to-red-500 transition-all duration-300 ease-out", style: { width: `${clampedProgress}%` } }) }), _jsx("div", { className: "flex h-6 w-6 flex-shrink-0 items-center justify-center sm:h-8 sm:w-8", children: _jsx(Trophy, { className: "h-5 w-5 text-yellow-500 sm:h-6 sm:w-6" }) })] }));
6
+ }
@@ -1 +1,5 @@
1
- import{jsx as l}from"react/jsx-runtime";import{cn as e}from"../../../shared/lib/utils";export default function r({children:r,className:i}){return l("div",{className:e("relative w-full h-full flex flex-col",i),children:r})}
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '../../../shared/lib/utils';
3
+ export default function CambridgeYleQuestionCard({ children, className, }) {
4
+ return _jsx("div", { className: cn('relative w-full h-full flex flex-col', className), children: children });
5
+ }
@@ -1 +1,9 @@
1
- import{jsx as e,Fragment as l,jsxs as r}from"react/jsx-runtime";import{cn as a}from"../../../shared/lib/utils";export default function d({children:d,className:i}){return r(l,{children:[e("div",{className:a("relative mx-auto flex min-h-[70vh] w-full flex-1 flex-col rounded-2xl bg-white p-4 shadow-lg lg:hidden",i),children:e("div",{className:"flex-1 overflow-auto",children:d})}),e("div",{className:a("relative mx-auto hidden w-full max-w-[1400px] flex-1 min-h-0 flex-col rounded-[24px] border-[12px] border-[#3182CE] bg-white shadow-xl lg:flex",i),children:e("div",{className:"flex-1 overflow-auto p-6 md:p-8",children:d})})]})}
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../../shared/lib/utils';
3
+ /**
4
+ * Full-width question card container for coloring/painting questions.
5
+ * Uses background without dashed separator (unlike CambridgeYleQuestionCard).
6
+ */
7
+ export default function CambridgeYleQuestionCardFullWidth({ children, className, }) {
8
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn('relative mx-auto flex min-h-[70vh] w-full flex-1 flex-col rounded-2xl bg-white p-4 shadow-lg lg:hidden', className), children: _jsx("div", { className: "flex-1 overflow-auto", children: children }) }), _jsx("div", { className: cn('relative mx-auto hidden w-full max-w-[1400px] flex-1 min-h-0 flex-col rounded-[24px] border-[12px] border-[#3182CE] bg-white shadow-xl lg:flex', className), children: _jsx("div", { className: "flex-1 overflow-auto p-6 md:p-8", children: children }) })] }));
9
+ }
@@ -11,7 +11,8 @@ export interface SidebarPart {
11
11
  export interface SidebarQuestion {
12
12
  globalIndex: number;
13
13
  partIndex: number;
14
- questionNumber: number;
14
+ questionNumber: number | string;
15
+ subQuestionNumber?: number | string;
15
16
  isAnswered: boolean;
16
17
  }
17
18
  export interface CambridgeYleSidebarProps {
@@ -1 +1,61 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{cn as r}from"../../../shared/lib/utils";import l from"next/image";import{useEffect as s,useRef as n}from"react";import a from"./assets/images/phao.png";import o from"./assets/images/sanho.png";import i from"./assets/images/sao.png";import c from"./assets/images/vooc.png";const d=[a,o,i,c];export function CambridgeYleSidebar({parts:a,questions:o,currentQuestionGlobalIndex:i,onPartClick:c,onQuestionClick:p,isNavDisabled:m,className:u}){const h=o[i],b=h?h.partIndex:0,x=n(null),f=n([]),g=(n(null),n(new Map));return s(()=>{const e=x.current,t=f.current[b];if(!e||!t)return;const r=e.getBoundingClientRect(),l=t.getBoundingClientRect(),s=l.top<r.top,n=l.bottom>r.bottom;(s||n)&&t.scrollIntoView({block:"nearest",behavior:"smooth"})},[b]),s(()=>{const e=g.current.get(i);e?.scrollIntoView({block:"center",behavior:"smooth"})},[i]),t("div",{className:r("flex flex-col w-full h-full pb-4",u),children:[t("div",{ref:x,className:"flex-1 overflow-y-auto custom-scrollbar p-4 lg:p-6 pb-2",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px]",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("polygon",{points:"12 2 2 7 12 12 22 7 12 2"}),e("polyline",{points:"2 17 12 22 22 17"}),e("polyline",{points:"2 12 12 17 22 12"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Parts"})]}),e("div",{className:"flex flex-col gap-2.5",children:a.map((s,n)=>{const o=n===b,i=d[n%d.length],p=n>0?a[n-1].category:null,u=s.category&&s.category!==p;return t("div",{ref:e=>{f.current[n]=e},className:"flex flex-col",children:[u&&t("div",{className:"flex items-center gap-2 mt-5 mb-3 px-1",children:[e("div",{className:"h-[4px] w-4 rounded-full bg-blue-500"}),e("span",{className:"text-[14px] font-black uppercase tracking-[0.15em] text-blue-800",children:s.category?.replace(/_/g," ")}),e("div",{className:"h-[2px] flex-1 rounded-full bg-blue-100"})]}),t("button",{type:"button",onClick:()=>c(n),disabled:m,className:r("flex items-center justify-between p-2 px-[15px] rounded-[15px] transition-all border font-medium shadow-sm",o?"bg-blue-600 text-white border-blue-600":"bg-white text-slate-800 border-transparent",o||m?"":"hover:border-blue-200",m?"opacity-50 cursor-not-allowed":"cursor-pointer"),children:[t("div",{className:"flex items-center gap-3",children:[e("div",{className:"flex items-center justify-center w-8 h-8 shrink-0",children:e(l,{src:i,alt:`part icon ${n}`,className:"w-[30px] h-auto object-contain"})}),e("span",{className:"font-black text-[15px]",children:s.name||`Part ${s.partNo}`})]}),t("div",{className:"flex items-center gap-2 shrink-0",children:[null!=s.points&&s.points>0&&t("span",{className:r("text-[12px] font-black tracking-wide whitespace-nowrap",o?"text-yellow-200":"text-amber-500"),children:[s.points," điểm"]}),t("span",{className:r("text-[13px] font-bold tracking-wide",o?"text-blue-100":"text-blue-900/60"),children:[s.answeredCount,"/",s.totalQuestions]})]})]})]},n)})})]}),e("div",{className:"px-6",children:e("hr",{className:"border-t-2 border-dashed border-blue-100"})}),t("div",{className:"flex-1 p-4 lg:p-6 pt-4 flex flex-col min-h-0",children:[t("div",{className:"flex items-center gap-2 mb-4 justify-center uppercase tracking-widest text-[16px] shrink-0",children:[e("div",{className:"flex items-center justify-center p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl text-white",children:t("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e("rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}),e("path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}),e("path",{d:"M12 11h4"}),e("path",{d:"M12 16h4"}),e("path",{d:"M8 11h.01"}),e("path",{d:"M8 16h.01"})]})}),e("span",{className:"font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent",children:"Question List"})]}),e("div",{className:"flex-1 overflow-y-auto custom-scrollbar pr-1",children:e("div",{className:"grid grid-cols-5 gap-2",children:o.map(t=>{const l=t.globalIndex===i,s=t.isAnswered;let n="bg-white text-slate-800 shadow-sm border-transparent";return l?n="bg-blue-600 text-white border-blue-600 shadow-md":s&&(n="bg-[#4ade80] text-white border-transparent shadow-sm"),l||m||(n+=" hover:shadow-md hover:text-blue-600"),n+=m?" opacity-50 cursor-not-allowed":" cursor-pointer",e("button",{ref:e=>{e?g.current.set(t.globalIndex,e):g.current.delete(t.globalIndex)},type:"button",onClick:()=>p(t.globalIndex),disabled:m,className:r("h-[44px] w-full rounded-[10px] flex items-center justify-center font-bold text-[15px] transition-all border",n),children:t.questionNumber},t.globalIndex)})})}),e("div",{className:"shrink-0 mt-4 pt-4 border-t border-blue-200/50",children:t("div",{className:"flex items-center justify-between text-[11px] xl:text-[11.5px] font-bold text-gray-700",children:[t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-blue-600 shadow-sm"}),e("span",{children:"Current"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-green-500 shadow-sm"}),e("span",{children:"Answered"})]}),t("div",{className:"flex items-center gap-1.5",children:[e("div",{className:"w-3.5 h-3.5 rounded-full bg-[#f4f9ff] border border-blue-200 shadow-sm"}),e("span",{children:"Not answered"})]})]})})]})]})}
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../../shared/lib/utils';
3
+ import { Fragment, useEffect, useRef } from 'react';
4
+ export function CambridgeYleSidebar({ parts, questions, currentQuestionGlobalIndex, onPartClick, onQuestionClick, isNavDisabled, className, }) {
5
+ const currentQuestion = questions[currentQuestionGlobalIndex];
6
+ const currentPartIndex = currentQuestion ? currentQuestion.partIndex : 0;
7
+ const partsScrollRef = useRef(null);
8
+ const partRefs = useRef([]);
9
+ const questionScrollRef = useRef(null);
10
+ const questionRefs = useRef(new Map());
11
+ useEffect(() => {
12
+ const container = partsScrollRef.current;
13
+ const activePart = partRefs.current[currentPartIndex];
14
+ if (!container || !activePart)
15
+ return;
16
+ const containerRect = container.getBoundingClientRect();
17
+ const activeRect = activePart.getBoundingClientRect();
18
+ const isAbove = activeRect.top < containerRect.top;
19
+ const isBelow = activeRect.bottom > containerRect.bottom;
20
+ if (isAbove || isBelow) {
21
+ activePart.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
22
+ }
23
+ }, [currentPartIndex]);
24
+ useEffect(() => {
25
+ const activeBtn = questionRefs.current.get(currentQuestionGlobalIndex);
26
+ activeBtn?.scrollIntoView({ block: 'center', behavior: 'smooth' });
27
+ }, [currentQuestionGlobalIndex]);
28
+ return (_jsxs("div", { className: cn("flex flex-col w-full h-full pb-3", className), children: [_jsxs("div", { ref: partsScrollRef, className: "shrink-0 max-h-[35%] overflow-y-auto custom-scrollbar px-2.5 pt-2 pb-1 xl:px-5 xl:pt-4 xl:pb-2", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1.5 xl:mb-3 xl:gap-2 justify-center uppercase tracking-widest text-[12px] xl:text-[14.5px]", children: [_jsx("div", { className: "flex items-center justify-center p-1 xl:p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-lg xl:rounded-xl text-white", children: _jsxs("svg", { className: "h-3.5 w-3.5 xl:h-4 xl:w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), _jsx("polyline", { points: "2 17 12 22 22 17" }), _jsx("polyline", { points: "2 12 12 17 22 12" })] }) }), _jsx("span", { className: "font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent", children: "Parts" })] }), _jsx("div", { className: "grid grid-cols-3 gap-1.5 xl:gap-2", children: parts.map((part, idx) => {
29
+ const isCurrent = idx === currentPartIndex;
30
+ const prevCategory = idx > 0 ? parts[idx - 1].category : null;
31
+ const showCategoryTitle = part.category && part.category !== prevCategory;
32
+ return (_jsxs(Fragment, { children: [showCategoryTitle && (_jsxs("div", { className: "col-span-3 flex min-w-0 items-center gap-1.5 mt-2 mb-1 px-1 xl:gap-2 xl:mt-3 xl:mb-1.5", children: [_jsx("div", { className: "h-[3px] w-3 shrink-0 rounded-full bg-blue-500 xl:h-[3.5px] xl:w-3.5" }), _jsx("span", { className: "min-w-0 truncate whitespace-nowrap text-[10.5px] xl:text-[12.5px] font-black uppercase tracking-[0.1em] text-blue-800", title: part.category?.replace(/_/g, ' '), children: part.category?.replace(/_/g, ' ') }), _jsx("div", { className: "h-[2px] min-w-0 flex-1 rounded-full bg-blue-100" })] })), _jsxs("button", { ref: (el) => { partRefs.current[idx] = el; }, type: "button", onClick: () => onPartClick(idx), disabled: isNavDisabled, className: cn("flex flex-col items-center justify-center py-1 px-1 xl:py-1.5 xl:px-1.5 rounded-md xl:rounded-lg transition-all border font-medium shadow-sm min-w-0 text-center", isCurrent
33
+ ? "bg-blue-600 text-white border-blue-600"
34
+ : "bg-white text-slate-800 border-transparent", !isCurrent && !isNavDisabled ? "hover:border-blue-200" : "", isNavDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), children: [_jsx("span", { className: "font-black text-[11px] xl:text-[13px] truncate w-full", children: part.name || `Part ${part.partNo}` }), _jsxs("span", { className: cn('text-[10px] xl:text-[11.5px] font-bold tracking-wide mt-0.5', isCurrent ? 'text-blue-100' : 'text-blue-900/60'), children: [part.answeredCount, "/", part.totalQuestions] })] })] }, idx));
35
+ }) })] }), _jsx("div", { className: "px-5", children: _jsx("hr", { className: "border-t-2 border-dashed border-blue-100" }) }), _jsxs("div", { className: "flex-1 px-2.5 pt-2 pb-2 xl:p-5 flex flex-col min-h-0", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-2 xl:gap-2 xl:mb-4 justify-center uppercase tracking-widest text-[12.5px] xl:text-[15.5px] shrink-0", children: [_jsx("div", { className: "flex items-center justify-center p-1 xl:p-1.5 bg-gradient-to-br from-blue-400 to-blue-600 rounded-lg xl:rounded-xl text-white", children: _jsxs("svg", { className: "h-3.5 w-3.5 xl:h-4 xl:w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1" }), _jsx("path", { d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" }), _jsx("path", { d: "M12 11h4" }), _jsx("path", { d: "M12 16h4" }), _jsx("path", { d: "M8 11h.01" }), _jsx("path", { d: "M8 16h.01" })] }) }), _jsx("span", { className: "font-black bg-gradient-to-r from-blue-700 to-blue-500 bg-clip-text text-transparent", children: "Question List" })] }), _jsx("div", { className: "flex-1 overflow-y-auto custom-scrollbar pr-1", children: _jsx("div", { className: "grid grid-cols-5 gap-1.5 xl:gap-2", children: questions.map((q) => {
36
+ const isCurrent = q.globalIndex === currentQuestionGlobalIndex;
37
+ const isAnswered = q.isAnswered;
38
+ let btnStyle = "bg-white text-slate-800 shadow-sm border-transparent";
39
+ if (isCurrent) {
40
+ btnStyle = "bg-blue-600 text-white border-blue-600 shadow-md";
41
+ }
42
+ else if (isAnswered) {
43
+ btnStyle = "bg-[#4ade80] text-white border-transparent shadow-sm";
44
+ }
45
+ if (!isCurrent && !isNavDisabled) {
46
+ btnStyle += " hover:shadow-md hover:text-blue-600";
47
+ }
48
+ if (isNavDisabled) {
49
+ btnStyle += " opacity-50 cursor-not-allowed";
50
+ }
51
+ else {
52
+ btnStyle += " cursor-pointer";
53
+ }
54
+ return (_jsx("button", { ref: (el) => {
55
+ if (el)
56
+ questionRefs.current.set(q.globalIndex, el);
57
+ else
58
+ questionRefs.current.delete(q.globalIndex);
59
+ }, type: "button", onClick: () => onQuestionClick(q.globalIndex), disabled: isNavDisabled, className: cn("h-[36px] xl:h-[40px] 2xl:h-[42px] w-full rounded-[9px] flex items-center justify-center font-bold text-[13px] xl:text-[14px] 2xl:text-[14.5px] transition-all border", btnStyle), children: q.subQuestionNumber !== undefined ? (_jsxs("span", { className: "inline-flex items-start justify-center leading-none", children: [_jsx("span", { children: q.questionNumber }), _jsxs("span", { className: "text-[9.5px] xl:text-[10.5px] opacity-75 font-semibold ml-0.5 -mt-0.5", children: [".", q.subQuestionNumber] })] })) : (q.questionNumber) }, q.globalIndex));
60
+ }) }) })] })] }));
61
+ }
@@ -3,5 +3,5 @@ interface CambridgeYleTimerProps {
3
3
  totalQuestions: number;
4
4
  answeredCount: number;
5
5
  }
6
- export declare function CambridgeYleTimer({ remainingSeconds, totalQuestions, answeredCount, }: CambridgeYleTimerProps): import("react").JSX.Element;
6
+ export declare function CambridgeYleTimer({ remainingSeconds, }: CambridgeYleTimerProps): import("react").JSX.Element;
7
7
  export {};
@@ -1 +1,25 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import s from"next/image";import r from"../../../components/themes/summer-sky/assets/images/clock.png";export function CambridgeYleTimer({remainingSeconds:a,totalQuestions:n,answeredCount:p}){const o=a%60,x=`${Math.floor(a/60).toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}`;let m="bg-[#001590]",i="shadow-[0_4px_20px_rgba(0,0,0,0.25)]";return a<=120?(m="bg-[rgba(220,38,38,0.85)]",i="shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse"):a<=300&&(m="bg-[rgba(180,120,0,0.85)]"),t("div",{className:`flex items-center w-[130px] sm:w-[170px] h-[40px] sm:h-[50px] rounded-[33.5px] backdrop-blur-[8px] transition-all duration-300 ease-in-out border-none ${m} ${i}`,children:[e(s,{src:r,alt:"clock",width:75,height:75,className:"w-[50px] h-[50px] sm:w-[75px] sm:h-[75px] -ml-[5px] sm:-ml-[10px] -mt-[10px] sm:-mt-[15px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10"}),e("span",{className:"flex-1 text-center font-bold text-[18px] sm:text-[25px] leading-none tracking-[-0.03em] uppercase text-white pr-[10px] sm:pr-[16px]",style:{fontFamily:"'SVN-Volte Rounded', 'Quicksand', sans-serif",textShadow:"0 2px 4px rgba(0, 0, 0, 0.2)"},children:x})]})}
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Image from 'next/image';
3
+ import summerSkyClockImg from '../summer-sky/assets/images/clock.png';
4
+ export function CambridgeYleTimer({ remainingSeconds, }) {
5
+ const minutes = Math.floor(remainingSeconds / 60);
6
+ const seconds = remainingSeconds % 60;
7
+ const formattedTime = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
8
+ // Use the same styles as the Speaking exam timer but relative positioning
9
+ // Warning colors can be added if needed based on remainingSeconds,
10
+ // but for now we'll match the default blue theme.
11
+ let bgColorClass = 'bg-[#001590]';
12
+ let shadowClass = 'shadow-[0_4px_20px_rgba(0,0,0,0.25)]';
13
+ // Optional warning states (similar to ExamTimer.module.css)
14
+ if (remainingSeconds <= 120) {
15
+ bgColorClass = 'bg-[rgba(220,38,38,0.85)]'; // Critical
16
+ shadowClass = 'shadow-[0_0_24px_rgba(220,38,38,0.5)] animate-pulse';
17
+ }
18
+ else if (remainingSeconds <= 300) {
19
+ bgColorClass = 'bg-[rgba(180,120,0,0.85)]'; // Warning
20
+ }
21
+ return (_jsxs("div", { className: `flex items-center w-[76px] sm:w-[86px] md:w-[94px] lg:w-[100px] xl:w-[140px] 2xl:w-[160px] h-[26px] sm:h-[29px] md:h-[32px] lg:h-[34px] xl:h-[46px] rounded-[33.5px] backdrop-blur-[8px] transition-all duration-300 ease-in-out border-none ${bgColorClass} ${shadowClass}`, children: [_jsx(Image, { src: summerSkyClockImg, alt: "clock", width: 75, height: 75, className: "w-[29px] h-[29px] sm:w-[33px] sm:h-[33px] md:w-[37px] md:h-[37px] lg:w-[42px] lg:h-[42px] xl:w-[60px] xl:h-[60px] -ml-[2px] sm:-ml-[3px] md:-ml-[4px] lg:-ml-[6px] -mt-[3px] sm:-mt-[4px] md:-mt-[6px] lg:-mt-[8px] shrink-0 drop-shadow-[0_2px_6px_rgba(0,0,0,0.2)] pointer-events-none z-10" }), _jsx("span", { className: "flex-1 text-center font-bold text-[10px] sm:text-[11px] md:text-[13px] lg:text-[14px] xl:text-[21px] 2xl:text-[23px] leading-none tracking-[-0.03em] uppercase text-white pr-[3px] sm:pr-[4px] md:pr-[5px] lg:pr-[7px] xl:pr-[12px]", style: {
22
+ fontFamily: "'SVN-Volte Rounded', 'Quicksand', sans-serif",
23
+ textShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
24
+ }, children: formattedTime })] }));
25
+ }
@@ -1 +1,13 @@
1
- export{CambridgeYleExamLayout}from"./CambridgeYleExamLayout";export{CambridgeYleHeader}from"./CambridgeYleHeader";export{CambridgeYleNavButton}from"./CambridgeYleNavButton";export{CambridgeYleProgressBar}from"./CambridgeYleProgressBar";export{CambridgeYleTimer}from"./CambridgeYleTimer";export{default as CambridgeYleQuestionCard}from"./CambridgeYleQuestionCard";export{default as CambridgeYleQuestionCardFullWidth}from"./CambridgeYleQuestionCardFullWidth";export{default as CambridgeYlePartBanner}from"./CambridgeYlePartBanner";export{default as CambridgeYleInstructionBanner}from"./CambridgeYleInstructionBanner";export{default as CambridgeYleAudioPlayer}from"./CambridgeYleAudioPlayer";export{default as CambridgeYleExampleText}from"./CambridgeYleExampleText";
1
+ // Cambridge YLE Theme Layout & UI components
2
+ // Previously known as the "Movers" theme
3
+ export { CambridgeYleExamLayout } from './CambridgeYleExamLayout';
4
+ export { CambridgeYleHeader } from './CambridgeYleHeader';
5
+ export { CambridgeYleNavButton } from './CambridgeYleNavButton';
6
+ export { CambridgeYleProgressBar } from './CambridgeYleProgressBar';
7
+ export { CambridgeYleTimer } from './CambridgeYleTimer';
8
+ export { default as CambridgeYleQuestionCard } from './CambridgeYleQuestionCard';
9
+ export { default as CambridgeYleQuestionCardFullWidth } from './CambridgeYleQuestionCardFullWidth';
10
+ export { default as CambridgeYlePartBanner } from './CambridgeYlePartBanner';
11
+ export { default as CambridgeYleInstructionBanner } from './CambridgeYleInstructionBanner';
12
+ export { default as CambridgeYleAudioPlayer } from './CambridgeYleAudioPlayer';
13
+ export { default as CambridgeYleExampleText } from './CambridgeYleExampleText';
@@ -1 +1,25 @@
1
- "use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{useMemo as t}from"react";import{ResolvedImage as r}from"../../../components/common/ResolvedImage";import{cn as a}from"../../../shared/lib/utils";import{transformAnswerTheQuestion as n}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as i}from"./english-cert-scroll";export function EcAnswerTheQuestion({part:l,answers:o,onAnswerChange:d,isReviewMode:c=!1}){const{questions:m,imageUrl:x,title:p}=t(()=>n(l.questions),[l.questions]);return s("div",{className:"flex flex-col gap-4",children:[x&&e("div",{className:"flex items-center justify-center",children:e(r,{src:x,alt:p||"Group image",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),e("div",{className:"flex flex-col gap-3",children:m.map(t=>{const n=o[t.id]?.answer??t.exampleAnswer??"";return e("div",{id:i(t.id),className:a("scroll-mt-24 rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",t.isExample&&"opacity-90"),children:s("div",{className:"flex items-start gap-3",children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:t.questionNumber}),s("div",{className:"min-w-0 flex-1 space-y-2",children:[t.imageUrl&&e(r,{src:t.imageUrl,alt:`Question ${t.questionNumber}`,className:"max-h-28 w-auto rounded object-contain"}),e("p",{className:"text-sm text-[#0f1730]",children:t.question}),s("div",{className:"flex flex-wrap items-center gap-2",children:[t.prefixText&&e("span",{className:"text-sm text-[#64748b]",children:t.prefixText}),t.isExample?e("span",{className:"rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]",children:t.exampleAnswer}):e("input",{type:"text",value:n,disabled:c,placeholder:"Enter your answer…",onChange:e=>{return s=t.id,r=e.target.value,void d(s,{answer:r});var s,r},className:a("min-w-[200px] flex-1 rounded-lg border-2 border-[#9cc4f5] bg-white px-3 py-2 text-sm font-medium text-[#0f1730] outline-none transition-all focus:border-[#1167e8]",c&&"cursor-not-allowed opacity-70")}),t.suffixText&&e("span",{className:"text-sm text-[#64748b]",children:t.suffixText})]}),t.suggestedAnswers&&t.suggestedAnswers.length>0&&e("div",{className:"flex flex-wrap gap-1.5",children:t.suggestedAnswers.map((s,r)=>e("span",{className:"rounded-full border border-[#e2ecf8] bg-[#f4f9ff] px-2.5 py-0.5 text-xs text-[#0b57d0]",children:s},`${t.id}-sa-${r}`))})]})]})},t.id)})})]})}
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useMemo } from 'react';
4
+ import { ResolvedImage } from '../../../components/common/ResolvedImage';
5
+ import { cn } from '../../../shared/lib/utils';
6
+ import { transformAnswerTheQuestion } from '../../../components/exams/take/exam-taking.utils';
7
+ import { englishCertQuestionDomId } from './english-cert-scroll';
8
+ /**
9
+ * Branded English Certification renderer for `ANSWER_THE_QUESTION`.
10
+ *
11
+ * Lists each question with an inline text input (plus optional prefix/suffix and
12
+ * suggested answers). Reuses {@link transformAnswerTheQuestion} so the stored
13
+ * answer shape (`{ [questionId]: { answer: string } }`) stays compatible with
14
+ * the grading store.
15
+ */
16
+ export function EcAnswerTheQuestion({ part, answers, onAnswerChange, isReviewMode = false, }) {
17
+ const { questions, imageUrl, title } = useMemo(() => transformAnswerTheQuestion(part.questions), [part.questions]);
18
+ const handleChange = (questionId, value) => {
19
+ onAnswerChange(questionId, { answer: value });
20
+ };
21
+ return (_jsxs("div", { className: "flex flex-col gap-4", children: [imageUrl && (_jsx("div", { className: "flex items-center justify-center", children: _jsx(ResolvedImage, { src: imageUrl, alt: title || 'Group image', className: "max-h-[280px] rounded-lg object-contain shadow-md" }) })), _jsx("div", { className: "flex flex-col gap-3", children: questions.map((q) => {
22
+ const stored = answers[q.id]?.answer ?? q.exampleAnswer ?? '';
23
+ return (_jsx("div", { id: englishCertQuestionDomId(q.id), className: cn('scroll-mt-24 rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]', q.isExample && 'opacity-90'), children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white", children: q.questionNumber }), _jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [q.imageUrl && (_jsx(ResolvedImage, { src: q.imageUrl, alt: `Question ${q.questionNumber}`, className: "max-h-28 w-auto rounded object-contain" })), _jsx("p", { className: "text-sm text-[#0f1730]", children: q.question }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [q.prefixText && (_jsx("span", { className: "text-sm text-[#64748b]", children: q.prefixText })), q.isExample ? (_jsx("span", { className: "rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]", children: q.exampleAnswer })) : (_jsx("input", { type: "text", value: stored, disabled: isReviewMode, placeholder: "Enter your answer\u2026", onChange: (e) => handleChange(q.id, e.target.value), className: cn('min-w-[200px] flex-1 rounded-lg border-2 border-[#9cc4f5] bg-white px-3 py-2 text-sm font-medium text-[#0f1730] outline-none transition-all focus:border-[#1167e8]', isReviewMode && 'cursor-not-allowed opacity-70') })), q.suffixText && (_jsx("span", { className: "text-sm text-[#64748b]", children: q.suffixText }))] }), q.suggestedAnswers && q.suggestedAnswers.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5", children: q.suggestedAnswers.map((sa, idx) => (_jsx("span", { className: "rounded-full border border-[#e2ecf8] bg-[#f4f9ff] px-2.5 py-0.5 text-xs text-[#0b57d0]", children: sa }, `${q.id}-sa-${idx}`))) }))] })] }) }, q.id));
24
+ }) })] }));
25
+ }
@@ -1 +1,89 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as n}from"../../../components/common/ResolvedImage";import{cn as s}from"../../../shared/lib/utils";import{transformMatchByWritingAnswer as a}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as o}from"./english-cert-scroll";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),l={empty:"bg-[#eef3fb] text-[#94a3b8] border border-[#dbe5f2]",filled:"bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-white border border-transparent",correct:"bg-[#16a34a] text-white border border-transparent",wrong:"bg-[#ef4444] text-white border border-transparent"};function d({letter:t,tone:r}){return e("span",{className:s("flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-base font-bold transition-colors",l[r]),children:t||"—"})}export function EcMatchByWritingAnswer({part:l,answers:c,onAnswerChange:m,isReviewMode:f=!1}){const{questions:b,options:p,groupImageUrl:x}=r(()=>a(l.questions),[l.questions]),u=r(()=>{const e=new Map;return p.forEach((t,r)=>{e.set(t.answer,i[r]??String(r+1))}),e},[p]),h=e=>c[e.id]?.answer??e.exampleAnswer??"",g=r(()=>{const e=new Set;return b.forEach(t=>{const r=h(t),n=u.get(r);n&&e.add(n)}),e},[b,c,u]);return t("div",{className:"flex flex-col gap-4",children:[x&&e("div",{className:"flex items-center justify-center",children:e(n,{src:x,alt:"Group image",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),p.length>0&&t("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"ANSWER OPTIONS"}),e("div",{className:"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2",children:p.map((r,a)=>{const o=i[a]??String(a+1),l=!f&&g.has(o);return t("div",{className:s("flex items-start gap-2.5 rounded-xl border border-[#e2ecf8] bg-[#f4f9ff] px-3 py-2 transition-opacity",l&&"opacity-50"),children:[t("span",{className:"relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:[o,l&&e("span",{className:"absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-[#16a34a] text-[8px] text-white",children:"✓"})]}),t("div",{className:"min-w-0 text-sm text-[#0f1730]",children:[r.imageUrl&&e(n,{src:r.imageUrl,alt:r.answer,className:"mb-1 max-h-24 w-auto rounded object-contain"}),e("span",{className:"font-medium",children:r.content||r.answer})]})]},`${r.answer}-${a}`)})})]}),e("div",{className:"flex flex-col gap-3",children:b.map(r=>{const a=h(r),l=u.get(a)??"",c=f&&r.isExample?a===(r.exampleAnswer??""):void 0,b=!0===c?"border-[#bbf7d0] bg-[#f0fdf4]":!1===c?"border-[#fecaca] bg-[#fef2f2]":"border-[#d9e4f2] bg-white/90",x=!0===c?"correct":!1===c?"wrong":l?"filled":"empty";return t("div",{id:o(r.id),className:s("scroll-mt-24 flex items-center gap-3 rounded-xl border p-3 shadow-sm transition-colors",b,r.isExample&&"opacity-90"),children:[e("span",{className:"flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white",children:r.questionNumber}),t("div",{className:"min-w-0 flex-1",children:[r.imageUrl&&e(n,{src:r.imageUrl,alt:`Question ${r.questionNumber}`,className:"mb-2 max-h-28 w-auto rounded object-contain"}),e("p",{className:"text-sm text-[#0f1730]",children:r.question})]}),t("div",{className:"flex shrink-0 items-center gap-2",children:[e(d,{letter:l,tone:x}),r.isExample?e("span",{className:"rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]",children:r.exampleAnswer}):t("select",{value:a,disabled:f,onChange:e=>{return t=r.id,n=e.target.value,void m(t,{answer:n});var t,n},className:s("h-9 min-w-[150px] rounded-lg border-2 border-[#9cc4f5] bg-white px-3 text-sm font-semibold text-[#0f1730] outline-none transition-all focus:border-[#1167e8]",f&&"cursor-not-allowed opacity-70"),children:[e("option",{value:"",children:"—"}),p.map((t,n)=>{const s=i[n]??String(n+1),a=t.content||t.answer;return e("option",{value:t.answer,children:a?`${s} — ${a}`:s},`${r.id}-${n}`)})]})]})]},r.id)})})]})}
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useMemo } from 'react';
4
+ import { ResolvedImage } from '../../../components/common/ResolvedImage';
5
+ import { cn } from '../../../shared/lib/utils';
6
+ import { transformMatchByWritingAnswer } from '../../../components/exams/take/exam-taking.utils';
7
+ import { englishCertQuestionDomId } from './english-cert-scroll';
8
+ /** Letters A, B, C, … used to label the answer options. */
9
+ const OPTION_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
10
+ const BADGE_TONE_CLASS = {
11
+ empty: 'bg-[#eef3fb] text-[#94a3b8] border border-[#dbe5f2]',
12
+ filled: 'bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-white border border-transparent',
13
+ correct: 'bg-[#16a34a] text-white border border-transparent',
14
+ wrong: 'bg-[#ef4444] text-white border border-transparent',
15
+ };
16
+ /** Big rounded badge that mirrors the currently selected letter. */
17
+ function LetterBadge({ letter, tone }) {
18
+ return (_jsx("span", { className: cn('flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-base font-bold transition-colors', BADGE_TONE_CLASS[tone]), children: letter || '—' }));
19
+ }
20
+ /**
21
+ * Branded English Certification renderer for `MATCH_BY_WRITING_ANSWER`.
22
+ *
23
+ * Shows a lettered answer bank (A–H) at the top, then each question with a
24
+ * dropdown to pick its matching letter plus a big letter badge mirroring the
25
+ * current selection. Selected letters are dimmed in the bank (take mode) so the
26
+ * student can track which options are still free. Reuses
27
+ * {@link transformMatchByWritingAnswer} so the stored answer shape
28
+ * (`{ [questionId]: { answer: string } }`) stays compatible with the grading
29
+ * store.
30
+ */
31
+ export function EcMatchByWritingAnswer({ part, answers, onAnswerChange, isReviewMode = false, }) {
32
+ const { questions, options, groupImageUrl } = useMemo(() => transformMatchByWritingAnswer(part.questions), [part.questions]);
33
+ /** Map each option's stored answer value → its display letter (A, B, C…). */
34
+ const answerToLetter = useMemo(() => {
35
+ const map = new Map();
36
+ options.forEach((opt, idx) => {
37
+ map.set(opt.answer, OPTION_LETTERS[idx] ?? String(idx + 1));
38
+ });
39
+ return map;
40
+ }, [options]);
41
+ /** Resolve the stored value for a question (selection or example fallback). */
42
+ const getStored = (q) => answers[q.id]?.answer ?? q.exampleAnswer ?? '';
43
+ /** Letters currently assigned across all questions — drives bank dimming. */
44
+ const usedLetters = useMemo(() => {
45
+ const set = new Set();
46
+ questions.forEach((q) => {
47
+ const value = getStored(q);
48
+ const letter = answerToLetter.get(value);
49
+ if (letter)
50
+ set.add(letter);
51
+ });
52
+ return set;
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ }, [questions, answers, answerToLetter]);
55
+ const handleSelect = (questionId, value) => {
56
+ onAnswerChange(questionId, { answer: value });
57
+ };
58
+ return (_jsxs("div", { className: "flex flex-col gap-4", children: [groupImageUrl && (_jsx("div", { className: "flex items-center justify-center", children: _jsx(ResolvedImage, { src: groupImageUrl, alt: "Group image", className: "max-h-[280px] rounded-lg object-contain shadow-md" }) })), options.length > 0 && (_jsxs("div", { className: "rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]", children: [_jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-[#64748b]", children: "ANSWER OPTIONS" }), _jsx("div", { className: "mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2", children: options.map((opt, idx) => {
59
+ const letter = OPTION_LETTERS[idx] ?? String(idx + 1);
60
+ // Dim used options only in take mode so review stays comparable.
61
+ const isUsed = !isReviewMode && usedLetters.has(letter);
62
+ return (_jsxs("div", { className: cn('flex items-start gap-2.5 rounded-xl border border-[#e2ecf8] bg-[#f4f9ff] px-3 py-2 transition-opacity', isUsed && 'opacity-50'), children: [_jsxs("span", { className: "relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white", children: [letter, isUsed && (_jsx("span", { className: "absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-[#16a34a] text-[8px] text-white", children: "\u2713" }))] }), _jsxs("div", { className: "min-w-0 text-sm text-[#0f1730]", children: [opt.imageUrl && (_jsx(ResolvedImage, { src: opt.imageUrl, alt: opt.answer, className: "mb-1 max-h-24 w-auto rounded object-contain" })), _jsx("span", { className: "font-medium", children: opt.content || opt.answer })] })] }, `${opt.answer}-${idx}`));
63
+ }) })] })), _jsx("div", { className: "flex flex-col gap-3", children: questions.map((q) => {
64
+ const stored = getStored(q);
65
+ const selectedLetter = answerToLetter.get(stored) ?? '';
66
+ // Review correctness is only known for example rows (the
67
+ // transformer exposes `exampleAnswer`); other rows stay neutral.
68
+ const reviewCorrect = isReviewMode && q.isExample
69
+ ? stored === (q.exampleAnswer ?? '')
70
+ : undefined;
71
+ const rowTint = reviewCorrect === true
72
+ ? 'border-[#bbf7d0] bg-[#f0fdf4]'
73
+ : reviewCorrect === false
74
+ ? 'border-[#fecaca] bg-[#fef2f2]'
75
+ : 'border-[#d9e4f2] bg-white/90';
76
+ const badgeTone = reviewCorrect === true
77
+ ? 'correct'
78
+ : reviewCorrect === false
79
+ ? 'wrong'
80
+ : selectedLetter
81
+ ? 'filled'
82
+ : 'empty';
83
+ return (_jsxs("div", { id: englishCertQuestionDomId(q.id), className: cn('scroll-mt-24 flex items-center gap-3 rounded-xl border p-3 shadow-sm transition-colors', rowTint, q.isExample && 'opacity-90'), children: [_jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] text-xs font-bold text-white", children: q.questionNumber }), _jsxs("div", { className: "min-w-0 flex-1", children: [q.imageUrl && (_jsx(ResolvedImage, { src: q.imageUrl, alt: `Question ${q.questionNumber}`, className: "mb-2 max-h-28 w-auto rounded object-contain" })), _jsx("p", { className: "text-sm text-[#0f1730]", children: q.question })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(LetterBadge, { letter: selectedLetter, tone: badgeTone }), q.isExample ? (_jsx("span", { className: "rounded-lg border border-[#b9edc8] bg-[#ddf8e7] px-3 py-1.5 text-sm font-semibold text-[#15803d]", children: q.exampleAnswer })) : (_jsxs("select", { value: stored, disabled: isReviewMode, onChange: (e) => handleSelect(q.id, e.target.value), className: cn('h-9 min-w-[150px] rounded-lg border-2 border-[#9cc4f5] bg-white px-3 text-sm font-semibold text-[#0f1730] outline-none transition-all focus:border-[#1167e8]', isReviewMode && 'cursor-not-allowed opacity-70'), children: [_jsx("option", { value: "", children: "\u2014" }), options.map((opt, idx) => {
84
+ const letter = OPTION_LETTERS[idx] ?? String(idx + 1);
85
+ const label = opt.content || opt.answer;
86
+ return (_jsx("option", { value: opt.answer, children: label ? `${letter} — ${label}` : letter }, `${q.id}-${idx}`));
87
+ })] }))] })] }, q.id));
88
+ }) })] }));
89
+ }
@@ -1 +1,56 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useMemo as r}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as n}from"../../../shared/lib/utils";import{transformWordFillParagraph as l}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as o}from"./english-cert-scroll";export function EcWordFillParagraph({part:s,answers:i,onAnswerChange:d,isReviewMode:c=!1}){const m=r(()=>l(s.questions),[s.questions]),{questionId:p,paragraph:x,title:b,imageUrl:f,wordBank:h,viewMode:u}=m,g=i[p]||[],w=r(()=>x.split(/(\{\d+\})/),[x]),N="WITH_WORD_BANK"===u,v=new Set(g.filter(Boolean)),_=(e,t)=>{if(c)return;const r=[...g];r[e]=t,d(p,r)};return t("div",{id:o(p),className:"scroll-mt-24 flex flex-col gap-4",children:[f&&e("div",{className:"flex items-center justify-center",children:e(a,{src:f,alt:b||"Illustration",className:"max-h-[280px] rounded-lg object-contain shadow-md"})}),N&&h.length>0&&t("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"Word bank"}),e("div",{className:"mt-2 flex flex-wrap gap-2",children:h.map((t,r)=>{const a=v.has(t.word);return e("span",{className:n("rounded-full border px-3 py-1 text-sm font-semibold transition-all",t.isExample?"border-[#b9edc8] bg-[#ddf8e7] text-[#15803d]":a?"border-[#d9e4f2] bg-[#f4f9ff] text-[#94a3b8] line-through":"border-[#9cc4f5] bg-white text-[#0b57d0]"),children:t.word},`${t.word}-${r}`)})})]}),e("div",{className:"rounded-2xl border border-[#d9e4f2] bg-white/90 p-5 text-base leading-loose text-[#0f1730] shadow-[0_14px_35px_rgba(13,71,161,0.10)]",children:w.map((r,a)=>{const l=r.match(/^\{(\d+)\}$/);if(!l)return e("span",{children:r},a);const o=parseInt(l[1],10),s=g[o]||"";return t("span",N?{className:"mx-1 inline-flex items-baseline gap-1 align-baseline",children:[t("span",{className:"text-[11px] font-bold text-[#1f7cff]",children:["(",o+1,")"]}),t("select",{value:s,disabled:c,onChange:e=>_(o,e.target.value),className:n("rounded-lg border-2 px-2 py-1 text-sm font-semibold outline-none transition-all",s?"border-[#1167e8] text-[#0b57d0]":"border-[#9cc4f5] text-[#64748b]",c&&"cursor-not-allowed opacity-70"),children:[e("option",{value:"",children:"———"}),h.filter(e=>!e.isExample).map((t,r)=>e("option",{value:t.word,children:t.word},`${o}-${r}`))]})]}:{className:"mx-1 inline-flex items-baseline gap-1 align-baseline",children:[t("span",{className:"text-[11px] font-bold text-[#1f7cff]",children:["(",o+1,")"]}),e("input",{type:"text",value:s,disabled:c,placeholder:"···",onChange:e=>_(o,e.target.value),style:{width:`${Math.max(4,s.length+1)}ch`},className:n("inline-block min-w-[4ch] max-w-[16ch] border-b-2 bg-transparent px-1 text-center text-sm font-semibold outline-none transition-colors",s?"border-[#1167e8] text-[#0b57d0]":"border-[#9cc4f5] text-[#64748b]",c&&"cursor-not-allowed opacity-70")})]},a)})})]})}
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useMemo } from 'react';
4
+ import { ResolvedImage } from '../../../components/common/ResolvedImage';
5
+ import { cn } from '../../../shared/lib/utils';
6
+ import { transformWordFillParagraph } from '../../../components/exams/take/exam-taking.utils';
7
+ import { englishCertQuestionDomId } from './english-cert-scroll';
8
+ /**
9
+ * Branded English Certification renderer for `WORD_FILL_PARAGRAPH`.
10
+ *
11
+ * Shows an optional word bank, then the paragraph with inline blanks. Supports
12
+ * `WITH_WORD_BANK` (dropdown selecting a bank word) and `DEFAULT` (free text
13
+ * input). Reuses {@link transformWordFillParagraph} so the stored answer shape
14
+ * (`{ [questionId]: string[] }` indexed by blank) stays compatible with the
15
+ * grading store.
16
+ */
17
+ export function EcWordFillParagraph({ part, answers, onAnswerChange, isReviewMode = false, }) {
18
+ const data = useMemo(() => transformWordFillParagraph(part.questions), [part.questions]);
19
+ const { questionId, paragraph, title, imageUrl, wordBank, viewMode } = data;
20
+ const currentAnswers = answers[questionId] || [];
21
+ const segments = useMemo(() => paragraph.split(/(\{\d+\})/), [paragraph]);
22
+ const useWordBank = viewMode === 'WITH_WORD_BANK';
23
+ const usedWords = new Set(currentAnswers.filter(Boolean));
24
+ const setBlank = (blankIndex, value) => {
25
+ if (isReviewMode)
26
+ return;
27
+ const next = [...currentAnswers];
28
+ next[blankIndex] = value;
29
+ onAnswerChange(questionId, next);
30
+ };
31
+ return (_jsxs("div", { id: englishCertQuestionDomId(questionId), className: "scroll-mt-24 flex flex-col gap-4", children: [imageUrl && (_jsx("div", { className: "flex items-center justify-center", children: _jsx(ResolvedImage, { src: imageUrl, alt: title || 'Illustration', className: "max-h-[280px] rounded-lg object-contain shadow-md" }) })), useWordBank && wordBank.length > 0 && (_jsxs("div", { className: "rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)]", children: [_jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-[#64748b]", children: "Word bank" }), _jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: wordBank.map((item, idx) => {
32
+ const isUsed = usedWords.has(item.word);
33
+ return (_jsx("span", { className: cn('rounded-full border px-3 py-1 text-sm font-semibold transition-all', item.isExample
34
+ ? 'border-[#b9edc8] bg-[#ddf8e7] text-[#15803d]'
35
+ : isUsed
36
+ ? 'border-[#d9e4f2] bg-[#f4f9ff] text-[#94a3b8] line-through'
37
+ : 'border-[#9cc4f5] bg-white text-[#0b57d0]'), children: item.word }, `${item.word}-${idx}`));
38
+ }) })] })), _jsx("div", { className: "rounded-2xl border border-[#d9e4f2] bg-white/90 p-5 text-base leading-loose text-[#0f1730] shadow-[0_14px_35px_rgba(13,71,161,0.10)]", children: segments.map((segment, idx) => {
39
+ const blankMatch = segment.match(/^\{(\d+)\}$/);
40
+ if (!blankMatch) {
41
+ return _jsx("span", { children: segment }, idx);
42
+ }
43
+ const blankIndex = parseInt(blankMatch[1], 10);
44
+ const studentAnswer = currentAnswers[blankIndex] || '';
45
+ if (useWordBank) {
46
+ return (_jsxs("span", { className: "mx-1 inline-flex items-baseline gap-1 align-baseline", children: [_jsxs("span", { className: "text-[11px] font-bold text-[#1f7cff]", children: ["(", blankIndex + 1, ")"] }), _jsxs("select", { value: studentAnswer, disabled: isReviewMode, onChange: (e) => setBlank(blankIndex, e.target.value), className: cn('rounded-lg border-2 px-2 py-1 text-sm font-semibold outline-none transition-all', studentAnswer
47
+ ? 'border-[#1167e8] text-[#0b57d0]'
48
+ : 'border-[#9cc4f5] text-[#64748b]', isReviewMode && 'cursor-not-allowed opacity-70'), children: [_jsx("option", { value: "", children: "\u2014\u2014\u2014" }), wordBank
49
+ .filter((w) => !w.isExample)
50
+ .map((w, wi) => (_jsx("option", { value: w.word, children: w.word }, `${blankIndex}-${wi}`)))] })] }, idx));
51
+ }
52
+ return (_jsxs("span", { className: "mx-1 inline-flex items-baseline gap-1 align-baseline", children: [_jsxs("span", { className: "text-[11px] font-bold text-[#1f7cff]", children: ["(", blankIndex + 1, ")"] }), _jsx("input", { type: "text", value: studentAnswer, disabled: isReviewMode, placeholder: "\u00B7\u00B7\u00B7", onChange: (e) => setBlank(blankIndex, e.target.value), style: { width: `${Math.max(4, studentAnswer.length + 1)}ch` }, className: cn('inline-block min-w-[4ch] max-w-[16ch] border-b-2 bg-transparent px-1 text-center text-sm font-semibold outline-none transition-colors', studentAnswer
53
+ ? 'border-[#1167e8] text-[#0b57d0]'
54
+ : 'border-[#9cc4f5] text-[#64748b]', isReviewMode && 'cursor-not-allowed opacity-70') })] }, idx));
55
+ }) })] }));
56
+ }