@tinyweb_dev/oe-exam-sdk 0.1.2 → 0.1.4

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 (328) hide show
  1. package/README.md +58 -4
  2. package/dist/api/contest-rooms.d.ts +13 -0
  3. package/dist/api/contest-rooms.js +1 -0
  4. package/dist/api/contest-rooms.types.d.ts +47 -0
  5. package/dist/api/contest-rooms.types.js +1 -0
  6. package/dist/api/exam-entry.d.ts +14 -0
  7. package/dist/api/exam-entry.js +1 -0
  8. package/dist/api/exam-entry.types.d.ts +93 -0
  9. package/dist/api/exam-entry.types.js +1 -0
  10. package/dist/api/exam-questions.d.ts +1 -1
  11. package/dist/api/exam-questions.js +1 -1
  12. package/dist/api/exam-questions.types.d.ts +45 -1
  13. package/dist/api/index.d.ts +2 -0
  14. package/dist/api/index.js +1 -1
  15. package/dist/components/exams/CompletionDialog.d.ts +8 -0
  16. package/dist/components/exams/CompletionDialog.js +1 -0
  17. package/dist/components/exams/CreateExamInfoForm.d.ts +4 -1
  18. package/dist/components/exams/CreateExamInfoForm.js +1 -1
  19. package/dist/components/exams/CreateExamPageContainer.d.ts +3 -0
  20. package/dist/components/exams/CreateExamPageContainer.js +1 -1
  21. package/dist/components/exams/ExamCreator.d.ts +9 -3
  22. package/dist/components/exams/ExamCreator.js +1 -1
  23. package/dist/components/exams/ExamPartTabs.d.ts +1 -1
  24. package/dist/components/exams/ExamPartTabs.js +1 -1
  25. package/dist/components/exams/ExamPreviewDialog.d.ts +20 -0
  26. package/dist/components/exams/ExamPreviewDialog.js +1 -0
  27. package/dist/components/exams/ExamQuestionGrid.d.ts +1 -1
  28. package/dist/components/exams/ExamQuestionGrid.js +1 -1
  29. package/dist/components/exams/ExamQuestionsPageContainer.d.ts +3 -0
  30. package/dist/components/exams/ExamQuestionsPageContainer.js +1 -1
  31. package/dist/components/exams/ExamViewDialog.d.ts +24 -0
  32. package/dist/components/exams/ExamViewDialog.js +1 -0
  33. package/dist/components/exams/TemplateSelector.js +1 -1
  34. package/dist/components/exams/UnsavedChangesDialog.d.ts +8 -0
  35. package/dist/components/exams/UnsavedChangesDialog.js +1 -0
  36. package/dist/components/exams/api.d.ts +1 -1
  37. package/dist/components/exams/create-exam.texts.d.ts +58 -0
  38. package/dist/components/exams/create-exam.texts.js +1 -0
  39. package/dist/components/exams/create-exam.validation.js +1 -1
  40. package/dist/components/exams/entry/EntryRestartDialog.d.ts +12 -0
  41. package/dist/components/exams/entry/EntryRestartDialog.js +1 -0
  42. package/dist/components/exams/entry/StudentExamEntryPageContainer.d.ts +31 -0
  43. package/dist/components/exams/entry/StudentExamEntryPageContainer.js +1 -0
  44. package/dist/components/exams/entry/exam-entry.states.d.ts +22 -0
  45. package/dist/components/exams/entry/exam-entry.states.js +1 -0
  46. package/dist/components/exams/entry/exam-entry.utils.d.ts +16 -0
  47. package/dist/components/exams/entry/exam-entry.utils.js +1 -0
  48. package/dist/components/exams/entry/fullscreen-loading.d.ts +5 -0
  49. package/dist/components/exams/entry/fullscreen-loading.js +1 -0
  50. package/dist/components/exams/entry/index.d.ts +7 -0
  51. package/dist/components/exams/entry/index.js +1 -0
  52. package/dist/components/exams/exam-question-status.d.ts +9 -0
  53. package/dist/components/exams/exam-question-status.js +1 -0
  54. package/dist/components/exams/index.d.ts +19 -1
  55. package/dist/components/exams/index.js +1 -1
  56. package/dist/components/exams/rooms/StudentContestRoomsPageContainer.d.ts +18 -0
  57. package/dist/components/exams/rooms/StudentContestRoomsPageContainer.js +1 -0
  58. package/dist/components/exams/rooms/contest-rooms.utils.d.ts +32 -0
  59. package/dist/components/exams/rooms/contest-rooms.utils.js +1 -0
  60. package/dist/components/exams/rooms/index.d.ts +3 -0
  61. package/dist/components/exams/rooms/index.js +1 -0
  62. package/dist/components/exams/take/ExamTakingApiContext.d.ts +10 -0
  63. package/dist/components/exams/take/ExamTakingApiContext.js +1 -0
  64. package/dist/components/exams/take/ExamTakingPageContainer.d.ts +28 -4
  65. package/dist/components/exams/take/ExamTakingPageContainer.js +1 -1
  66. package/dist/components/exams/take/components/QuestionRenderer.d.ts +25 -0
  67. package/dist/components/exams/take/components/QuestionRenderer.js +1 -0
  68. package/dist/components/exams/take/components/index.d.ts +10 -0
  69. package/dist/components/exams/take/components/index.js +1 -0
  70. package/dist/components/exams/take/components/question-renderers/ArticlesViewer.d.ts +7 -0
  71. package/dist/components/exams/take/components/question-renderers/ArticlesViewer.js +1 -0
  72. package/dist/components/exams/take/components/question-renderers/MoversAnswerTheQuestionRenderer.d.ts +22 -0
  73. package/dist/components/exams/take/components/question-renderers/MoversAnswerTheQuestionRenderer.js +1 -0
  74. package/dist/components/exams/take/components/question-renderers/MoversChooseAdjectiveRenderer.d.ts +14 -0
  75. package/dist/components/exams/take/components/question-renderers/MoversChooseAdjectiveRenderer.js +1 -0
  76. package/dist/components/exams/take/components/question-renderers/MoversChooseBestAnswerRenderer.d.ts +2 -0
  77. package/dist/components/exams/take/components/question-renderers/MoversChooseBestAnswerRenderer.js +1 -0
  78. package/dist/components/exams/take/components/question-renderers/MoversColoringRenderer.d.ts +3 -0
  79. package/dist/components/exams/take/components/question-renderers/MoversColoringRenderer.js +1 -0
  80. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.d.ts +2 -0
  81. package/dist/components/exams/take/components/question-renderers/MoversFillWordHintRenderer.js +1 -0
  82. package/dist/components/exams/take/components/question-renderers/MoversGridFillRenderer.d.ts +2 -0
  83. package/dist/components/exams/take/components/question-renderers/MoversGridFillRenderer.js +1 -0
  84. package/dist/components/exams/take/components/question-renderers/MoversLabelThePictureRenderer.d.ts +2 -0
  85. package/dist/components/exams/take/components/question-renderers/MoversLabelThePictureRenderer.js +1 -0
  86. package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.d.ts +21 -0
  87. package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +1 -0
  88. package/dist/components/exams/take/components/question-renderers/MoversMatchByWritingAnswerRenderer.d.ts +19 -0
  89. package/dist/components/exams/take/components/question-renderers/MoversMatchByWritingAnswerRenderer.js +1 -0
  90. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.d.ts +2 -0
  91. package/dist/components/exams/take/components/question-renderers/MoversPictureChooseRenderer.js +1 -0
  92. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.d.ts +2 -0
  93. package/dist/components/exams/take/components/question-renderers/MoversPictureFillBlankChooseRenderer.js +1 -0
  94. package/dist/components/exams/take/components/question-renderers/MoversReadingPassageRenderer.d.ts +2 -0
  95. package/dist/components/exams/take/components/question-renderers/MoversReadingPassageRenderer.js +1 -0
  96. package/dist/components/exams/take/components/question-renderers/MoversTrueFalseRenderer.d.ts +20 -0
  97. package/dist/components/exams/take/components/question-renderers/MoversTrueFalseRenderer.js +1 -0
  98. package/dist/components/exams/take/components/question-renderers/MoversWordFillParagraphRenderer.d.ts +32 -0
  99. package/dist/components/exams/take/components/question-renderers/MoversWordFillParagraphRenderer.js +1 -0
  100. package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.d.ts +18 -0
  101. package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +1 -0
  102. package/dist/components/exams/take/components/question-renderers/MoversWordOrderingRenderer.d.ts +19 -0
  103. package/dist/components/exams/take/components/question-renderers/MoversWordOrderingRenderer.js +1 -0
  104. package/dist/components/exams/take/components/question-renderers/MoversWriteSentencesRenderer.d.ts +22 -0
  105. package/dist/components/exams/take/components/question-renderers/MoversWriteSentencesRenderer.js +1 -0
  106. package/dist/components/exams/take/components/question-renderers/MoversWritingRenderer.d.ts +18 -0
  107. package/dist/components/exams/take/components/question-renderers/MoversWritingRenderer.js +1 -0
  108. package/dist/components/exams/take/components/question-renderers/index.d.ts +19 -0
  109. package/dist/components/exams/take/components/question-renderers/index.js +1 -0
  110. package/dist/components/exams/take/components/speaking/FindObjectInPicture.module.css +133 -0
  111. package/dist/components/exams/take/components/speaking/SpeakingAudioPlayer.d.ts +9 -0
  112. package/dist/components/exams/take/components/speaking/SpeakingAudioPlayer.js +1 -0
  113. package/dist/components/exams/take/components/speaking/SpeakingCompareImages.module.css +153 -0
  114. package/dist/components/exams/take/components/speaking/SpeakingContentFrame.d.ts +7 -0
  115. package/dist/components/exams/take/components/speaking/SpeakingContentFrame.js +1 -0
  116. package/dist/components/exams/take/components/speaking/SpeakingDragObjects.module.css +238 -0
  117. package/dist/components/exams/take/components/speaking/SpeakingExamLayout.d.ts +27 -0
  118. package/dist/components/exams/take/components/speaking/SpeakingExamLayout.js +1 -0
  119. package/dist/components/exams/take/components/speaking/SpeakingHeader.d.ts +6 -0
  120. package/dist/components/exams/take/components/speaking/SpeakingHeader.js +1 -0
  121. package/dist/components/exams/take/components/speaking/SpeakingInfoExchange.module.css +193 -0
  122. package/dist/components/exams/take/components/speaking/SpeakingInfoExchangeSummerSky.module.css +238 -0
  123. package/dist/components/exams/take/components/speaking/SpeakingInstructionBar.d.ts +5 -0
  124. package/dist/components/exams/take/components/speaking/SpeakingInstructionBar.js +1 -0
  125. package/dist/components/exams/take/components/speaking/SpeakingMicButton.d.ts +14 -0
  126. package/dist/components/exams/take/components/speaking/SpeakingMicButton.js +1 -0
  127. package/dist/components/exams/take/components/speaking/SpeakingNavButton.d.ts +7 -0
  128. package/dist/components/exams/take/components/speaking/SpeakingNavButton.js +1 -0
  129. package/dist/components/exams/take/components/speaking/SpeakingPartBadge.d.ts +6 -0
  130. package/dist/components/exams/take/components/speaking/SpeakingPartBadge.js +1 -0
  131. package/dist/components/exams/take/components/speaking/SpeakingReadDisplayedContent.module.css +115 -0
  132. package/dist/components/exams/take/components/speaking/SpeakingRecordingPreview.d.ts +11 -0
  133. package/dist/components/exams/take/components/speaking/SpeakingRecordingPreview.js +1 -0
  134. package/dist/components/exams/take/components/speaking/SpeakingReportErrorButton.d.ts +1 -0
  135. package/dist/components/exams/take/components/speaking/SpeakingReportErrorButton.js +1 -0
  136. package/dist/components/exams/take/components/speaking/SpeakingStoryImages.module.css +231 -0
  137. package/dist/components/exams/take/components/speaking/SpeakingVideoIntro.d.ts +13 -0
  138. package/dist/components/exams/take/components/speaking/SpeakingVideoIntro.js +1 -0
  139. package/dist/components/exams/take/components/speaking/index.d.ts +1 -0
  140. package/dist/components/exams/take/components/speaking/index.js +1 -0
  141. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseAnswerGroupRenderer.d.ts +16 -0
  142. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseAnswerGroupRenderer.js +1 -0
  143. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseObjectsRenderer.d.ts +16 -0
  144. package/dist/components/exams/take/components/speaking/renderers/SpeakingChooseObjectsRenderer.js +1 -0
  145. package/dist/components/exams/take/components/speaking/renderers/SpeakingCompareImagesRenderer.d.ts +17 -0
  146. package/dist/components/exams/take/components/speaking/renderers/SpeakingCompareImagesRenderer.js +1 -0
  147. package/dist/components/exams/take/components/speaking/renderers/SpeakingConversationRenderer.d.ts +16 -0
  148. package/dist/components/exams/take/components/speaking/renderers/SpeakingConversationRenderer.js +1 -0
  149. package/dist/components/exams/take/components/speaking/renderers/SpeakingCueCardRenderer.d.ts +17 -0
  150. package/dist/components/exams/take/components/speaking/renderers/SpeakingCueCardRenderer.js +1 -0
  151. package/dist/components/exams/take/components/speaking/renderers/SpeakingDescribeImageRenderer.d.ts +18 -0
  152. package/dist/components/exams/take/components/speaking/renderers/SpeakingDescribeImageRenderer.js +1 -0
  153. package/dist/components/exams/take/components/speaking/renderers/SpeakingDragObjectsRenderer.d.ts +16 -0
  154. package/dist/components/exams/take/components/speaking/renderers/SpeakingDragObjectsRenderer.js +1 -0
  155. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.d.ts +16 -0
  156. package/dist/components/exams/take/components/speaking/renderers/SpeakingGNInterviewRenderer.js +1 -0
  157. package/dist/components/exams/take/components/speaking/renderers/SpeakingInfoExchangeRenderer.d.ts +16 -0
  158. package/dist/components/exams/take/components/speaking/renderers/SpeakingInfoExchangeRenderer.js +1 -0
  159. package/dist/components/exams/take/components/speaking/renderers/SpeakingListenAndSpeakAnswerRenderer.d.ts +16 -0
  160. package/dist/components/exams/take/components/speaking/renderers/SpeakingListenAndSpeakAnswerRenderer.js +1 -0
  161. package/dist/components/exams/take/components/speaking/renderers/SpeakingOddOneOutRenderer.d.ts +16 -0
  162. package/dist/components/exams/take/components/speaking/renderers/SpeakingOddOneOutRenderer.js +1 -0
  163. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionListRenderer.d.ts +26 -0
  164. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionListRenderer.js +1 -0
  165. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionRenderer.d.ts +32 -0
  166. package/dist/components/exams/take/components/speaking/renderers/SpeakingQuestionRenderer.js +1 -0
  167. package/dist/components/exams/take/components/speaking/renderers/SpeakingReadDisplayedContentRenderer.d.ts +34 -0
  168. package/dist/components/exams/take/components/speaking/renderers/SpeakingReadDisplayedContentRenderer.js +1 -0
  169. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQARenderer.d.ts +17 -0
  170. package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQARenderer.js +1 -0
  171. package/dist/components/exams/take/components/speaking/renderers/SpeakingStoryImagesRenderer.d.ts +17 -0
  172. package/dist/components/exams/take/components/speaking/renderers/SpeakingStoryImagesRenderer.js +1 -0
  173. package/dist/components/exams/take/components/speaking/renderers/index.d.ts +13 -0
  174. package/dist/components/exams/take/components/speaking/renderers/index.js +1 -0
  175. package/dist/components/exams/take/hooks/index.d.ts +2 -0
  176. package/dist/components/exams/take/hooks/index.js +1 -0
  177. package/dist/components/exams/take/hooks/useAnswerAutosave.d.ts +27 -0
  178. package/dist/components/exams/take/hooks/useAnswerAutosave.js +1 -0
  179. package/dist/components/exams/take/hooks/useAttemptSubmit.d.ts +29 -0
  180. package/dist/components/exams/take/hooks/useAttemptSubmit.js +1 -0
  181. package/dist/components/exams/take/hooks/useAutoSave.d.ts +20 -0
  182. package/dist/components/exams/take/hooks/useAutoSave.js +1 -0
  183. package/dist/components/exams/take/hooks/useExamCountdown.d.ts +22 -0
  184. package/dist/components/exams/take/hooks/useExamCountdown.js +1 -0
  185. package/dist/components/exams/take/hooks/useExamTimer.d.ts +21 -0
  186. package/dist/components/exams/take/hooks/useExamTimer.js +1 -0
  187. package/dist/components/exams/take/hooks/useProctoringCamera.d.ts +19 -0
  188. package/dist/components/exams/take/hooks/useProctoringCamera.js +1 -0
  189. package/dist/components/exams/take/hooks/useProctoringSnapshot.d.ts +25 -0
  190. package/dist/components/exams/take/hooks/useProctoringSnapshot.js +1 -0
  191. package/dist/components/exams/take/hooks/useSpeakingConversationAudio.d.ts +19 -0
  192. package/dist/components/exams/take/hooks/useSpeakingConversationAudio.js +1 -0
  193. package/dist/components/exams/take/hooks/useSpeakingNavigation.d.ts +37 -0
  194. package/dist/components/exams/take/hooks/useSpeakingNavigation.js +1 -0
  195. package/dist/components/exams/take/hooks/useSpeakingRecorder.d.ts +45 -5
  196. package/dist/components/exams/take/hooks/useSpeakingRecorder.js +1 -1
  197. package/dist/components/exams/take/hooks/useSpeakingRendererSetup.d.ts +39 -0
  198. package/dist/components/exams/take/hooks/useSpeakingRendererSetup.js +1 -0
  199. package/dist/components/exams/take/hooks/useToeicAudio.d.ts +17 -0
  200. package/dist/components/exams/take/hooks/useToeicAudio.js +1 -0
  201. package/dist/components/exams/take/index.d.ts +9 -1
  202. package/dist/components/exams/take/index.js +1 -1
  203. package/dist/components/exams/take/types/speaking-cue-card.types.d.ts +10 -0
  204. package/dist/components/exams/take/types/speaking-cue-card.types.js +1 -0
  205. package/dist/components/exams/take/types/speaking.types.d.ts +153 -0
  206. package/dist/components/exams/take/types/speaking.types.js +1 -0
  207. package/dist/components/exams/take/types.d.ts +286 -1
  208. package/dist/components/exams/take/utils/answer-transformers.d.ts +26 -0
  209. package/dist/components/exams/take/utils/answer-transformers.js +1 -0
  210. package/dist/components/exams/take/utils/coloring-assignments.d.ts +5 -0
  211. package/dist/components/exams/take/utils/coloring-assignments.js +1 -0
  212. package/dist/components/exams/take/utils/question-transformers.d.ts +362 -0
  213. package/dist/components/exams/take/utils/question-transformers.js +1 -0
  214. package/dist/components/features/exam-entry/entry-state-cards.d.ts +19 -0
  215. package/dist/components/features/exam-entry/entry-state-cards.js +1 -0
  216. package/dist/components/features/exam-entry/index.d.ts +2 -0
  217. package/dist/components/features/exam-entry/index.js +1 -0
  218. package/dist/components/features/exam-entry/themed/CambridgeYleWaitingRoom.d.ts +12 -0
  219. package/dist/components/features/exam-entry/themed/CambridgeYleWaitingRoom.js +1 -0
  220. package/dist/components/features/exam-entry/themed/ThemedWaitingRoom.d.ts +14 -0
  221. package/dist/components/features/exam-entry/themed/ThemedWaitingRoom.js +1 -0
  222. package/dist/components/features/exam-entry/themed/ToeicWaitingRoom.d.ts +16 -0
  223. package/dist/components/features/exam-entry/themed/ToeicWaitingRoom.js +1 -0
  224. package/dist/components/features/exam-entry/themed/components/CloseButton.d.ts +9 -0
  225. package/dist/components/features/exam-entry/themed/components/CloseButton.js +1 -0
  226. package/dist/components/features/exam-entry/themed/components/ExamInfoPanel.d.ts +13 -0
  227. package/dist/components/features/exam-entry/themed/components/ExamInfoPanel.js +1 -0
  228. package/dist/components/features/exam-entry/themed/components/ModeSelector.d.ts +7 -0
  229. package/dist/components/features/exam-entry/themed/components/ModeSelector.js +1 -0
  230. package/dist/components/features/exam-entry/themed/components/StartButton.d.ts +11 -0
  231. package/dist/components/features/exam-entry/themed/components/StartButton.js +1 -0
  232. package/dist/components/features/exam-entry/themed/components/index.d.ts +4 -0
  233. package/dist/components/features/exam-entry/themed/components/index.js +1 -0
  234. package/dist/components/features/exam-entry/themed/index.d.ts +1 -0
  235. package/dist/components/features/exam-entry/themed/index.js +1 -0
  236. package/dist/components/results/ResultReviewPageContainer.d.ts +3 -1
  237. package/dist/components/results/ResultReviewPageContainer.js +1 -1
  238. package/dist/components/results/hooks/useResultReviewPolling.d.ts +27 -0
  239. package/dist/components/results/hooks/useResultReviewPolling.js +1 -0
  240. package/dist/components/results/index.d.ts +3 -0
  241. package/dist/components/results/index.js +1 -1
  242. package/dist/components/results/review-status.utils.d.ts +12 -0
  243. package/dist/components/results/review-status.utils.js +1 -0
  244. package/dist/components/shared/audio/SpeakingAudioPlayer.d.ts +12 -0
  245. package/dist/components/shared/audio/SpeakingAudioPlayer.js +1 -0
  246. package/dist/components/shared/audio/SpeakingAudioPlayer.module.css +115 -0
  247. package/dist/components/shared/audio/assets/fr-image-part1-border.png +0 -0
  248. package/dist/components/shared/audio/assets/ic-speaker.webp +0 -0
  249. package/dist/components/themes/cambridge-yle/CambridgeYleTimer.js +1 -1
  250. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.d.ts +11 -3
  251. package/dist/components/themes/english-certification/EnglishCertificationAudioPlayer.js +1 -1
  252. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.d.ts +5 -1
  253. package/dist/components/themes/english-certification/EnglishCertificationQuestionRenderer.js +1 -1
  254. package/dist/components/themes/index.d.ts +11 -0
  255. package/dist/components/themes/index.js +1 -1
  256. package/dist/components/themes/spaceship/SpaceshipAudioPlayer.d.ts +8 -0
  257. package/dist/components/themes/spaceship/SpaceshipAudioPlayer.js +1 -0
  258. package/dist/components/themes/spaceship/SpaceshipLayout.d.ts +2 -0
  259. package/dist/components/themes/spaceship/SpaceshipLayout.js +1 -0
  260. package/dist/components/themes/spaceship/assets/images/X-sunset.png +0 -0
  261. package/dist/components/themes/spaceship/assets/images/X.webp +0 -0
  262. package/dist/components/themes/spaceship/assets/images/audio-bar.webp +0 -0
  263. package/dist/components/themes/spaceship/assets/images/background.webp +0 -0
  264. package/dist/components/themes/spaceship/assets/images/bg_sunset.png +0 -0
  265. package/dist/components/themes/spaceship/assets/images/big-blue-badge-sunset.png +0 -0
  266. package/dist/components/themes/spaceship/assets/images/big-blue-badge.png +0 -0
  267. package/dist/components/themes/spaceship/assets/images/big-blue-badge.webp +0 -0
  268. package/dist/components/themes/spaceship/assets/images/bingo.webp +0 -0
  269. package/dist/components/themes/spaceship/assets/images/blue-badge-sunset.png +0 -0
  270. package/dist/components/themes/spaceship/assets/images/blue-badge.png +0 -0
  271. package/dist/components/themes/spaceship/assets/images/blue-wrapper-sunset.png +0 -0
  272. package/dist/components/themes/spaceship/assets/images/blue-wrapper.webp +0 -0
  273. package/dist/components/themes/spaceship/assets/images/board_red.png +0 -0
  274. package/dist/components/themes/spaceship/assets/images/button_feedback_vi.png +0 -0
  275. package/dist/components/themes/spaceship/assets/images/circle-btn-right-sunset.png +0 -0
  276. package/dist/components/themes/spaceship/assets/images/circle-btn-right.png +0 -0
  277. package/dist/components/themes/spaceship/assets/images/circle-btn-sunset.png +0 -0
  278. package/dist/components/themes/spaceship/assets/images/circle-btn.webp +0 -0
  279. package/dist/components/themes/spaceship/assets/images/focus-vector.webp +0 -0
  280. package/dist/components/themes/spaceship/assets/images/head-phone_red.png +0 -0
  281. package/dist/components/themes/spaceship/assets/images/ic-mute-sunset.png +0 -0
  282. package/dist/components/themes/spaceship/assets/images/ic-mute.png +0 -0
  283. package/dist/components/themes/spaceship/assets/images/ic-play-sunset.png +0 -0
  284. package/dist/components/themes/spaceship/assets/images/ic-play-violet.webp +0 -0
  285. package/dist/components/themes/spaceship/assets/images/ic-play.webp +0 -0
  286. package/dist/components/themes/spaceship/assets/images/micro.png +0 -0
  287. package/dist/components/themes/spaceship/assets/images/next-small.webp +0 -0
  288. package/dist/components/themes/spaceship/assets/images/next-sunset.png +0 -0
  289. package/dist/components/themes/spaceship/assets/images/next.webp +0 -0
  290. package/dist/components/themes/spaceship/assets/images/purple-circle.webp +0 -0
  291. package/dist/components/themes/spaceship/assets/images/question-badge-sunset.png +0 -0
  292. package/dist/components/themes/spaceship/assets/images/question-badge.webp +0 -0
  293. package/dist/components/themes/spaceship/assets/images/red-badge-sunset.png +0 -0
  294. package/dist/components/themes/spaceship/assets/images/red-badge.webp +0 -0
  295. package/dist/components/themes/spaceship/assets/images/red-wrapper-sunset.png +0 -0
  296. package/dist/components/themes/spaceship/assets/images/red-wrapper.webp +0 -0
  297. package/dist/components/themes/spaceship/assets/images/robot-avatar.png +0 -0
  298. package/dist/components/themes/spaceship/assets/images/sound_red.png +0 -0
  299. package/dist/components/themes/spaceship/assets/images/student-avatar.png +0 -0
  300. package/dist/components/themes/spaceship/assets/images/teacher-play-sunset.png +0 -0
  301. package/dist/components/themes/spaceship/assets/images/teacher-play.webp +0 -0
  302. package/dist/components/themes/spaceship/assets/images/timer-badge.png +0 -0
  303. package/dist/components/themes/spaceship/assets/styles/SpaceshipLayout.module.css +347 -0
  304. package/dist/components/themes/spaceship/assets/styles/SpaceshipWaitingRoom.module.css +395 -0
  305. package/dist/components/ui/badge.d.ts +1 -1
  306. package/dist/index.d.ts +4 -4
  307. package/dist/index.js +1 -1
  308. package/dist/shared/index.d.ts +3 -0
  309. package/dist/shared/index.js +1 -1
  310. package/dist/shared/lib/stores/examTakingStore.d.ts +54 -0
  311. package/dist/shared/lib/stores/examTakingStore.js +1 -0
  312. package/dist/shared/lib/stores/gradingTransientStore.d.ts +23 -0
  313. package/dist/shared/lib/stores/gradingTransientStore.js +1 -0
  314. package/dist/shared/lib/themes/config/starters.config.d.ts +3 -0
  315. package/dist/shared/lib/themes/config/starters.config.js +1 -0
  316. package/dist/shared/lib/themes/index.d.ts +18 -0
  317. package/dist/shared/lib/themes/index.js +1 -0
  318. package/dist/shared/lib/themes/types.d.ts +39 -0
  319. package/dist/shared/lib/themes/types.js +1 -0
  320. package/dist/shared/lib/toast.d.ts +19 -0
  321. package/dist/shared/lib/toast.js +1 -0
  322. package/dist/shared/lib/utils/question-reverse-transform.d.ts +6 -0
  323. package/dist/shared/lib/utils/question-reverse-transform.js +1 -0
  324. package/dist/shared/lib/utils/question-transform-validation.d.ts +6 -0
  325. package/dist/shared/lib/utils/question-transform-validation.js +1 -0
  326. package/dist/shared/lib/utils/question-transform.d.ts +6 -2
  327. package/dist/shared/lib/utils/question-transform.js +1 -1
  328. package/package.json +19 -4
@@ -7,7 +7,7 @@ import { type VariantProps } from 'class-variance-authority';
7
7
  * No border by default
8
8
  */
9
9
  declare const badgeVariants: (props?: {
10
- variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "info" | "warning" | "dark";
10
+ variant?: "default" | "destructive" | "outline" | "secondary" | "warning" | "success" | "info" | "dark";
11
11
  } & import("class-variance-authority/types").ClassProp) => string;
12
12
  export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
13
13
  }
package/dist/index.d.ts CHANGED
@@ -6,10 +6,10 @@ export * as Questions from './components/questions';
6
6
  export * as Results from './components/results';
7
7
  export * as Themes from './components/themes';
8
8
  export * as Shared from './shared';
9
- export { buildExamTemplatePayload, createExamCreateApi, createExamQuestionsApi, createExamQuestionsFetchApi, createExamTakingApi, createMockCreateExamApi, createMockExamQuestionsApi, createMockExamTakingApi, createMockResultReviewApi, createResultReviewApi } from './api';
10
- export type { AnswerGradingStatusItem, AnswersGradingStatusResult, CreateExamFetchApiOptions, CreateExamPayload, CreateExamSdkApi, ExamFormData, ExamLevelOption, ExamQuestionsSdkApi, ExamResponse, ExamTakingAnswerValue, ExamTakingAttempt, ExamTakingFetchApiOptions, ExamTakingQuestion, ExamTakingQuestionsResult, ExamTakingRoom, ExamTakingSdkApi, ExamTakingTemplatePart, ExamTemplatePayload, ExamWithTemplate, FetchApiOptions, GradingSummary, SaveExamInput, SaveExamTakingAnswersInput, SaveQuestionInput, SubmitExamTakingAttemptResult, UpdateExamTemplateInput, UpdatePartAudioInput, UploadAudioAnswerResult } from './api';
11
- export { CreateExamPageContainer, ExamQuestionsPageContainer, ExamTakingPageContainer } from './components/exams';
12
- export type { CreateExamPageContainerProps, ExamQuestionsPageContainerProps, ExamTakingPageContainerProps } from './components/exams';
9
+ export { buildExamTemplatePayload, createContestRoomsApi, createExamCreateApi, createExamEntryApi, createExamQuestionsApi, createExamQuestionsFetchApi, createExamTakingApi, createMockContestRoomsApi, createMockCreateExamApi, createMockExamEntryApi, createMockExamQuestionsApi, createMockExamTakingApi, createMockResultReviewApi, createResultReviewApi } from './api';
10
+ export type { AnswerGradingStatusItem, AnswersGradingStatusResult, ContestRoomListItem, ContestRoomRegistrationStatus, ContestRoomVisibility, ContestRoomsContestDetail, ContestRoomsFetchApiOptions, ContestRoomsSdkApi, CreateExamFetchApiOptions, CreateExamPayload, CreateExamSdkApi, ExamFormData, ExamLevelOption, ExamQuestionsSdkApi, ExamResponse, ExamTakingAnswerValue, ExamTakingAttempt, ExamTakingFetchApiOptions, ExamTakingQuestion, ExamTakingQuestionsResult, ExamTakingRoom, ExamTakingSdkApi, ExamTakingTemplatePart, ExamTemplatePayload, ExamWithTemplate, ExistingQuestionBank, FetchApiOptions, GradingSummary, QuestionSearchItem, SaveExamInput, SaveExamTakingAnswersInput, SaveQuestionInput, SaveQuestionResult, SearchQuestionBankInput, SearchQuestionBankResult, SubmitExamTakingAttemptResult, UpdateExamTemplateInput, UpdatePartAudioInput, UploadAudioAnswerResult } from './api';
11
+ export { CreateExamPageContainer, ExamPreviewDialog, ExamQuestionsPageContainer, ExamTakingPageContainer, ExamViewDialog, StudentContestRoomsPageContainer, StudentExamEntryPageContainer } from './components/exams';
12
+ export type { CreateExamPageContainerProps, CreateExamTexts, ExamPreviewDialogProps, ExamQuestionsPageContainerProps, ExamTakingPageContainerProps, ExamViewDialogExam, ExamViewDialogProps, StudentContestRoomsPageContainerProps, StudentExamEntryPageContainerProps } from './components/exams';
13
13
  export { ResultReviewPageContainer } from './components/results';
14
14
  export type { ResultReviewPageContainerProps } from './components/results';
15
15
  export { QuestionCreator } from './components/questions/creator/QuestionCreator';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export*as Api from"./api";export*as Components from"./components";export*as Mcp from"./mcp";export*as Exams from"./components/exams";export*as Questions from"./components/questions";export*as Results from"./components/results";export*as Themes from"./components/themes";export*as Shared from"./shared";export{buildExamTemplatePayload,createExamCreateApi,createExamQuestionsApi,createExamQuestionsFetchApi,createExamTakingApi,createMockCreateExamApi,createMockExamQuestionsApi,createMockExamTakingApi,createMockResultReviewApi,createResultReviewApi}from"./api";export{CreateExamPageContainer,ExamQuestionsPageContainer,ExamTakingPageContainer}from"./components/exams";export{ResultReviewPageContainer}from"./components/results";export{QuestionCreator}from"./components/questions/creator/QuestionCreator";export{QuestionGroupCreator}from"./components/questions/creator/QuestionGroupCreator";export{renderDedicatedComponent}from"./components/questions/creator/dedicated-component-router";export{questionTypeRegistry}from"./components/questions/creator/question-type-registry";export{QUESTION_TYPE_CONFIG,QUESTION_TYPES_WITH_DEDICATED_COMPONENTS}from"./components/questions/_shared/config/question-types.config";export{validateQuestion}from"./components/questions/_shared/utils/question-validation";export{buildAnswerPayload}from"./components/questions/_shared/utils/answer-builder";export*from"./components/questions/_shared/types";
1
+ export*as Api from"./api";export*as Components from"./components";export*as Mcp from"./mcp";export*as Exams from"./components/exams";export*as Questions from"./components/questions";export*as Results from"./components/results";export*as Themes from"./components/themes";export*as Shared from"./shared";export{buildExamTemplatePayload,createContestRoomsApi,createExamCreateApi,createExamEntryApi,createExamQuestionsApi,createExamQuestionsFetchApi,createExamTakingApi,createMockContestRoomsApi,createMockCreateExamApi,createMockExamEntryApi,createMockExamQuestionsApi,createMockExamTakingApi,createMockResultReviewApi,createResultReviewApi}from"./api";export{CreateExamPageContainer,ExamPreviewDialog,ExamQuestionsPageContainer,ExamTakingPageContainer,ExamViewDialog,StudentContestRoomsPageContainer,StudentExamEntryPageContainer}from"./components/exams";export{ResultReviewPageContainer}from"./components/results";export{QuestionCreator}from"./components/questions/creator/QuestionCreator";export{QuestionGroupCreator}from"./components/questions/creator/QuestionGroupCreator";export{renderDedicatedComponent}from"./components/questions/creator/dedicated-component-router";export{questionTypeRegistry}from"./components/questions/creator/question-type-registry";export{QUESTION_TYPE_CONFIG,QUESTION_TYPES_WITH_DEDICATED_COMPONENTS}from"./components/questions/_shared/config/question-types.config";export{validateQuestion}from"./components/questions/_shared/utils/question-validation";export{buildAnswerPayload}from"./components/questions/_shared/utils/answer-builder";export*from"./components/questions/_shared/types";
@@ -5,3 +5,6 @@ export * from './constants/routes';
5
5
  export * from './lib/utils';
6
6
  export * from '../components/questions/_shared';
7
7
  export * from './types';
8
+ export * from './lib/utils/question-transform';
9
+ export * from './lib/utils/question-reverse-transform';
10
+ export * from './lib/utils/question-transform-validation';
@@ -1 +1 @@
1
- export*from"./constants/ApiConstant";export*from"./constants/QueryKeyConstant";export*from"./constants/exam-level.enum";export*from"./constants/routes";export*from"./lib/utils";export*from"../components/questions/_shared";export*from"./types";
1
+ export*from"./constants/ApiConstant";export*from"./constants/QueryKeyConstant";export*from"./constants/exam-level.enum";export*from"./constants/routes";export*from"./lib/utils";export*from"../components/questions/_shared";export*from"./types";export*from"./lib/utils/question-transform";export*from"./lib/utils/question-reverse-transform";export*from"./lib/utils/question-transform-validation";
@@ -0,0 +1,54 @@
1
+ import type { StudentQuestion, InitializeData, StoreTemplatePart } from '../../types/exam-taking.types';
2
+ interface ExamTakingState {
3
+ attemptId: string | null;
4
+ examRoomId: string | null;
5
+ questions: StudentQuestion[];
6
+ answers: Record<string, any>;
7
+ currentIndex: number;
8
+ remainingSeconds: number;
9
+ endsAt: number | null;
10
+ isInitialized: boolean;
11
+ isDirty: boolean;
12
+ lastSavedAt: Date | null;
13
+ isSubmitting: boolean;
14
+ isNavDisabled: boolean;
15
+ flaggedQuestions: Set<string>;
16
+ currentPartIndex: number;
17
+ currentQuestionGlobalIndex: number;
18
+ playedIntroParts: Set<number>;
19
+ playedListeningAudioParts: Set<string>;
20
+ examType: string | null;
21
+ examTitle: string | null;
22
+ parts: StoreTemplatePart[];
23
+ hydrateFromServer: (data: InitializeData) => void;
24
+ setAnswer: (questionId: string, answer: any) => void;
25
+ nextQuestion: () => void;
26
+ prevQuestion: () => void;
27
+ goToQuestion: (index: number) => void;
28
+ syncRemainingSeconds: () => number;
29
+ markSaved: () => void;
30
+ setIsSubmitting: (value: boolean) => void;
31
+ setIsNavDisabled: (value: boolean) => void;
32
+ toggleFlag: (questionId: string) => void;
33
+ setCurrentPartIndex: (index: number) => void;
34
+ setCurrentQuestionGlobalIndex: (index: number) => void;
35
+ markIntroPlayed: (partIndex: number) => void;
36
+ markListeningAudioPlayed: (partId: string) => void;
37
+ setExamType: (type: string) => void;
38
+ setParts: (parts: StoreTemplatePart[]) => void;
39
+ reset: () => void;
40
+ }
41
+ export declare const useExamTakingStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ExamTakingState>, "setState" | "persist"> & {
42
+ setState(partial: ExamTakingState | Partial<ExamTakingState> | ((state: ExamTakingState) => ExamTakingState | Partial<ExamTakingState>), replace?: false): unknown;
43
+ setState(state: ExamTakingState | ((state: ExamTakingState) => ExamTakingState), replace: true): unknown;
44
+ persist: {
45
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ExamTakingState, unknown, unknown>>) => void;
46
+ clearStorage: () => void;
47
+ rehydrate: () => Promise<void> | void;
48
+ hasHydrated: () => boolean;
49
+ onHydrate: (fn: (state: ExamTakingState) => void) => () => void;
50
+ onFinishHydration: (fn: (state: ExamTakingState) => void) => () => void;
51
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<ExamTakingState, unknown, unknown>>;
52
+ };
53
+ }>;
54
+ export {};
@@ -0,0 +1 @@
1
+ import{create as e}from"zustand";import{persist as t,createJSONStorage as n}from"zustand/middleware";const a="__set__",r=n(()=>localStorage,{replacer:(e,t)=>t instanceof Set?{[a]:Array.from(t)}:t,reviver:(e,t)=>t&&"object"==typeof t&&Array.isArray(t[a])?new Set(t[a]):t});export const useExamTakingStore=e()(t((e,t)=>({attemptId:null,examRoomId:null,questions:[],answers:{},currentIndex:0,remainingSeconds:0,endsAt:null,isInitialized:!1,isDirty:!1,lastSavedAt:null,isSubmitting:!1,isNavDisabled:!1,flaggedQuestions:new Set,currentPartIndex:0,currentQuestionGlobalIndex:0,playedIntroParts:new Set,playedListeningAudioParts:new Set,examType:null,examTitle:null,parts:[],hydrateFromServer:n=>{const a=new Date(n.startedAt),r=60*n.durationMinutes*1e3,s=a.getTime()+r,i=Date.now(),d=Math.max(0,s-i),o=Math.floor(d/1e3),l=t(),u=l.attemptId===n.attemptId;e({attemptId:n.attemptId,examRoomId:n.examRoomId,questions:n.questions,remainingSeconds:o,endsAt:s,isInitialized:!0,isDirty:!1,lastSavedAt:null,isSubmitting:!1,isNavDisabled:!1,examType:n.examType??null,examTitle:n.examTitle??null,parts:n.parts??[],answers:u?l.answers:{},currentIndex:u?l.currentIndex:0,currentPartIndex:u?l.currentPartIndex:0,currentQuestionGlobalIndex:u?l.currentQuestionGlobalIndex:0,flaggedQuestions:u?l.flaggedQuestions:new Set,playedIntroParts:u?l.playedIntroParts:new Set,playedListeningAudioParts:u?l.playedListeningAudioParts:new Set})},setAnswer:(t,n)=>{e(e=>({answers:{...e.answers,[t]:n},isDirty:!0}))},nextQuestion:()=>{e(e=>{const t=e.currentIndex+1;return t<e.questions.length?{currentIndex:t}:e})},prevQuestion:()=>{e(e=>{const t=e.currentIndex-1;return t>=0?{currentIndex:t}:e})},goToQuestion:t=>{e(e=>t>=0&&t<e.questions.length?{currentIndex:t}:e)},syncRemainingSeconds:()=>{const{endsAt:n,remainingSeconds:a}=t();if(null==n)return a;const r=Math.max(0,Math.round((n-Date.now())/1e3));return e({remainingSeconds:r}),r},markSaved:()=>{e({isDirty:!1,lastSavedAt:new Date})},setIsSubmitting:t=>{e({isSubmitting:t})},setIsNavDisabled:t=>{e({isNavDisabled:t})},toggleFlag:t=>{e(e=>{const n=new Set(e.flaggedQuestions);return n.has(t)?n.delete(t):n.add(t),{flaggedQuestions:n}})},setCurrentPartIndex:t=>{e({currentPartIndex:t})},setCurrentQuestionGlobalIndex:t=>{e({currentQuestionGlobalIndex:t})},markIntroPlayed:t=>{e(e=>{if(e.playedIntroParts.has(t))return e;const n=new Set(e.playedIntroParts);return n.add(t),{playedIntroParts:n}})},markListeningAudioPlayed:t=>{e(e=>{if(e.playedListeningAudioParts.has(t))return e;const n=new Set(e.playedListeningAudioParts);return n.add(t),{playedListeningAudioParts:n}})},setExamType:t=>{e({examType:t})},setParts:t=>{e({parts:t})},reset:()=>{e({attemptId:null,examRoomId:null,questions:[],answers:{},currentIndex:0,remainingSeconds:0,endsAt:null,isInitialized:!1,isDirty:!1,lastSavedAt:null,isSubmitting:!1,isNavDisabled:!1,flaggedQuestions:new Set,currentPartIndex:0,currentQuestionGlobalIndex:0,playedIntroParts:new Set,playedListeningAudioParts:new Set,examType:null,examTitle:null,parts:[]}),useExamTakingStore.persist.clearStorage()}}),{name:"exam-taking-storage",storage:r,partialize:e=>({attemptId:e.attemptId,examRoomId:e.examRoomId,answers:e.answers,currentIndex:e.currentIndex,currentPartIndex:e.currentPartIndex,currentQuestionGlobalIndex:e.currentQuestionGlobalIndex,flaggedQuestions:e.flaggedQuestions,playedIntroParts:e.playedIntroParts,playedListeningAudioParts:e.playedListeningAudioParts,examType:e.examType,examTitle:e.examTitle})}));
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Transient (in-memory only) store for handing off `pendingAnswerIds`
3
+ * from the submit page to the result page after fire-and-forget submit.
4
+ *
5
+ * Why a store instead of query params or localStorage?
6
+ * - Query params: pollute URL, large lists overflow
7
+ * - localStorage: leaks across tabs/sessions, hard to invalidate
8
+ * - Zustand transient: cheap, auto-clears on tab close, scoped to this attempt
9
+ *
10
+ * Falls back to GET /grading-summary if user navigates directly to result page
11
+ * (e.g. refresh, deep link, new tab) and the store is empty.
12
+ */
13
+ interface GradingTransientState {
14
+ /** Map attemptId → pending answer IDs (just-submitted handoff) */
15
+ pendingByAttempt: Record<string, string[]>;
16
+ /** Last time setPending was called for an attempt (for TTL cleanup) */
17
+ setAtByAttempt: Record<string, number>;
18
+ setPending: (attemptId: string, answerIds: string[]) => void;
19
+ getPending: (attemptId: string) => string[] | undefined;
20
+ clear: (attemptId: string) => void;
21
+ }
22
+ export declare const useGradingTransientStore: import("zustand").UseBoundStore<import("zustand").StoreApi<GradingTransientState>>;
23
+ export {};
@@ -0,0 +1 @@
1
+ import{create as t}from"zustand";export const useGradingTransientStore=t((t,e)=>({pendingByAttempt:{},setAtByAttempt:{},setPending:(e,n)=>{t(t=>({pendingByAttempt:{...t.pendingByAttempt,[e]:n},setAtByAttempt:{...t.setAtByAttempt,[e]:Date.now()}}))},getPending:t=>{const n=e().setAtByAttempt[t];if(n){if(!(Date.now()-n>3e5))return e().pendingByAttempt[t];e().clear(t)}},clear:e=>{t(t=>{const{[e]:n,...p}=t.pendingByAttempt,{[e]:A,...m}=t.setAtByAttempt;return{pendingByAttempt:p,setAtByAttempt:m}})}}));
@@ -0,0 +1,3 @@
1
+ import type { ThemeConfig } from '../types';
2
+ export declare const startersTheme: ThemeConfig;
3
+ export declare const commonTheme: ThemeConfig;
@@ -0,0 +1 @@
1
+ import e from"../../../../components/themes/cambridge-yle/assets/images/background-ocean-edu-2.png";import r from"../../../../components/themes/cambridge-yle/assets/images/bg-title.png";import t from"../../../../components/themes/cambridge-yle/assets/images/border.png";import s from"../../../../components/themes/cambridge-yle/assets/images/close.png";import a from"../../../../components/themes/cambridge-yle/assets/images/rocket.png";import o from"../../../../components/themes/cambridge-yle/assets/images/icon-bottom-left.png";import c from"../../../../components/themes/cambridge-yle/assets/images/icon-bottom-right.png";import m from"../../../../components/themes/cambridge-yle/assets/images/button_feedback_vi.png";export const startersTheme={id:"starters",displayName:"STARTERS",colors:{primary:"#0473f9",secondary:"#0ea5e9",background:"#e0f2fe",text:"#002249",cardBg:"#0473f9",cardBorder:"#1d4ed8"},assets:{background:e.src,cardFrame:t.src,titleBar:r.src,logo:r.src,closeButton:s.src,startIcon:a.src,bottomLeft:o.src,bottomRight:c.src,feedbackButton:m.src},visuals:{backgroundFilter:"blur(2px) brightness(0.8) saturate(0.9)",backgroundOverlay:"linear-gradient(to bottom, rgba(23, 37, 84, 0.5), rgba(30, 58, 138, 0.4), rgba(23, 37, 84, 0.6))",cardBackground:"radial-gradient(60% 60% at 50% 40%, rgba(56, 189, 248, 0.90) 0%, rgba(4, 115, 249, 0.92) 100%)"}};export const commonTheme={id:"common",displayName:"NHIỆM VỤ ĐẦU",colors:{primary:"#0473f9",secondary:"#0ea5e9",background:"#e0f2fe",text:"#002249",cardBg:"#0473f9",cardBorder:"#1d4ed8"},assets:{background:e.src,cardFrame:t.src,titleBar:r.src,logo:r.src,closeButton:s.src,startIcon:a.src,bottomLeft:o.src,bottomRight:c.src,feedbackButton:m.src},visuals:{backgroundFilter:"blur(2px) brightness(0.8) saturate(0.9)",backgroundOverlay:"linear-gradient(to bottom, rgba(23, 37, 84, 0.5), rgba(30, 58, 138, 0.4), rgba(23, 37, 84, 0.6))",cardBackground:"radial-gradient(60% 60% at 50% 40%, rgba(56, 189, 248, 0.90) 0%, rgba(4, 115, 249, 0.92) 100%)"}};
@@ -0,0 +1,18 @@
1
+ import type { ThemeConfig } from './types';
2
+ export declare function normalizeExamTheme(theme?: string | null): string;
3
+ export declare function getThemeConfigByExamTheme(_theme?: string | null): ThemeConfig | null;
4
+ export declare function resolveThemeConfig(options: {
5
+ examTheme?: string | null;
6
+ templateTheme?: string | null;
7
+ level?: string | null;
8
+ }): ThemeConfig;
9
+ /**
10
+ * Get theme based on exam level string
11
+ * Maps Cambridge YLE levels to themes
12
+ */
13
+ export declare function getThemeForLevel(level?: string): ThemeConfig;
14
+ /**
15
+ * Get default theme (starters)
16
+ */
17
+ export declare function getTheme(): ThemeConfig;
18
+ export type { ThemeConfig, ExamTheme, ThemeColors, ThemeAssets, ThemeVisuals } from './types';
@@ -0,0 +1 @@
1
+ import{commonTheme as e,startersTheme as r}from"./config/starters.config";const t={common:e,starters:r,movers:r,flyers:r};export function normalizeExamTheme(e){return"string"==typeof e?e.trim().toUpperCase():""}export function getThemeConfigByExamTheme(e){return null}export function resolveThemeConfig(e){return getThemeConfigByExamTheme(e.examTheme)??getThemeConfigByExamTheme(e.templateTheme)??getThemeForLevel(e.level??void 0)}export function getThemeForLevel(r){if(!r)return e;const n=r.toLowerCase();return n.includes("pre-a1")||n.includes("a1")||n.includes("starter")?t.starters:n.includes("a2")||n.includes("mover")?t.movers:n.includes("b1")||n.includes("b2")||n.includes("flyer")?t.flyers:e}export function getTheme(){return r}
@@ -0,0 +1,39 @@
1
+ export type ExamTheme = 'common' | 'starters' | 'movers' | 'flyers';
2
+ export interface ThemeColors {
3
+ primary: string;
4
+ secondary: string;
5
+ background: string;
6
+ text: string;
7
+ cardBg: string;
8
+ cardBorder: string;
9
+ }
10
+ export interface ThemeAssets {
11
+ background: string;
12
+ cardFrame: string;
13
+ titleBar: string;
14
+ logo: string;
15
+ closeButton: string;
16
+ startIcon: string;
17
+ bottomLeft: string;
18
+ bottomRight: string;
19
+ feedbackButton?: string;
20
+ }
21
+ export interface ThemeVisuals {
22
+ /** CSS filter applied to the fullscreen background image */
23
+ backgroundFilter?: string;
24
+ /** CSS background value rendered above the fullscreen background image */
25
+ backgroundOverlay?: string;
26
+ /** CSS background value used for the main waiting-room card surface */
27
+ cardBackground?: string;
28
+ }
29
+ export interface ThemeConfig {
30
+ id: ExamTheme;
31
+ displayName: string;
32
+ colors: ThemeColors;
33
+ assets: ThemeAssets;
34
+ visuals?: ThemeVisuals;
35
+ /** CSS filter applied to the close button and card frame border images */
36
+ assetFilter?: string;
37
+ /** CSS filter applied specifically to the title bar image (may differ from assetFilter) */
38
+ titleBarFilter?: string;
39
+ }
@@ -0,0 +1 @@
1
+ export{};
@@ -0,0 +1,19 @@
1
+ export declare const toast: {
2
+ success: (message: string, description?: string) => string | number;
3
+ error: (message: string, description?: string) => string | number;
4
+ warning: (message: string, description?: string) => string | number;
5
+ info: (message: string, description?: string) => string | number;
6
+ loading: (message: string, description?: string) => string | number;
7
+ promise: <T>(promise: Promise<T>, { loading, success, error, }: {
8
+ loading: string;
9
+ success: string | ((data: T) => string);
10
+ error: string | ((error: any) => string);
11
+ }) => (string & {
12
+ unwrap: () => Promise<T>;
13
+ }) | (number & {
14
+ unwrap: () => Promise<T>;
15
+ }) | {
16
+ unwrap: () => Promise<T>;
17
+ };
18
+ dismiss: (id?: string | number) => string | number;
19
+ };
@@ -0,0 +1 @@
1
+ import{toast as s}from"sonner";export const toast={success:(i,r)=>s.success(i,{description:r,duration:3e3}),error:(i,r)=>s.error(i,{description:r,duration:4e3}),warning:(i,r)=>s.warning(i,{description:r,duration:3500}),info:(i,r)=>s.info(i,{description:r,duration:3e3}),loading:(i,r)=>s.loading(i,{description:r}),promise:(i,{loading:r,success:o,error:n})=>s.promise(i,{loading:r,success:o,error:n}),dismiss:i=>s.dismiss(i)};
@@ -0,0 +1,6 @@
1
+ import type { ExamQuestion } from '../../types/entities/exam.types';
2
+ type JsonRecord = Record<string, unknown>;
3
+ type ApiQuestion = JsonRecord;
4
+ export declare function transformApiQuestionToFrontend(apiQuestion: ApiQuestion): Partial<ExamQuestion>;
5
+ export declare function transformApiQuestionsToFrontend(apiQuestions: ApiQuestion[]): Partial<ExamQuestion>[];
6
+ export {};
@@ -0,0 +1 @@
1
+ const n=n=>"object"==typeof n&&null!==n&&!Array.isArray(n),e=e=>n(e)?e:{},t=n=>Array.isArray(n)?n:[],o=(n,e="")=>"string"==typeof n?n:e,r=(n,e)=>"number"==typeof n&&Number.isFinite(n)?n:e,s=n=>e(n.correctAnswer??n.correct_answer),i=n=>e(n.questionGroup??n.question_group),_=n=>Number.parseFloat(String(n.total_points??n.points??1))||1,a=n=>{const e=n?.toUpperCase();return"EASY"===e||"MEDIUM"===e||"HARD"===e?e:void 0},E=n=>{const e=n?.toUpperCase();return"LISTENING"===e||"READING"===e||"WRITING"===e||"SPEAKING"===e?e:void 0},A=n=>({content:n.content,answer:s(n)}),N=n=>{const r=e(n.content),i=s(n);return{content:"",answer:{imageUrl:o(r.imageUrl),question:o(r.question),options:t(r.options).map(n=>"string"==typeof n?n:o(e(n).text)),correctAnswer:i.answer??i.correctAnswer??-1,explanation:o(n.explanation),points:_(n)}}},p=n=>{const t=e(n.content),a=s(n),E=i(n);return{content:"",answer:{...e(E.payload),...t,...a,groupNumber:r(E.groupNumber,1),explanation:o(n.explanation),points:_(n)}}},u=n=>{const t=s(n),r=e(n.content);return{content:n.content??"",answer:{...t,...r,explanation:o(n.explanation),points:_(n)}}},S={CHOOSE_THE_CORRECT_ANSWER:n=>{const r=e(n.content),i=s(n),a=i.answer??-1,E=Boolean(r.multipleAnswers??i.multipleAnswers??Array.isArray(a));return{content:"",answer:{question:o(r.question),optionType:o(r.optionType,"text"),options:t(r.options),imageUrl:o(r.imageUrl),askerName:o(r.askerName),answererName:o(r.answererName),correctAnswer:E?Array.isArray(a)?a:-1===a?[]:[a]:Array.isArray(a)?a[0]??-1:a,multipleAnswers:E,explanation:o(n.explanation),points:_(n)}}},LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:N,LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:N,FILL_IN_BLANK:n=>{const r=e(n.content),i=s(n),a=e(t(r.blanks)[0]);return{content:"",answer:{question:o(r.question??a.text),answers:Array.isArray(i.answers)?i.answers:[],caseSensitive:Boolean(i.caseSensitive??!1),imageUrl:o(r.imageUrl),showHints:Boolean(r.showHints??!1),hints:t(r.hints),explanation:o(n.explanation),points:_(n),blanks:t(r.blanks)}}},READ_PASSAGE_AND_ANSWER_QUESTIONS:n=>{const a=e(n.content),E=s(n),A=i(n),N=e(A.payload);return{content:"",answer:{passage:o(N.passage??a.passage),passageTitle:o(N.passageTitle??a.passageTitle),instructions:o(N.instructions??a.instructions),singleQuestion:{id:o(n.id,`question-${String(n.question_number??n.questionNumber??1)}`),question:o(a.question),options:t(a.options),correctAnswer:E.correctAnswer??E.answer??-1,points:_(n),groupNumber:r(A.groupNumber,1)}}}},LABEL_THE_PICTURE:n=>{const r=e(n.content),i=s(n),_=e(i.labels??i.answers);return{content:"",answer:{imageUrl:o(r.imageUrl),wordBank:t(r.wordBank),labels:t(r.labels).map(n=>{const t=e(n),r=o(t.id);return{...t,correctAnswer:t.correctAnswer??_[r]??""}})}}},READ_AND_COLOR_OBJECTS:p,IMAGE_OBJECT_MATCHING:p,FILL_MISSING_WORDS_IN_GRID:n=>({content:n.content??{},answer:s(n)}),LOOK_PICTURE_FILL_WORD_HINT:p,ANSWER_THE_QUESTION:p,TRUE_FALSE:u,WORD_ORDERING:u,WORD_FILL_PARAGRAPH:u,MATCH_BY_WRITING_ANSWER:p,WRITE_SENTENCES:p,WRITE_A_SHORT_LETTER:u,WRITE_CORRECT_VERB_FORM:u,CHOOSE_CORRECT_ADJECTIVE:u,WORD_FILL_STRUCTURED_FORM:p,LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP:p,LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE:p,LISTEN_AND_DRAG_OBJECTS_INTO_SCENE:p,LISTEN_AND_SPEAK_ANSWER:p,LISTEN_AND_SPEAK_IMAGE_GROUP:p,LISTEN_AND_SPEAK_QUESTION_LIST:p,LISTEN_AND_SPEAK_COMPARE_IMAGES:p,LISTEN_AND_SPEAK_WITH_STORY_IMAGES:p,LISTEN_AND_SPEAK_ODD_ONE_OUT:p,LISTEN_AND_SPEAK_INFO_EXCHANGE:p,SPEAKING_DESCRIBE_IMAGE:u,READ_DISPLAYED_CONTENT:u,SPONTANEOUS_QA:u,SPEAKING_CONVERSATION:p,SPEAKING_CUE_CARD:u,GN_SPEAKING_INTERVIEW:p};export function transformApiQuestionToFrontend(e){const t=String(e.questionType??e.question_type??e.type??""),s=(S[t]??A)(e),i=(e=>{const t=e.questionBank??e.question_bank;return n(t)?t:void 0})(e);return{id:o(e.id),type:t,content:s.content,answer:s.answer,points:_(e),level:(N=e.level,"Pre-A1"===N||"A1"===N||"A2"===N||"B1"===N||"B2"===N||"C1"===N||"C2"===N?N:void 0),difficulty:a(o(e.difficulty??e.difficult_level)),skill:E(o(e.questionSkillType??e.question_skill_type??e.skill)),explanation:o(e.explanation),partId:o(e.partId??e.part_id),questionNumber:r(e.questionNumber??e.question_number,1),isCompleted:!0,questionGroup:e.questionGroup,questionBank:i?{id:o(i.id),code:o(i.code),title:o(i.title)}:void 0};var N}export function transformApiQuestionsToFrontend(n){return n.map(transformApiQuestionToFrontend)}
@@ -0,0 +1,6 @@
1
+ import type { ExamQuestion } from '../../types/entities/exam.types';
2
+ export interface QuestionTransformValidationResult {
3
+ isValid: boolean;
4
+ errors: string[];
5
+ }
6
+ export declare function validateQuestionForTransform(question: Partial<ExamQuestion>): QuestionTransformValidationResult;
@@ -0,0 +1 @@
1
+ const n=n=>"string"==typeof n&&n.trim().length>0,t=n=>Array.isArray(n)&&n.length>0,e=n=>"object"==typeof n&&null!==n&&!Array.isArray(n),s=n=>e(n)?n:void 0,u=n=>"number"==typeof n&&Number.isFinite(n)&&n>0;export function validateQuestionForTransform(r){const h=[];r.type||h.push("Question type is required");const o=s(r.answer),p=s(r.content);switch(r.type){case"FILL_MISSING_WORDS_IN_GRID":!function(n,t,s){Array.isArray(n?.grid)||s.push("Grid is required for FILL_MISSING_WORDS_IN_GRID");u(n?.rows)||s.push("Rows must be at least 1");u(n?.columns)||s.push("Columns must be at least 1");i=t?.answers,e(i)&&Object.keys(i).length>0||s.push("At least one missing letter is required");var i}(p,o,h);break;case"LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER":!function(t,e){n(t?.imageUrl)||e.push("Vui lòng upload hình ảnh");n(t?.question)||e.push("Vui lòng nhập nội dung câu hỏi");i(t?.options,e),(void 0===t?.correctAnswer||-1===t.correctAnswer)&&e.push("Vui lòng chọn đáp án đúng")}(o,h);break;case"LOOK_PICTURE_CHOOSE_CORRECT_ANSWER":!function(t,e){n(t?.imageUrl)||e.push("Vui lòng upload hình ảnh");i(t?.options,e),("number"!=typeof t?.correctAnswer||t.correctAnswer<0)&&e.push("Vui lòng chọn đáp án đúng")}(o,h);break;case"LOOK_PICTURE_FILL_WORD_HINT":!function(e,u){if(!t(e?.subQuestions))return void u.push("Vui lòng nhập dữ liệu câu hỏi");e.subQuestions.forEach(t=>{const e=s(t);n(e?.imageUrl)||u.push("Vui lòng upload hình ảnh"),n(e?.word)||u.push("Vui lòng nhập từ có chỗ trống"),n(e?.correctAnswer)||u.push("Vui lòng nhập đáp án đúng")})}(o,h);break;case"LABEL_THE_PICTURE":!function(e,s){n(e?.imageUrl)||s.push("Vui lòng upload hình ảnh");t(e?.labels)||s.push("Vui lòng thêm ít nhất một vị trí cần điền")}(o,h);break;case"READ_AND_COLOR_OBJECTS":case"IMAGE_OBJECT_MATCHING":!function(e,s){n(e?.backgroundImageUrl)||s.push("Vui lòng upload ảnh nền");t(e?.colorNodes)||s.push("Vui lòng thêm ít nhất một màu");t(e?.regionNodes)||s.push("Vui lòng thêm ít nhất một vùng tô màu")}(o,h);break;case"READ_PASSAGE_AND_ANSWER_QUESTIONS":!function(t,e){n(t?.passage)||e.push("Vui lòng nhập nội dung đoạn văn");const u=s(t?.singleQuestion);if(!u)return void e.push("Vui lòng nhập dữ liệu câu hỏi");n(u.question)||e.push("Vui lòng nhập câu hỏi");i(u.options,e),("number"!=typeof u.correctAnswer||u.correctAnswer<0)&&e.push("Vui lòng chọn đáp án đúng")}(o,h);break;case"CHOOSE_CORRECT_ADJECTIVE":!function(t,e,s){n(t?.sentence)||s.push("Vui lòng nhập câu hỏi");i(t?.options,s),("number"!=typeof e?.answer||e.answer<0)&&s.push("Vui lòng chọn đáp án đúng")}(p,o,h);break;case"ANSWER_THE_QUESTION":!function(t,e){n(t?.question)||e.push("Vui lòng nhập câu hỏi");n(t?.correctAnswer)||e.push("Vui lòng nhập đáp án")}(o,h);break;case"WORD_ORDERING":!function(n,e){(!t(n?.words)||n.words.length<2)&&e.push("Cần ít nhất 2 từ/chữ cái");(!t(n?.answer)||n.answer.length<2)&&e.push("Cần ít nhất 2 từ/chữ cái trong đáp án")}(o,h);break;case"WORD_FILL_PARAGRAPH":!function(e,s){n(e?.paragraph)||s.push("Vui lòng nhập đoạn văn");"DEFAULT"===e?.viewMode||"EMAIL"===e?.viewMode||t(e?.wordBank)||s.push("Cần ít nhất 1 chỗ trống");t(e?.answers)||s.push("Cần ít nhất 1 đáp án")}(o,h);break;case"LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP":!function(e,s){(!t(e?.options)||e.options.length<2)&&s.push("Cần tối thiểu 2 đáp án trong nhóm");n(e?.audioUrl)||s.push("Phải có file audio");n(e?.correctAnswer)||s.push("Phải chọn đáp án đúng")}(o,h);break;case"LISTEN_AND_SPEAK_QUESTION_LIST":!function(e,s){n(e?.audioUrl)||s.push("Vui lòng tải lên file âm thanh");n(e?.activeQuestionId)||s.push("Vui lòng chọn câu hỏi");t(e?.expectedAnswers)||s.push("Cần ít nhất 1 đáp án mong muốn")}(o,h);break;case"WRITE_A_SHORT_LETTER":!function(n,t){u(n?.minWords)||t.push("Số từ tối thiểu phải >= 1");"number"==typeof n?.maxWords&&"number"==typeof n.minWords&&n.maxWords<n.minWords&&t.push("Số từ tối đa phải >= số từ tối thiểu")}(o,h)}return{isValid:0===h.length,errors:h}}function i(e,u){if(!t(e)||e.length<2)return void u.push("Phải có ít nhất 2 lựa chọn");e.filter(t=>{const e="string"==typeof t?t:s(t)?.text;return n(e)}).length<2&&u.push("Phải có ít nhất 2 đáp án được điền")}
@@ -8,6 +8,8 @@ export interface TransformQuestionOptions {
8
8
  questionBankCode?: string;
9
9
  questionBankTitle?: string;
10
10
  sectionId?: number;
11
+ examLevel?: string;
12
+ subjectId?: string;
11
13
  }
12
14
  /**
13
15
  * Transform frontend question format to API format.
@@ -22,9 +24,11 @@ export interface TransformQuestionItem {
22
24
  addToQuestionBank?: boolean;
23
25
  questionBankCode?: string;
24
26
  questionBankTitle?: string;
27
+ examLevel?: string;
28
+ subjectId?: string;
25
29
  }
26
30
  /**
27
- * Transform multiple questions to API format. Mirrors the reference FE behaviour
28
- * but without the standalone validation pass (validation lives in the creator UI).
31
+ * Transform multiple questions to API format with the same validation gate used
32
+ * by the host frontend screen.
29
33
  */
30
34
  export declare function transformQuestionsToApiFormat(questions: TransformQuestionItem[]): TransformQuestionsResult;
@@ -1 +1 @@
1
- import{transformLookPictureChooseCorrectAnswer as o}from"../../../components/questions/types/look-picture-choose-correct-answer/transform";import{transformLookPictureFillBlankChooseAnswer as t}from"../../../components/questions/types/look-picture-fill-blank-choose-answer/transform";import{transformLookPictureFillWordHint as s}from"../../../components/questions/types/look-picture-fill-word-hint/transform";import{transformReadAndColorObjects as e}from"../../../components/questions/types/read-and-color-objects/transform";import{transformReadPassageAndAnswerQuestions as n}from"../../../components/questions/types/read-passage-and-answer-questions/transform";import{transformArrangeLettersIntoWords as r}from"../../../components/questions/types/arrange-letters-into-words/transform";import{transformWriteShortParagraph as a}from"../../../components/questions/types/write-short-paragraph/transform";import{transformWriteAShortLetter as i}from"../../../components/questions/types/write-a-short-letter/transform";import{transformFillMissingWordsInGrid as p}from"../../../components/questions/types/fill-missing-words-in-grid/transform";import{transformLabelThePicture as m}from"../../../components/questions/types/label-the-picture/transform";import{transformChooseTheCorrectAnswer as u}from"../../../components/questions/types/choose-the-correct-answer/transform";import{transformFillInBlank as _}from"../../../components/questions/types/fill-in-blank/transform";import{transformWriteCorrectVerbForm as c}from"../../../components/questions/types/write-correct-verb-form/transform";import{transformChooseCorrectAdjective as E}from"../../../components/questions/types/choose-correct-adjective/transform";import{transformAnswerTheQuestion as f}from"../../../components/questions/types/answer-the-question/transform";import{transformTrueFalse as N}from"../../../components/questions/types/true-false/transform";import{transformWordOrdering as A}from"../../../components/questions/types/word-ordering/transform";import{transformWordFillParagraph as T}from"../../../components/questions/types/word-fill-paragraph/transform";import{transformMatchByWritingAnswer as I}from"../../../components/questions/types/match-by-writing-answer/transform";import{transformWriteSentences as S}from"../../../components/questions/types/write-sentences/transform";import{transformListenAndChooseFromAnswerGroup as R}from"../../../components/questions/types/listen-and-choose-from-answer-group/transform";import{transformListenAndChooseObjectsInScene as d}from"../../../components/questions/types/listen-and-choose-objects-in-scene/transform";import{transformListenAndDragObjectsIntoScene as l}from"../../../components/questions/types/listen-and-drag-objects-into-scene/transform";import{transformListenAndSpeakAnswer as q}from"../../../components/questions/types/listen-and-speak-answer/transform";import{transformListenAndSpeakImageGroup as D}from"../../../components/questions/types/listen-and-speak-image-group/transform";import{transformListenAndSpeakQuestionList as O}from"../../../components/questions/types/listen-and-speak-question-list/transform";import{transformListenAndSpeakCompareImages as y}from"../../../components/questions/types/listen-and-speak-compare-images/transform";import{transformListenAndSpeakOddOneOut as C}from"../../../components/questions/types/listen-and-speak-odd-one-out/transform";import{transformListenAndSpeakWithStoryImages as G}from"../../../components/questions/types/listen-and-speak-with-story-images/transform";import{transformListenAndSpeakInfoExchange as g}from"../../../components/questions/types/listen-and-speak-info-exchange/transform";import{transformSpeakingDescribeImage as L}from"../../../components/questions/types/speaking-describe-image/transform";import{transformReadDisplayedContent as w}from"../../../components/questions/types/read-displayed-content/transform";import{transformSpontaneousQA as k}from"../../../components/questions/types/spontaneous-qa/transform";import{transformSpeakingConversation as h}from"../../../components/questions/types/speaking-conversation/transform";import{transformSpeakingCueCard as P}from"../../../components/questions/types/speaking-cue-card/transform";import{transformGNSpeakingInterview as B}from"../../../components/questions/types/gn-speaking-interview/transform";import{transformWordFillStructuredForm as W}from"../../../components/questions/types/word-fill-structured-form/transform";const b={LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:o,LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:t,LOOK_PICTURE_FILL_WORD_HINT:s,READ_AND_COLOR_OBJECTS:e,IMAGE_OBJECT_MATCHING:e,READ_PASSAGE_AND_ANSWER_QUESTIONS:n,ARRANGE_LETTERS_INTO_WORDS:r,WRITE_SHORT_PARAGRAPH:a,WRITE_A_SHORT_LETTER:i,FILL_MISSING_WORDS_IN_GRID:p,LABEL_THE_PICTURE:m,CHOOSE_THE_CORRECT_ANSWER:u,FILL_IN_BLANK:_,WRITE_CORRECT_VERB_FORM:c,CHOOSE_CORRECT_ADJECTIVE:E,ANSWER_THE_QUESTION:f,TRUE_FALSE:N,WORD_ORDERING:A,WORD_FILL_PARAGRAPH:T,MATCH_BY_WRITING_ANSWER:I,WRITE_SENTENCES:S,LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP:R,LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE:d,LISTEN_AND_DRAG_OBJECTS_INTO_SCENE:l,LISTEN_AND_SPEAK_ANSWER:q,LISTEN_AND_SPEAK_IMAGE_GROUP:D,LISTEN_AND_SPEAK_QUESTION_LIST:O,LISTEN_AND_SPEAK_COMPARE_IMAGES:y,LISTEN_AND_SPEAK_ODD_ONE_OUT:C,LISTEN_AND_SPEAK_WITH_STORY_IMAGES:G,LISTEN_AND_SPEAK_INFO_EXCHANGE:g,SPEAKING_DESCRIBE_IMAGE:L,READ_DISPLAYED_CONTENT:w,SPONTANEOUS_QA:k,SPEAKING_CONVERSATION:h,SPEAKING_CUE_CARD:P,GN_SPEAKING_INTERVIEW:B,WORD_FILL_STRUCTURED_FORM:W};export function transformQuestionToApiFormat(o,t={}){const{partId:s,partNo:e,questionNumber:n,addToQuestionBank:r,questionBankCode:a,questionBankTitle:i,sectionId:p}=t,{id:m,type:u,points:_,explanation:c}=o,E=u?b[u]:void 0,f=E?E(o):{apiContent:{},apiCorrectAnswer:{}},{apiContent:N,apiCorrectAnswer:A,totalPoints:T,hintLetters:I,groupNumber:S,passageData:R,imageData:d,basicGroupData:l,questionListGroupData:q,sceneData:D,answerGroupData:O,compareImagesGroupData:y,infoExchangeGroupData:C,conversationGroupData:G,isExample:g,suggestedAnswers:L}=f,w=o.answer,k=o.content,h={id:m,questionType:u||"",content:N,correctAnswer:A||{},points:T??_??1,explanation:f.explanation||c||w?.explanation||k?.explanation||"",questionNumber:n,partId:s,partNo:e,...null!=p?{sectionId:p}:{},questionSkillType:o.skill,addToQuestionBank:r??!1,questionBank:r&&a&&i?{code:a,title:i}:void 0,isExample:g||!1};L&&L.length>0&&(h.suggestedAnswers=L);const P=function(o){const{hintLetters:t,passageData:s,imageData:e,basicGroupData:n,sceneData:r,answerGroupData:a,questionListGroupData:i,compareImagesGroupData:p,infoExchangeGroupData:m,conversationGroupData:u}=o;if(t&&t.length>0)return{hintLetters:t};if(s)return s;if(e)return e;if(n&&(n.title||n.subtitle||n.content||n.imageUrl||n.articles))return n;return r||(a||(i||(p||(m||(u||void 0)))))}({hintLetters:I,passageData:R,imageData:d,basicGroupData:l,sceneData:D,answerGroupData:O,questionListGroupData:q,compareImagesGroupData:y,infoExchangeGroupData:C,conversationGroupData:G});return P&&(h.isGroup=!0,h.questionGroup={payload:P,groupNumber:S||1}),h}export function transformQuestionsToApiFormat(o){const t=[];return o.forEach((o,s)=>{const{question:e,partId:n,partNo:r,sectionId:a,addToQuestionBank:i,questionBankCode:p,questionBankTitle:m}=o,u=e.questionNumber??s+1;t.push(transformQuestionToApiFormat(e,{partId:n,partNo:r,questionNumber:u,addToQuestionBank:i,questionBankCode:p,questionBankTitle:m,sectionId:a}))}),{validQuestions:t,invalidQuestions:[]}}
1
+ import{validateQuestionForTransform as o}from"./question-transform-validation";import{transformLookPictureChooseCorrectAnswer as t}from"../../../components/questions/types/look-picture-choose-correct-answer/transform";import{transformLookPictureFillBlankChooseAnswer as s}from"../../../components/questions/types/look-picture-fill-blank-choose-answer/transform";import{transformLookPictureFillWordHint as e}from"../../../components/questions/types/look-picture-fill-word-hint/transform";import{transformReadAndColorObjects as n}from"../../../components/questions/types/read-and-color-objects/transform";import{transformReadPassageAndAnswerQuestions as r}from"../../../components/questions/types/read-passage-and-answer-questions/transform";import{transformArrangeLettersIntoWords as a}from"../../../components/questions/types/arrange-letters-into-words/transform";import{transformWriteShortParagraph as i}from"../../../components/questions/types/write-short-paragraph/transform";import{transformWriteAShortLetter as p}from"../../../components/questions/types/write-a-short-letter/transform";import{transformFillMissingWordsInGrid as m}from"../../../components/questions/types/fill-missing-words-in-grid/transform";import{transformLabelThePicture as u}from"../../../components/questions/types/label-the-picture/transform";import{transformChooseTheCorrectAnswer as c}from"../../../components/questions/types/choose-the-correct-answer/transform";import{transformFillInBlank as _}from"../../../components/questions/types/fill-in-blank/transform";import{transformWriteCorrectVerbForm as E}from"../../../components/questions/types/write-correct-verb-form/transform";import{transformChooseCorrectAdjective as f}from"../../../components/questions/types/choose-correct-adjective/transform";import{transformAnswerTheQuestion as N}from"../../../components/questions/types/answer-the-question/transform";import{transformTrueFalse as A}from"../../../components/questions/types/true-false/transform";import{transformWordOrdering as I}from"../../../components/questions/types/word-ordering/transform";import{transformWordFillParagraph as d}from"../../../components/questions/types/word-fill-paragraph/transform";import{transformMatchByWritingAnswer as T}from"../../../components/questions/types/match-by-writing-answer/transform";import{transformWriteSentences as l}from"../../../components/questions/types/write-sentences/transform";import{transformListenAndChooseFromAnswerGroup as S}from"../../../components/questions/types/listen-and-choose-from-answer-group/transform";import{transformListenAndChooseObjectsInScene as R}from"../../../components/questions/types/listen-and-choose-objects-in-scene/transform";import{transformListenAndDragObjectsIntoScene as q}from"../../../components/questions/types/listen-and-drag-objects-into-scene/transform";import{transformListenAndSpeakAnswer as D}from"../../../components/questions/types/listen-and-speak-answer/transform";import{transformListenAndSpeakImageGroup as O}from"../../../components/questions/types/listen-and-speak-image-group/transform";import{transformListenAndSpeakQuestionList as L}from"../../../components/questions/types/listen-and-speak-question-list/transform";import{transformListenAndSpeakCompareImages as y}from"../../../components/questions/types/listen-and-speak-compare-images/transform";import{transformListenAndSpeakOddOneOut as C}from"../../../components/questions/types/listen-and-speak-odd-one-out/transform";import{transformListenAndSpeakWithStoryImages as G}from"../../../components/questions/types/listen-and-speak-with-story-images/transform";import{transformListenAndSpeakInfoExchange as g}from"../../../components/questions/types/listen-and-speak-info-exchange/transform";import{transformSpeakingDescribeImage as w}from"../../../components/questions/types/speaking-describe-image/transform";import{transformReadDisplayedContent as h}from"../../../components/questions/types/read-displayed-content/transform";import{transformSpontaneousQA as k}from"../../../components/questions/types/spontaneous-qa/transform";import{transformSpeakingConversation as P}from"../../../components/questions/types/speaking-conversation/transform";import{transformSpeakingCueCard as b}from"../../../components/questions/types/speaking-cue-card/transform";import{transformGNSpeakingInterview as B}from"../../../components/questions/types/gn-speaking-interview/transform";import{transformWordFillStructuredForm as W}from"../../../components/questions/types/word-fill-structured-form/transform";const v={LOOK_PICTURE_CHOOSE_CORRECT_ANSWER:t,LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER:s,LOOK_PICTURE_FILL_WORD_HINT:e,READ_AND_COLOR_OBJECTS:n,IMAGE_OBJECT_MATCHING:n,READ_PASSAGE_AND_ANSWER_QUESTIONS:r,ARRANGE_LETTERS_INTO_WORDS:a,WRITE_SHORT_PARAGRAPH:i,WRITE_A_SHORT_LETTER:p,FILL_MISSING_WORDS_IN_GRID:m,LABEL_THE_PICTURE:u,CHOOSE_THE_CORRECT_ANSWER:c,FILL_IN_BLANK:_,WRITE_CORRECT_VERB_FORM:E,CHOOSE_CORRECT_ADJECTIVE:f,ANSWER_THE_QUESTION:N,TRUE_FALSE:A,WORD_ORDERING:I,WORD_FILL_PARAGRAPH:d,MATCH_BY_WRITING_ANSWER:T,WRITE_SENTENCES:l,LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP:S,LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE:R,LISTEN_AND_DRAG_OBJECTS_INTO_SCENE:q,LISTEN_AND_SPEAK_ANSWER:D,LISTEN_AND_SPEAK_IMAGE_GROUP:O,LISTEN_AND_SPEAK_QUESTION_LIST:L,LISTEN_AND_SPEAK_COMPARE_IMAGES:y,LISTEN_AND_SPEAK_ODD_ONE_OUT:C,LISTEN_AND_SPEAK_WITH_STORY_IMAGES:G,LISTEN_AND_SPEAK_INFO_EXCHANGE:g,SPEAKING_DESCRIBE_IMAGE:w,READ_DISPLAYED_CONTENT:h,SPONTANEOUS_QA:k,SPEAKING_CONVERSATION:P,SPEAKING_CUE_CARD:b,GN_SPEAKING_INTERVIEW:B,WORD_FILL_STRUCTURED_FORM:W};export function transformQuestionToApiFormat(o,t={}){const{partId:s,partNo:e,questionNumber:n,addToQuestionBank:r,questionBankCode:a,questionBankTitle:i,sectionId:p,examLevel:m,subjectId:u}=t,{id:c,type:_,points:E,explanation:f}=o,N=_?v[_]:void 0,A=N?N(o):{apiContent:{},apiCorrectAnswer:{}},{apiContent:I,apiCorrectAnswer:d,totalPoints:T,hintLetters:l,groupNumber:S,passageData:R,imageData:q,basicGroupData:D,questionListGroupData:O,sceneData:L,answerGroupData:y,compareImagesGroupData:C,infoExchangeGroupData:G,conversationGroupData:g,isExample:w,suggestedAnswers:h}=A,k=o.answer,P=o.content,b={id:c,questionType:_||"",content:I,correctAnswer:d||{},points:T??E??1,explanation:A.explanation||f||k?.explanation||P?.explanation||"",questionNumber:n,partId:s,partNo:e,...null!=p?{sectionId:p}:{},questionSkillType:o.skill,examLevel:m,subjectId:u,addToQuestionBank:r??!1,questionBank:r&&a&&i?{code:a,title:i}:void 0,isExample:w||!1};h&&h.length>0&&(b.suggestedAnswers=h);const B=function(o){const{hintLetters:t,passageData:s,imageData:e,basicGroupData:n,sceneData:r,answerGroupData:a,questionListGroupData:i,compareImagesGroupData:p,infoExchangeGroupData:m,conversationGroupData:u}=o;if(t&&t.length>0)return{hintLetters:t};if(s)return s;if(e)return e;if(n&&(n.title||n.subtitle||n.content||n.imageUrl||n.articles))return n;return r||(a||(i||(p||(m||(u||void 0)))))}({hintLetters:l,passageData:R,imageData:q,basicGroupData:D,sceneData:L,answerGroupData:y,questionListGroupData:O,compareImagesGroupData:C,infoExchangeGroupData:G,conversationGroupData:g});return B&&(b.isGroup=!0,b.questionGroup={payload:B,groupNumber:S||1}),b}export function transformQuestionsToApiFormat(t){const s=[],e=[];return t.forEach((t,n)=>{const{question:r,partId:a,partNo:i,sectionId:p,addToQuestionBank:m,questionBankCode:u,questionBankTitle:c,examLevel:_,subjectId:E}=t,f=o(r);if(!f.isValid)return void e.push({index:n,errors:f.errors});const N=r.questionNumber??n+1;s.push(transformQuestionToApiFormat(r,{partId:a,partNo:i,questionNumber:N,addToQuestionBank:m,questionBankCode:u,questionBankTitle:c,sectionId:p,examLevel:_,subjectId:E}))}),{validQuestions:s,invalidQuestions:e}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinyweb_dev/oe-exam-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Reusable OceanEdu question components.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,11 +18,18 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "clean": "rm -rf dist",
21
- "build:ts": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
22
- "build:assets": "for d in cambridge-yle english-certification summer-sky; do [ -d src/components/themes/$d/assets ] && cp -R src/components/themes/$d/assets dist/components/themes/$d/ || true; done && cp src/global.d.ts dist/global.d.ts",
21
+ "build:compile": "tsc -p tsconfig.build.json",
22
+ "build:alias": "tsc-alias -p tsconfig.build.json",
23
+ "build:ts": "npm run build:compile && npm run build:assets && npm run build:alias",
24
+ "build:assets": "for d in cambridge-yle english-certification summer-sky spaceship; do [ -d src/components/themes/$d/assets ] && cp -R src/components/themes/$d/assets dist/components/themes/$d/ || true; done; [ -d src/components/shared/audio/assets ] && cp -R src/components/shared/audio/assets dist/components/shared/audio/ || true; (cd src && find . -name '*.module.css' -exec cp --parents {} ../dist/ \\;); cp src/global.d.ts dist/global.d.ts",
23
25
  "minify:js": "find dist -name '*.js' -type f -exec sh -c 'for f do terser \"$f\" --compress directives=false --mangle --module --comments false --output \"$f\"; done' sh {} +",
24
- "build": "npm run clean && npm run build:ts && npm run build:assets && npm run minify:js",
26
+ "build": "npm run clean && npm run build:ts && npm run minify:js",
25
27
  "pack:local": "npm pack",
28
+ "release": "npm run release:patch",
29
+ "release:patch": "npm version patch --no-git-tag-version && npm run release:push",
30
+ "release:minor": "npm version minor --no-git-tag-version && npm run release:push",
31
+ "release:major": "npm version major --no-git-tag-version && npm run release:push",
32
+ "release:push": "npm run build && npm pack --dry-run && VERSION=$(node -p \"require('./package.json').version\") && git add package.json package-lock.json && git commit -m \"chore(sdk): release v$VERSION\" && git tag \"sdk-v$VERSION\" && git push origin HEAD && git push origin \"sdk-v$VERSION\"",
26
33
  "prepack": "npm run build"
27
34
  },
28
35
  "exports": {
@@ -50,6 +57,14 @@
50
57
  "types": "./dist/components/exams/take/index.d.ts",
51
58
  "import": "./dist/components/exams/take/index.js"
52
59
  },
60
+ "./components/exams/entry": {
61
+ "types": "./dist/components/exams/entry/index.d.ts",
62
+ "import": "./dist/components/exams/entry/index.js"
63
+ },
64
+ "./components/exams/rooms": {
65
+ "types": "./dist/components/exams/rooms/index.d.ts",
66
+ "import": "./dist/components/exams/rooms/index.js"
67
+ },
53
68
  "./components/questions": {
54
69
  "types": "./dist/components/questions/index.d.ts",
55
70
  "import": "./dist/components/questions/index.js"