@intellectif/lk-react 23.1.0 → 23.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +9 -5
- package/dist/ActivityErrorBoundary-B379hvtL.cjs +39 -0
- package/dist/ActivityErrorBoundary-B379hvtL.cjs.map +1 -0
- package/dist/ActivityErrorBoundary-Dw6SbWv3.js +34 -0
- package/dist/ActivityErrorBoundary-Dw6SbWv3.js.map +1 -0
- package/dist/ActivityMedia-CQQTRNl7.cjs +641 -0
- package/dist/ActivityMedia-CQQTRNl7.cjs.map +1 -0
- package/dist/ActivityMedia-vDiP-Psa.js +636 -0
- package/dist/ActivityMedia-vDiP-Psa.js.map +1 -0
- package/dist/ActivityPreview-1hhTkYuj.js +240 -0
- package/dist/ActivityPreview-1hhTkYuj.js.map +1 -0
- package/dist/ActivityPreview-BKr34exz.cjs +245 -0
- package/dist/ActivityPreview-BKr34exz.cjs.map +1 -0
- package/dist/ActivitySequence-CkX87pfB.js +839 -0
- package/dist/ActivitySequence-CkX87pfB.js.map +1 -0
- package/dist/ActivitySequence-CmoSyDnp.cjs +844 -0
- package/dist/ActivitySequence-CmoSyDnp.cjs.map +1 -0
- package/dist/Dictation-BlxRp-3k.js +926 -0
- package/dist/Dictation-BlxRp-3k.js.map +1 -0
- package/dist/Dictation-jECzL88E.cjs +931 -0
- package/dist/Dictation-jECzL88E.cjs.map +1 -0
- package/dist/FeedbackRegion-BNNMtTY-.cjs +108 -0
- package/dist/FeedbackRegion-BNNMtTY-.cjs.map +1 -0
- package/dist/FeedbackRegion-CyPSp8bA.js +85 -0
- package/dist/FeedbackRegion-CyPSp8bA.js.map +1 -0
- package/dist/FillInTheBlanks-B6xzqYXx.js +474 -0
- package/dist/FillInTheBlanks-B6xzqYXx.js.map +1 -0
- package/dist/FillInTheBlanks-BpKhdHg2.cjs +479 -0
- package/dist/FillInTheBlanks-BpKhdHg2.cjs.map +1 -0
- package/dist/GapSelect-DUSiaEQH.js +441 -0
- package/dist/GapSelect-DUSiaEQH.js.map +1 -0
- package/dist/GapSelect-payTq_Zn.cjs +446 -0
- package/dist/GapSelect-payTq_Zn.cjs.map +1 -0
- package/dist/InteractiveVideo-BguGv-HA.cjs +2955 -0
- package/dist/InteractiveVideo-BguGv-HA.cjs.map +1 -0
- package/dist/InteractiveVideo-Cg2jbU3j.js +2944 -0
- package/dist/InteractiveVideo-Cg2jbU3j.js.map +1 -0
- package/dist/LkAiProvider-DAPpA3PQ.d.cts +84 -0
- package/dist/LkAiProvider-DAPpA3PQ.d.cts.map +1 -0
- package/dist/LkAiProvider-QdEcIhoo.d.ts +84 -0
- package/dist/LkAiProvider-QdEcIhoo.d.ts.map +1 -0
- package/dist/LkIntlProvider-D_FdYXjQ.js +375 -0
- package/dist/LkIntlProvider-D_FdYXjQ.js.map +1 -0
- package/dist/LkIntlProvider-oi57lYB0.cjs +410 -0
- package/dist/LkIntlProvider-oi57lYB0.cjs.map +1 -0
- package/dist/MultipleChoice-COn5MtKY.cjs +433 -0
- package/dist/MultipleChoice-COn5MtKY.cjs.map +1 -0
- package/dist/MultipleChoice-Dra0_KYD.js +428 -0
- package/dist/MultipleChoice-Dra0_KYD.js.map +1 -0
- package/dist/PronunciationFeedback-DlMPGjkR.cjs +831 -0
- package/dist/PronunciationFeedback-DlMPGjkR.cjs.map +1 -0
- package/dist/PronunciationFeedback-Dxd6XPkO.js +772 -0
- package/dist/PronunciationFeedback-Dxd6XPkO.js.map +1 -0
- package/dist/ReadAloud-C8RhaUqV.js +1092 -0
- package/dist/{chunk-DC4CQCK5.js.map → ReadAloud-C8RhaUqV.js.map} +1 -1
- package/dist/ReadAloud-akDehitT.cjs +1103 -0
- package/dist/ReadAloud-akDehitT.cjs.map +1 -0
- package/dist/StimulusPanel-BgzByfkb.js +74 -0
- package/dist/StimulusPanel-BgzByfkb.js.map +1 -0
- package/dist/StimulusPanel-b66gaN3i.cjs +79 -0
- package/dist/StimulusPanel-b66gaN3i.cjs.map +1 -0
- package/dist/ThemeProvider-B6DyGqzh.d.cts +62 -0
- package/dist/ThemeProvider-B6DyGqzh.d.cts.map +1 -0
- package/dist/ThemeProvider-BCrxBaY-.d.ts +62 -0
- package/dist/ThemeProvider-BCrxBaY-.d.ts.map +1 -0
- package/dist/ThemeProvider-BRN1tj4n.cjs +187 -0
- package/dist/ThemeProvider-BRN1tj4n.cjs.map +1 -0
- package/dist/ThemeProvider-C7K9iMLX.js +158 -0
- package/dist/ThemeProvider-C7K9iMLX.js.map +1 -0
- package/dist/WrittenResponse-Bj3eFmGl.cjs +491 -0
- package/dist/WrittenResponse-Bj3eFmGl.cjs.map +1 -0
- package/dist/WrittenResponse-Cl8G6nO_.js +486 -0
- package/dist/WrittenResponse-Cl8G6nO_.js.map +1 -0
- package/dist/ai/LkAiProvider.cjs +34 -14
- package/dist/ai/LkAiProvider.cjs.map +1 -1
- package/dist/ai/LkAiProvider.d.cts +2 -83
- package/dist/ai/LkAiProvider.d.ts +2 -83
- package/dist/ai/LkAiProvider.js +33 -2
- package/dist/ai/LkAiProvider.js.map +1 -1
- package/dist/ai/useAiHelp.cjs +7 -25
- package/dist/ai/useAiHelp.d.cts +175 -177
- package/dist/ai/useAiHelp.d.cts.map +1 -0
- package/dist/ai/useAiHelp.d.ts +175 -177
- package/dist/ai/useAiHelp.d.ts.map +1 -0
- package/dist/ai/useAiHelp.js +3 -4
- package/dist/components/ActivityPreview.cjs +3 -29
- package/dist/components/ActivityPreview.d.cts +2 -81
- package/dist/components/ActivityPreview.d.ts +2 -81
- package/dist/components/ActivityPreview.js +2 -20
- package/dist/components/ActivitySequence.cjs +3 -30
- package/dist/components/ActivitySequence.d.cts +2 -432
- package/dist/components/ActivitySequence.d.ts +2 -432
- package/dist/components/ActivitySequence.js +2 -21
- package/dist/components/Dictation.cjs +4 -21
- package/dist/components/Dictation.d.cts +2 -19
- package/dist/components/Dictation.d.ts +2 -19
- package/dist/components/Dictation.js +3 -12
- package/dist/components/FillInTheBlanks.cjs +4 -20
- package/dist/components/FillInTheBlanks.d.cts +2 -30
- package/dist/components/FillInTheBlanks.d.ts +2 -30
- package/dist/components/FillInTheBlanks.js +3 -11
- package/dist/components/GapSelect.cjs +4 -20
- package/dist/components/GapSelect.d.cts +2 -27
- package/dist/components/GapSelect.d.ts +2 -27
- package/dist/components/GapSelect.js +3 -11
- package/dist/components/InteractiveVideo.cjs +5 -32
- package/dist/components/InteractiveVideo.d.cts +3 -291
- package/dist/components/InteractiveVideo.d.ts +3 -291
- package/dist/components/InteractiveVideo.js +3 -19
- package/dist/components/MultipleChoice.cjs +4 -20
- package/dist/components/MultipleChoice.d.cts +2 -26
- package/dist/components/MultipleChoice.d.ts +2 -26
- package/dist/components/MultipleChoice.js +3 -11
- package/dist/components/PronunciationFeedback.cjs +4 -17
- package/dist/components/PronunciationFeedback.d.cts +2 -90
- package/dist/components/PronunciationFeedback.d.ts +2 -90
- package/dist/components/PronunciationFeedback.js +3 -8
- package/dist/components/ReadAloud.cjs +4 -22
- package/dist/components/ReadAloud.d.cts +7 -11
- package/dist/components/ReadAloud.d.cts.map +1 -0
- package/dist/components/ReadAloud.d.ts +7 -11
- package/dist/components/ReadAloud.d.ts.map +1 -0
- package/dist/components/ReadAloud.js +3 -13
- package/dist/components/StimulusPanel.cjs +3 -14
- package/dist/components/StimulusPanel.d.cts +2 -51
- package/dist/components/StimulusPanel.d.ts +2 -51
- package/dist/components/StimulusPanel.js +2 -5
- package/dist/components/WrittenResponse.cjs +4 -19
- package/dist/components/WrittenResponse.d.cts +3 -18
- package/dist/components/WrittenResponse.d.ts +3 -18
- package/dist/components/WrittenResponse.js +3 -10
- package/dist/direction-Dq0_HtA5.js +183 -0
- package/dist/direction-Dq0_HtA5.js.map +1 -0
- package/dist/direction-K1pj0HCA.cjs +200 -0
- package/dist/direction-K1pj0HCA.cjs.map +1 -0
- package/dist/hooks/useActivityState.cjs +28 -10
- package/dist/hooks/useActivityState.cjs.map +1 -1
- package/dist/hooks/useActivityState.d.cts +25 -24
- package/dist/hooks/useActivityState.d.cts.map +1 -0
- package/dist/hooks/useActivityState.d.ts +25 -24
- package/dist/hooks/useActivityState.d.ts.map +1 -0
- package/dist/hooks/useActivityState.js +28 -2
- package/dist/hooks/useActivityState.js.map +1 -1
- package/dist/hooks/useSpeechRecorder.cjs +5 -16
- package/dist/hooks/useSpeechRecorder.d.cts +2 -127
- package/dist/hooks/useSpeechRecorder.d.ts +2 -127
- package/dist/hooks/useSpeechRecorder.js +3 -3
- package/dist/hooks/useXAPI.cjs +126 -10
- package/dist/hooks/useXAPI.cjs.map +1 -1
- package/dist/hooks/useXAPI.d.cts +14 -14
- package/dist/hooks/useXAPI.d.cts.map +1 -0
- package/dist/hooks/useXAPI.d.ts +14 -14
- package/dist/hooks/useXAPI.d.ts.map +1 -0
- package/dist/hooks/useXAPI.js +126 -2
- package/dist/hooks/useXAPI.js.map +1 -1
- package/dist/i18n/LkIntlProvider.cjs +9 -32
- package/dist/i18n/LkIntlProvider.d.cts +34 -38
- package/dist/i18n/LkIntlProvider.d.cts.map +1 -0
- package/dist/i18n/LkIntlProvider.d.ts +34 -38
- package/dist/i18n/LkIntlProvider.d.ts.map +1 -0
- package/dist/i18n/LkIntlProvider.js +3 -3
- package/dist/index-6P4rJHrJ.d.cts +432 -0
- package/dist/index-6P4rJHrJ.d.cts.map +1 -0
- package/dist/index-90CX504k.d.ts +90 -0
- package/dist/index-90CX504k.d.ts.map +1 -0
- package/dist/index-B_SgnjsC.d.cts +291 -0
- package/dist/index-B_SgnjsC.d.cts.map +1 -0
- package/dist/index-BavVW5z5.d.cts +25 -0
- package/dist/index-BavVW5z5.d.cts.map +1 -0
- package/dist/index-BhHv6Fiu.d.cts +28 -0
- package/dist/index-BhHv6Fiu.d.cts.map +1 -0
- package/dist/index-Bsu8VciA.d.ts +432 -0
- package/dist/index-Bsu8VciA.d.ts.map +1 -0
- package/dist/index-C1KGpD1k.d.ts +49 -0
- package/dist/index-C1KGpD1k.d.ts.map +1 -0
- package/dist/index-CKTpYTCC.d.cts +49 -0
- package/dist/index-CKTpYTCC.d.cts.map +1 -0
- package/dist/index-CO_SRFJj.d.ts +16 -0
- package/dist/index-CO_SRFJj.d.ts.map +1 -0
- package/dist/index-CSsuUsP7.d.cts +124 -0
- package/dist/index-CSsuUsP7.d.cts.map +1 -0
- package/dist/index-CunUyeuN.d.cts +78 -0
- package/dist/index-CunUyeuN.d.cts.map +1 -0
- package/dist/index-CzfRzks6.d.cts +90 -0
- package/dist/index-CzfRzks6.d.cts.map +1 -0
- package/dist/index-D14xtpBS.d.cts +24 -0
- package/dist/index-D14xtpBS.d.cts.map +1 -0
- package/dist/index-DHRPAPZf.d.ts +291 -0
- package/dist/index-DHRPAPZf.d.ts.map +1 -0
- package/dist/index-DLV6cK26.d.cts +16 -0
- package/dist/index-DLV6cK26.d.cts.map +1 -0
- package/dist/index-DbCCQ9cP.d.ts +124 -0
- package/dist/index-DbCCQ9cP.d.ts.map +1 -0
- package/dist/index-DeV5B2m5.d.ts +24 -0
- package/dist/index-DeV5B2m5.d.ts.map +1 -0
- package/dist/index-TZCJVSge.d.ts +28 -0
- package/dist/index-TZCJVSge.d.ts.map +1 -0
- package/dist/index-ZVvLHsd3.d.ts +25 -0
- package/dist/index-ZVvLHsd3.d.ts.map +1 -0
- package/dist/index-eQwBgpSw.d.ts +78 -0
- package/dist/index-eQwBgpSw.d.ts.map +1 -0
- package/dist/index.cjs +118 -163
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -24
- package/dist/index.d.ts +20 -24
- package/dist/index.js +84 -29
- package/dist/index.js.map +1 -1
- package/dist/theme/ThemeProvider.cjs +8 -28
- package/dist/theme/ThemeProvider.d.cts +2 -59
- package/dist/theme/ThemeProvider.d.ts +2 -59
- package/dist/theme/ThemeProvider.js +3 -3
- package/dist/tries-CbbtZkdG.cjs +363 -0
- package/dist/tries-CbbtZkdG.cjs.map +1 -0
- package/dist/tries-DTHSrLCm.js +310 -0
- package/dist/tries-DTHSrLCm.js.map +1 -0
- package/dist/types-BOQd93x3.d.cts +994 -0
- package/dist/types-BOQd93x3.d.cts.map +1 -0
- package/dist/types-HIrgF_mS.d.ts +994 -0
- package/dist/types-HIrgF_mS.d.ts.map +1 -0
- package/dist/useAiHelp-B-ccDL5Q.js +906 -0
- package/dist/useAiHelp-B-ccDL5Q.js.map +1 -0
- package/dist/useAiHelp-h9yOLFqt.cjs +995 -0
- package/dist/useAiHelp-h9yOLFqt.cjs.map +1 -0
- package/dist/useSpeechRecorder--O_f-xvt.cjs +720 -0
- package/dist/useSpeechRecorder--O_f-xvt.cjs.map +1 -0
- package/dist/useSpeechRecorder-DtAYvl02.d.cts +154 -0
- package/dist/useSpeechRecorder-DtAYvl02.d.cts.map +1 -0
- package/dist/useSpeechRecorder-DtAYvl02.d.ts +154 -0
- package/dist/useSpeechRecorder-DtAYvl02.d.ts.map +1 -0
- package/dist/useSpeechRecorder-zIi9Dlw8.js +709 -0
- package/dist/useSpeechRecorder-zIi9Dlw8.js.map +1 -0
- package/package.json +10 -11
- package/dist/WrittenResponse-B7A5gHMj.d.ts +0 -115
- package/dist/WrittenResponse-BpL9p2Hn.d.cts +0 -115
- package/dist/ai/useAiHelp.cjs.map +0 -1
- package/dist/ai/useAiHelp.js.map +0 -1
- package/dist/chunk-2PNSVBLQ.cjs +0 -54
- package/dist/chunk-2PNSVBLQ.cjs.map +0 -1
- package/dist/chunk-2TW6WLBC.js +0 -80
- package/dist/chunk-2TW6WLBC.js.map +0 -1
- package/dist/chunk-4ZZWZSWI.js +0 -61
- package/dist/chunk-4ZZWZSWI.js.map +0 -1
- package/dist/chunk-6N43WDVG.js +0 -29
- package/dist/chunk-6N43WDVG.js.map +0 -1
- package/dist/chunk-7ALBSPYR.cjs +0 -436
- package/dist/chunk-7ALBSPYR.cjs.map +0 -1
- package/dist/chunk-7NFY3M3W.js +0 -234
- package/dist/chunk-7NFY3M3W.js.map +0 -1
- package/dist/chunk-7SB2MJA4.js +0 -29
- package/dist/chunk-7SB2MJA4.js.map +0 -1
- package/dist/chunk-ABJJ3LII.js +0 -434
- package/dist/chunk-ABJJ3LII.js.map +0 -1
- package/dist/chunk-BIGGXHAW.cjs +0 -342
- package/dist/chunk-BIGGXHAW.cjs.map +0 -1
- package/dist/chunk-C7QZE5BI.js +0 -430
- package/dist/chunk-C7QZE5BI.js.map +0 -1
- package/dist/chunk-CWTUWNV3.cjs +0 -2937
- package/dist/chunk-CWTUWNV3.cjs.map +0 -1
- package/dist/chunk-DC4CQCK5.js +0 -915
- package/dist/chunk-DS6HN3YR.cjs +0 -496
- package/dist/chunk-DS6HN3YR.cjs.map +0 -1
- package/dist/chunk-FDQR4GAZ.js +0 -240
- package/dist/chunk-FDQR4GAZ.js.map +0 -1
- package/dist/chunk-FKGMSOJF.js +0 -394
- package/dist/chunk-FKGMSOJF.js.map +0 -1
- package/dist/chunk-G6PXJ2SA.js +0 -823
- package/dist/chunk-G6PXJ2SA.js.map +0 -1
- package/dist/chunk-HNLRVRQR.js +0 -335
- package/dist/chunk-HNLRVRQR.js.map +0 -1
- package/dist/chunk-J3C72RPK.cjs +0 -31
- package/dist/chunk-J3C72RPK.cjs.map +0 -1
- package/dist/chunk-K63VPFOV.cjs +0 -134
- package/dist/chunk-K63VPFOV.cjs.map +0 -1
- package/dist/chunk-KFLIDTDU.cjs +0 -825
- package/dist/chunk-KFLIDTDU.cjs.map +0 -1
- package/dist/chunk-KHKH5LCT.cjs +0 -250
- package/dist/chunk-KHKH5LCT.cjs.map +0 -1
- package/dist/chunk-LBEKRN6Y.cjs +0 -664
- package/dist/chunk-LBEKRN6Y.cjs.map +0 -1
- package/dist/chunk-LPUWXIPR.cjs +0 -578
- package/dist/chunk-LPUWXIPR.cjs.map +0 -1
- package/dist/chunk-MCO52PV5.js +0 -520
- package/dist/chunk-MCO52PV5.js.map +0 -1
- package/dist/chunk-MKXEM2C5.cjs +0 -396
- package/dist/chunk-MKXEM2C5.cjs.map +0 -1
- package/dist/chunk-MXNC5UNO.js +0 -563
- package/dist/chunk-MXNC5UNO.js.map +0 -1
- package/dist/chunk-NAK55BYU.cjs +0 -859
- package/dist/chunk-NAK55BYU.cjs.map +0 -1
- package/dist/chunk-NDBMKGQ5.cjs +0 -599
- package/dist/chunk-NDBMKGQ5.cjs.map +0 -1
- package/dist/chunk-OD65OZIW.cjs +0 -159
- package/dist/chunk-OD65OZIW.cjs.map +0 -1
- package/dist/chunk-ORT3KLGI.js +0 -50
- package/dist/chunk-ORT3KLGI.js.map +0 -1
- package/dist/chunk-PNNUPUH4.cjs +0 -82
- package/dist/chunk-PNNUPUH4.cjs.map +0 -1
- package/dist/chunk-PWHECW6N.js +0 -2934
- package/dist/chunk-PWHECW6N.js.map +0 -1
- package/dist/chunk-RBS5A2DF.js +0 -857
- package/dist/chunk-RBS5A2DF.js.map +0 -1
- package/dist/chunk-RPWUDXG5.cjs +0 -63
- package/dist/chunk-RPWUDXG5.cjs.map +0 -1
- package/dist/chunk-TCDJY3H6.js +0 -494
- package/dist/chunk-TCDJY3H6.js.map +0 -1
- package/dist/chunk-TP5UMRAU.cjs +0 -918
- package/dist/chunk-TP5UMRAU.cjs.map +0 -1
- package/dist/chunk-TS7J6DTY.js +0 -597
- package/dist/chunk-TS7J6DTY.js.map +0 -1
- package/dist/chunk-TUVENMXB.cjs +0 -20
- package/dist/chunk-TUVENMXB.cjs.map +0 -1
- package/dist/chunk-UDCQTOVU.cjs +0 -523
- package/dist/chunk-UDCQTOVU.cjs.map +0 -1
- package/dist/chunk-UHKZXOXD.js +0 -128
- package/dist/chunk-UHKZXOXD.js.map +0 -1
- package/dist/chunk-V6BA44DS.cjs +0 -236
- package/dist/chunk-V6BA44DS.cjs.map +0 -1
- package/dist/chunk-XO5R73Y4.js +0 -653
- package/dist/chunk-XO5R73Y4.js.map +0 -1
- package/dist/chunk-XOR4MPEN.cjs +0 -31
- package/dist/chunk-XOR4MPEN.cjs.map +0 -1
- package/dist/chunk-YORQQXGO.js +0 -155
- package/dist/chunk-YORQQXGO.js.map +0 -1
- package/dist/chunk-YY4PFR3Z.cjs +0 -432
- package/dist/chunk-YY4PFR3Z.cjs.map +0 -1
- package/dist/chunk-ZPI6Q42R.js +0 -17
- package/dist/chunk-ZPI6Q42R.js.map +0 -1
- package/dist/components/ActivityPreview.cjs.map +0 -1
- package/dist/components/ActivityPreview.js.map +0 -1
- package/dist/components/ActivitySequence.cjs.map +0 -1
- package/dist/components/ActivitySequence.js.map +0 -1
- package/dist/components/Dictation.cjs.map +0 -1
- package/dist/components/Dictation.js.map +0 -1
- package/dist/components/FillInTheBlanks.cjs.map +0 -1
- package/dist/components/FillInTheBlanks.js.map +0 -1
- package/dist/components/GapSelect.cjs.map +0 -1
- package/dist/components/GapSelect.js.map +0 -1
- package/dist/components/InteractiveVideo.cjs.map +0 -1
- package/dist/components/InteractiveVideo.js.map +0 -1
- package/dist/components/MultipleChoice.cjs.map +0 -1
- package/dist/components/MultipleChoice.js.map +0 -1
- package/dist/components/PronunciationFeedback.cjs.map +0 -1
- package/dist/components/PronunciationFeedback.js.map +0 -1
- package/dist/components/ReadAloud.cjs.map +0 -1
- package/dist/components/ReadAloud.js.map +0 -1
- package/dist/components/StimulusPanel.cjs.map +0 -1
- package/dist/components/StimulusPanel.js.map +0 -1
- package/dist/components/WrittenResponse.cjs.map +0 -1
- package/dist/components/WrittenResponse.js.map +0 -1
- package/dist/hooks/useSpeechRecorder.cjs.map +0 -1
- package/dist/hooks/useSpeechRecorder.js.map +0 -1
- package/dist/i18n/LkIntlProvider.cjs.map +0 -1
- package/dist/i18n/LkIntlProvider.js.map +0 -1
- package/dist/machine-CuwKqWXC.d.cts +0 -26
- package/dist/machine-CuwKqWXC.d.ts +0 -26
- package/dist/theme/ThemeProvider.cjs.map +0 -1
- package/dist/theme/ThemeProvider.js.map +0 -1
- package/dist/types-C4IsUQsK.d.ts +0 -989
- package/dist/types-CJgZWtl4.d.cts +0 -989
package/dist/chunk-4ZZWZSWI.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { ActivityMedia } from './chunk-TS7J6DTY.js';
|
|
3
|
-
import { useLkStrings } from './chunk-HNLRVRQR.js';
|
|
4
|
-
import { useId, useMemo } from 'react';
|
|
5
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
-
|
|
7
|
-
function StimulusPanel({
|
|
8
|
-
stimulus,
|
|
9
|
-
range,
|
|
10
|
-
sanitizeHtml,
|
|
11
|
-
locale,
|
|
12
|
-
renderMode,
|
|
13
|
-
mediaBudget,
|
|
14
|
-
mediaStrings,
|
|
15
|
-
onInteraction,
|
|
16
|
-
disabled,
|
|
17
|
-
strings
|
|
18
|
-
}) {
|
|
19
|
-
const titleId = useId();
|
|
20
|
-
const s = useLkStrings(strings);
|
|
21
|
-
const bodyHtml = useMemo(() => {
|
|
22
|
-
if (sanitizeHtml === void 0 || typeof stimulus.bodyHtml !== "string") {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
return sanitizeHtml(stimulus.bodyHtml);
|
|
26
|
-
}, [stimulus.bodyHtml, sanitizeHtml]);
|
|
27
|
-
const rangeText = range === void 0 ? null : s.stimulusRange(range.first, range.last);
|
|
28
|
-
const naming = stimulus.title !== void 0 ? { "aria-labelledby": titleId } : { "aria-label": s.stimulusKind[stimulus.kind] };
|
|
29
|
-
const contentLang = stimulus.locale !== void 0 ? { lang: stimulus.locale } : {};
|
|
30
|
-
return /* @__PURE__ */ jsxs("section", { className: "lk-stimulus", "data-kind": stimulus.kind, lang: locale, ...naming, children: [
|
|
31
|
-
stimulus.title !== void 0 ? /* @__PURE__ */ jsx("p", { className: "lk-stimulus-title", id: titleId, ...contentLang, children: stimulus.title }) : null,
|
|
32
|
-
rangeText !== null ? /* @__PURE__ */ jsx("p", { className: "lk-stimulus-range", children: rangeText }) : null,
|
|
33
|
-
stimulus.media !== void 0 ? /* @__PURE__ */ jsx(
|
|
34
|
-
ActivityMedia,
|
|
35
|
-
{
|
|
36
|
-
media: stimulus.media,
|
|
37
|
-
...renderMode !== void 0 ? { renderMode } : {},
|
|
38
|
-
...mediaBudget !== void 0 ? { mediaBudget } : {},
|
|
39
|
-
...mediaStrings !== void 0 ? { mediaStrings } : {},
|
|
40
|
-
...strings !== void 0 ? { strings } : {},
|
|
41
|
-
...onInteraction !== void 0 ? { onInteraction } : {},
|
|
42
|
-
...disabled !== void 0 ? { disabled } : {},
|
|
43
|
-
...locale !== void 0 ? { locale } : {}
|
|
44
|
-
}
|
|
45
|
-
) : null,
|
|
46
|
-
bodyHtml !== null ? /* @__PURE__ */ jsx(
|
|
47
|
-
"div",
|
|
48
|
-
{
|
|
49
|
-
className: "lk-stimulus-body",
|
|
50
|
-
"data-format": "html",
|
|
51
|
-
...contentLang,
|
|
52
|
-
dangerouslySetInnerHTML: { __html: bodyHtml }
|
|
53
|
-
}
|
|
54
|
-
) : stimulus.body !== void 0 ? /* @__PURE__ */ jsx("div", { className: "lk-stimulus-body", "data-format": "text", ...contentLang, children: stimulus.body }) : null,
|
|
55
|
-
stimulus.attribution !== void 0 ? /* @__PURE__ */ jsx("p", { className: "lk-stimulus-attribution", ...contentLang, children: /* @__PURE__ */ jsx("cite", { children: stimulus.attribution }) }) : null
|
|
56
|
-
] });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export { StimulusPanel };
|
|
60
|
-
//# sourceMappingURL=chunk-4ZZWZSWI.js.map
|
|
61
|
-
//# sourceMappingURL=chunk-4ZZWZSWI.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/StimulusPanel/StimulusPanel.tsx"],"names":[],"mappings":"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","file":"chunk-4ZZWZSWI.js","sourcesContent":["'use client';\n\nimport type { InteractionEvent, Stimulus } from '@intellectif/lk-core';\nimport { useId, useMemo } from 'react';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport type { LkStringsOverride } from '../../i18n/strings.js';\nimport { ActivityMedia } from '../shared/ActivityMedia.js';\nimport type {\n HtmlSanitizer,\n MediaBudgetBinding,\n MediaTransportStrings,\n RenderMode,\n} from '../types.js';\n\nexport interface StimulusPanelProps {\n stimulus: Stimulus;\n /**\n * 1-based presented positions of the first and last question this material\n * serves, rendered as \"Questions 3–8\" so a learner knows how far the\n * passage carries.\n */\n range?: { first: number; last: number };\n /** Renders `stimulus.bodyHtml` when provided. See `HtmlSanitizer`. */\n sanitizeHtml?: HtmlSanitizer;\n locale?: string;\n /**\n * Forwarded to the stimulus's own media. `review` keeps the browser's control\n * bar even under an enforcing policy — a graded paper cannot be changed by\n * listening again.\n */\n renderMode?: RenderMode;\n /**\n * Binds this group's recording to a play budget the consumer persists. One\n * recording serves every question in the group, so the key is derived from\n * the ENTRY rather than the slot — see `stimulusMediaKey()` in lk-core.\n */\n mediaBudget?: MediaBudgetBinding;\n /** Translations for the audio transport chrome. */\n mediaStrings?: Partial<MediaTransportStrings>;\n onInteraction?: (event: InteractionEvent) => void;\n disabled?: boolean;\n /** Overrides the SDK's chrome text for this panel. See {@link LkIntlProvider}. */\n strings?: LkStringsOverride;\n}\n\n/**\n * Presents a shared stimulus — the passage, recording or image an item group's\n * questions refer to. A landmark region named by its title (or by its kind),\n * so a screen-reader user can jump back to the material from any question.\n *\n * Rich text follows the SDK-wide rule: `bodyHtml` is rendered only through a\n * caller-supplied sanitiser, and the plain `body` is the fallback — which the\n * schema guarantees exists whenever `bodyHtml` does.\n */\nexport function StimulusPanel({\n stimulus,\n range,\n sanitizeHtml,\n locale,\n renderMode,\n mediaBudget,\n mediaStrings,\n onInteraction,\n disabled,\n strings,\n}: StimulusPanelProps): React.JSX.Element {\n const titleId = useId();\n const s = useLkStrings(strings);\n\n const bodyHtml = useMemo(() => {\n if (sanitizeHtml === undefined || typeof stimulus.bodyHtml !== 'string') {\n return null;\n }\n return sanitizeHtml(stimulus.bodyHtml);\n }, [stimulus.bodyHtml, sanitizeHtml]);\n\n const rangeText = range === undefined ? null : s.stimulusRange(range.first, range.last);\n\n const naming =\n stimulus.title !== undefined\n ? { 'aria-labelledby': titleId }\n : { 'aria-label': s.stimulusKind[stimulus.kind] };\n\n // The AUTHORED parts carry the stimulus language; the SDK's own chrome does\n // not. Declaring `stimulus.locale` on the whole region made a screen reader\n // read \"Recording\" and \"Questions 3–5\" — English strings this package ships\n // — in the passage's voice, so a Spanish listening panel announced its own\n // name and the only orientation text in it with Spanish phonetics\n // (WCAG 3.1.2 Language of Parts). Scope the declaration to the content it\n // actually describes.\n const contentLang = stimulus.locale !== undefined ? { lang: stimulus.locale } : {};\n\n return (\n <section className=\"lk-stimulus\" data-kind={stimulus.kind} lang={locale} {...naming}>\n {stimulus.title !== undefined ? (\n <p className=\"lk-stimulus-title\" id={titleId} {...contentLang}>\n {stimulus.title}\n </p>\n ) : null}\n {rangeText !== null ? <p className=\"lk-stimulus-range\">{rangeText}</p> : null}\n {stimulus.media !== undefined ? (\n <ActivityMedia\n media={stimulus.media}\n {...(renderMode !== undefined ? { renderMode } : {})}\n {...(mediaBudget !== undefined ? { mediaBudget } : {})}\n {...(mediaStrings !== undefined ? { mediaStrings } : {})}\n {...(strings !== undefined ? { strings } : {})}\n {...(onInteraction !== undefined ? { onInteraction } : {})}\n {...(disabled !== undefined ? { disabled } : {})}\n {...(locale !== undefined ? { locale } : {})}\n />\n ) : null}\n {bodyHtml !== null ? (\n <div\n className=\"lk-stimulus-body\"\n data-format=\"html\"\n {...contentLang}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: rendered only through the caller-supplied HtmlSanitizer — the SDK never injects unsanitised markup\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n ) : stimulus.body !== undefined ? (\n <div className=\"lk-stimulus-body\" data-format=\"text\" {...contentLang}>\n {stimulus.body}\n </div>\n ) : null}\n {stimulus.attribution !== undefined ? (\n <p className=\"lk-stimulus-attribution\" {...contentLang}>\n <cite>{stimulus.attribution}</cite>\n </p>\n ) : null}\n </section>\n );\n}\n"]}
|
package/dist/chunk-6N43WDVG.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useState, useRef, useCallback } from 'react';
|
|
3
|
-
|
|
4
|
-
// src/hooks/useActivityState.ts
|
|
5
|
-
function useActivityState(initialState = "idle") {
|
|
6
|
-
const [state, setState] = useState(initialState);
|
|
7
|
-
const startTimeRef = useRef(null);
|
|
8
|
-
const start = useCallback(() => {
|
|
9
|
-
if (startTimeRef.current === null) {
|
|
10
|
-
startTimeRef.current = Date.now();
|
|
11
|
-
}
|
|
12
|
-
setState((prev) => prev === "idle" ? "in-progress" : prev);
|
|
13
|
-
}, []);
|
|
14
|
-
const complete = useCallback(() => setState("completed"), []);
|
|
15
|
-
const review = useCallback(() => setState("reviewing"), []);
|
|
16
|
-
const reset = useCallback((to = "idle") => {
|
|
17
|
-
startTimeRef.current = null;
|
|
18
|
-
setState(to);
|
|
19
|
-
}, []);
|
|
20
|
-
const getTimeSpent = useCallback(
|
|
21
|
-
() => startTimeRef.current === null ? 0 : Date.now() - startTimeRef.current,
|
|
22
|
-
[]
|
|
23
|
-
);
|
|
24
|
-
return { state, start, complete, review, reset, getTimeSpent };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export { useActivityState };
|
|
28
|
-
//# sourceMappingURL=chunk-6N43WDVG.js.map
|
|
29
|
-
//# sourceMappingURL=chunk-6N43WDVG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useActivityState.ts"],"names":[],"mappings":";;;AAgCO,SAAS,gBAAA,CAAiB,eAA8B,MAAA,EAAgC;AAM7F,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,YAAY,CAAA;AAC9D,EAAA,MAAM,YAAA,GAAe,OAAsB,IAAI,CAAA;AAE/C,EAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAG9B,IAAA,IAAI,YAAA,CAAa,YAAY,IAAA,EAAM;AACjC,MAAA,YAAA,CAAa,OAAA,GAAU,KAAK,GAAA,EAAI;AAAA,IAClC;AACA,IAAA,QAAA,CAAS,CAAC,IAAA,KAAU,IAAA,KAAS,MAAA,GAAS,gBAAgB,IAAK,CAAA;AAAA,EAC7D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAW,WAAA,CAAY,MAAM,SAAS,WAAW,CAAA,EAAG,EAAE,CAAA;AAE5D,EAAA,MAAM,SAAS,WAAA,CAAY,MAAM,SAAS,WAAW,CAAA,EAAG,EAAE,CAAA;AAE1D,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,CAAC,EAAA,GAAoB,MAAA,KAAW;AACxD,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,IAAA,QAAA,CAAS,EAAE,CAAA;AAAA,EACb,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,MAAO,aAAa,OAAA,KAAY,IAAA,GAAO,IAAI,IAAA,CAAK,GAAA,KAAQ,YAAA,CAAa,OAAA;AAAA,IACrE;AAAC,GACH;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,OAAO,YAAA,EAAa;AAC/D","file":"chunk-6N43WDVG.js","sourcesContent":["'use client';\n\nimport { useCallback, useRef, useState } from 'react';\n\nexport type ActivityState = 'idle' | 'in-progress' | 'completed' | 'reviewing';\n\nexport interface UseActivityStateResult {\n state: ActivityState;\n /** idle → in-progress; records start time once. Idempotent: repeated calls\n * (e.g. every learner interaction) neither restart timing nor regress state. */\n start: () => void;\n /** → completed. */\n complete: () => void;\n /** → reviewing (e.g. when showing correct answers). */\n review: () => void;\n /**\n * Clears timing and returns to `to`, defaulting to `idle`. Call when the\n * activity `data` prop changes.\n *\n * The target is a parameter because \"reset\" for a RESTORED item does not\n * mean idle: an item the learner had already submitted must come back\n * submitted, or a data-prop change quietly unlocks committed work.\n */\n reset: (to?: ActivityState) => void;\n /** Elapsed ms since `start()`; 0 when not started (or after `reset()`). */\n getTimeSpent: () => number;\n}\n\n/**\n * Tracks an activity's lifecycle state and elapsed time. Timing is held in a\n * ref (no re-render) and `getTimeSpent()` is read imperatively at submission.\n */\nexport function useActivityState(initialState: ActivityState = 'idle'): UseActivityStateResult {\n // `initialState` seeds the MOUNT only, like any `default*` value. It exists\n // so a resumed attempt can reopen a question the learner had already\n // submitted as submitted — without it, an exam that locks each question on\n // submit silently unlocks every one of them after a crash, and the learner\n // can answer and submit the same question twice.\n const [state, setState] = useState<ActivityState>(initialState);\n const startTimeRef = useRef<number | null>(null);\n\n const start = useCallback(() => {\n // Ref guard makes timing idempotent without a side effect in the updater\n // (StrictMode double-invokes updaters); the updater itself stays pure.\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n setState((prev) => (prev === 'idle' ? 'in-progress' : prev));\n }, []);\n\n const complete = useCallback(() => setState('completed'), []);\n\n const review = useCallback(() => setState('reviewing'), []);\n\n const reset = useCallback((to: ActivityState = 'idle') => {\n startTimeRef.current = null;\n setState(to);\n }, []);\n\n const getTimeSpent = useCallback(\n () => (startTimeRef.current === null ? 0 : Date.now() - startTimeRef.current),\n [],\n );\n\n return { state, start, complete, review, reset, getTimeSpent };\n}\n"]}
|
package/dist/chunk-7ALBSPYR.cjs
DELETED
|
@@ -1,436 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var chunkKHKH5LCT_cjs = require('./chunk-KHKH5LCT.cjs');
|
|
5
|
-
var chunk2PNSVBLQ_cjs = require('./chunk-2PNSVBLQ.cjs');
|
|
6
|
-
var chunkJ3C72RPK_cjs = require('./chunk-J3C72RPK.cjs');
|
|
7
|
-
var chunkLPUWXIPR_cjs = require('./chunk-LPUWXIPR.cjs');
|
|
8
|
-
var chunkNDBMKGQ5_cjs = require('./chunk-NDBMKGQ5.cjs');
|
|
9
|
-
var chunkXOR4MPEN_cjs = require('./chunk-XOR4MPEN.cjs');
|
|
10
|
-
var chunkBIGGXHAW_cjs = require('./chunk-BIGGXHAW.cjs');
|
|
11
|
-
var chunkTUVENMXB_cjs = require('./chunk-TUVENMXB.cjs');
|
|
12
|
-
var lkCore = require('@intellectif/lk-core');
|
|
13
|
-
var react = require('react');
|
|
14
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
15
|
-
|
|
16
|
-
var PLACEHOLDER = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
17
|
-
function parsePassage(passage) {
|
|
18
|
-
const segments = [];
|
|
19
|
-
const re = new RegExp(PLACEHOLDER);
|
|
20
|
-
let last = 0;
|
|
21
|
-
let ordinal = 0;
|
|
22
|
-
let match = re.exec(passage);
|
|
23
|
-
while (match !== null) {
|
|
24
|
-
if (match.index > last) {
|
|
25
|
-
segments.push({ kind: "text", value: passage.slice(last, match.index) });
|
|
26
|
-
}
|
|
27
|
-
ordinal += 1;
|
|
28
|
-
segments.push({ kind: "gap", id: match[1], ordinal });
|
|
29
|
-
last = match.index + match[0].length;
|
|
30
|
-
match = re.exec(passage);
|
|
31
|
-
}
|
|
32
|
-
if (last < passage.length) {
|
|
33
|
-
segments.push({ kind: "text", value: passage.slice(last) });
|
|
34
|
-
}
|
|
35
|
-
return segments;
|
|
36
|
-
}
|
|
37
|
-
var NO_SELECTIONS = {};
|
|
38
|
-
function selectionsOf(response) {
|
|
39
|
-
return response !== void 0 && response.type === "gap-select" ? response.selections : NO_SELECTIONS;
|
|
40
|
-
}
|
|
41
|
-
function correctnessByItem(details) {
|
|
42
|
-
const map = /* @__PURE__ */ new Map();
|
|
43
|
-
for (const detail of details) {
|
|
44
|
-
map.set(detail.itemId, chunkLPUWXIPR_cjs.detailIsRight(detail));
|
|
45
|
-
}
|
|
46
|
-
return map;
|
|
47
|
-
}
|
|
48
|
-
function choicesFor(banks, gap) {
|
|
49
|
-
if (gap.choices !== void 0) {
|
|
50
|
-
return gap.choices;
|
|
51
|
-
}
|
|
52
|
-
return banks?.find((bank) => bank.id === gap.bankId)?.choices ?? [];
|
|
53
|
-
}
|
|
54
|
-
function GapSelect({
|
|
55
|
-
data,
|
|
56
|
-
onComplete,
|
|
57
|
-
onSubmit,
|
|
58
|
-
onChange,
|
|
59
|
-
onInteraction,
|
|
60
|
-
value,
|
|
61
|
-
defaultValue,
|
|
62
|
-
defaultSubmitted,
|
|
63
|
-
renderMode = "practice",
|
|
64
|
-
outcome,
|
|
65
|
-
mediaBudget,
|
|
66
|
-
mediaStrings,
|
|
67
|
-
strings,
|
|
68
|
-
theme,
|
|
69
|
-
locale,
|
|
70
|
-
disabled,
|
|
71
|
-
shuffleSeed,
|
|
72
|
-
ai: aiProp,
|
|
73
|
-
delivery,
|
|
74
|
-
scoring
|
|
75
|
-
}) {
|
|
76
|
-
const isExam = renderMode === "exam";
|
|
77
|
-
const isReview = renderMode === "review";
|
|
78
|
-
const s = chunkBIGGXHAW_cjs.useLkStrings(strings);
|
|
79
|
-
const ai = chunkTUVENMXB_cjs.useLearnerAi(aiProp);
|
|
80
|
-
const policy = chunk2PNSVBLQ_cjs.useDeliveryPolicy(delivery);
|
|
81
|
-
const scoringPolicy = chunkKHKH5LCT_cjs.useItemScoringPolicy(scoring);
|
|
82
|
-
const devError = react.useMemo(() => {
|
|
83
|
-
if (!chunkLPUWXIPR_cjs.isDevelopment()) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
if (data.redacted === true) {
|
|
87
|
-
try {
|
|
88
|
-
lkCore.assertRedacted(data);
|
|
89
|
-
return null;
|
|
90
|
-
} catch (error) {
|
|
91
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const result2 = lkCore.validateActivity("gap-select", data);
|
|
95
|
-
return result2.success ? null : new lkCore.ActivitySchemaError("gap-select", result2.errors);
|
|
96
|
-
}, [data]);
|
|
97
|
-
const { state, start, complete, getTimeSpent, reset } = chunkXOR4MPEN_cjs.useActivityState(
|
|
98
|
-
defaultSubmitted === true ? "completed" : "idle"
|
|
99
|
-
);
|
|
100
|
-
const tries = chunkKHKH5LCT_cjs.useTries({
|
|
101
|
-
policy: scoringPolicy,
|
|
102
|
-
graded: renderMode === "practice" && policy.feedback,
|
|
103
|
-
submitted: state === "completed",
|
|
104
|
-
disabled: disabled === true
|
|
105
|
-
});
|
|
106
|
-
const resetTries = tries.reset;
|
|
107
|
-
const isControlled = value !== void 0;
|
|
108
|
-
const [internalSelections, setInternalSelections] = react.useState(
|
|
109
|
-
() => selectionsOf(defaultValue)
|
|
110
|
-
);
|
|
111
|
-
const [result, setResult] = react.useState(null);
|
|
112
|
-
const [summary, setSummary] = react.useState(null);
|
|
113
|
-
const [overall, setOverall] = react.useState(null);
|
|
114
|
-
const [feedbackHidden, setFeedbackHidden] = react.useState(false);
|
|
115
|
-
const seedHintsRef = react.useRef(chunkKHKH5LCT_cjs.hintsOf(value ?? defaultValue));
|
|
116
|
-
const formRef = react.useRef(null);
|
|
117
|
-
const feedbackRef = react.useRef(null);
|
|
118
|
-
const focusAfterRef = react.useRef(null);
|
|
119
|
-
const selections = isControlled ? selectionsOf(value) : internalSelections;
|
|
120
|
-
const defaultValueRef = react.useRef(defaultValue);
|
|
121
|
-
react.useEffect(() => {
|
|
122
|
-
defaultValueRef.current = defaultValue;
|
|
123
|
-
}, [defaultValue]);
|
|
124
|
-
const defaultSubmittedRef = react.useRef(defaultSubmitted);
|
|
125
|
-
react.useEffect(() => {
|
|
126
|
-
defaultSubmittedRef.current = defaultSubmitted;
|
|
127
|
-
}, [defaultSubmitted]);
|
|
128
|
-
const lastDataRef = react.useRef(data);
|
|
129
|
-
react.useEffect(() => {
|
|
130
|
-
if (lastDataRef.current === data) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
lastDataRef.current = data;
|
|
134
|
-
setInternalSelections(selectionsOf(defaultValueRef.current));
|
|
135
|
-
setResult(null);
|
|
136
|
-
setSummary(null);
|
|
137
|
-
setOverall(null);
|
|
138
|
-
setFeedbackHidden(false);
|
|
139
|
-
seedHintsRef.current = chunkKHKH5LCT_cjs.hintsOf(defaultValueRef.current);
|
|
140
|
-
resetTries();
|
|
141
|
-
reset(defaultSubmittedRef.current === true ? "completed" : "idle");
|
|
142
|
-
}, [data, reset, resetTries]);
|
|
143
|
-
const segments = react.useMemo(() => parsePassage(data.passage), [data.passage]);
|
|
144
|
-
const gapById = react.useMemo(() => new Map(data.gaps.map((gap) => [gap.id, gap])), [data.gaps]);
|
|
145
|
-
const sessionIdRef = react.useRef(null);
|
|
146
|
-
const choicesByGap = react.useMemo(() => {
|
|
147
|
-
const map = /* @__PURE__ */ new Map();
|
|
148
|
-
const seedSource = shuffleSeed ?? (sessionIdRef.current ??= chunkLPUWXIPR_cjs.randomSessionId());
|
|
149
|
-
for (const gap of data.gaps) {
|
|
150
|
-
const choices = choicesFor(data.banks, gap);
|
|
151
|
-
map.set(
|
|
152
|
-
gap.id,
|
|
153
|
-
data.shuffleChoices === true ? lkCore.seededShuffle(choices, `${seedSource}:${data.id}:${gap.id}`) : choices
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
return map;
|
|
157
|
-
}, [data, shuffleSeed]);
|
|
158
|
-
const answered = state === "completed";
|
|
159
|
-
const aiHints = chunkKHKH5LCT_cjs.useComponentAiHints({
|
|
160
|
-
ai,
|
|
161
|
-
data,
|
|
162
|
-
renderMode,
|
|
163
|
-
submitted: answered,
|
|
164
|
-
disabled: disabled === true,
|
|
165
|
-
response: { type: "gap-select", selections },
|
|
166
|
-
locale,
|
|
167
|
-
onInteraction,
|
|
168
|
-
strings: s,
|
|
169
|
-
delivery: policy
|
|
170
|
-
});
|
|
171
|
-
const hintsRevealed = renderMode === "practice" ? seedHintsRef.current + aiHints.used : 0;
|
|
172
|
-
const responseOf = (next) => ({
|
|
173
|
-
type: "gap-select",
|
|
174
|
-
selections: next,
|
|
175
|
-
...hintsRevealed > 0 ? { hintsRevealed } : {}
|
|
176
|
-
});
|
|
177
|
-
const hintsSeenRef = react.useRef(aiHints.used);
|
|
178
|
-
react.useEffect(() => {
|
|
179
|
-
if (hintsSeenRef.current === aiHints.used) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
hintsSeenRef.current = aiHints.used;
|
|
183
|
-
if (aiHints.used > 0) {
|
|
184
|
-
onChange?.(responseOf(selections));
|
|
185
|
-
}
|
|
186
|
-
}, [aiHints.used]);
|
|
187
|
-
react.useEffect(() => {
|
|
188
|
-
const target = focusAfterRef.current;
|
|
189
|
-
if (target === null) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
focusAfterRef.current = null;
|
|
193
|
-
if (target === "answer") {
|
|
194
|
-
formRef.current?.querySelector("select:not(:disabled)")?.focus();
|
|
195
|
-
} else {
|
|
196
|
-
feedbackRef.current?.focus();
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
if (devError) {
|
|
200
|
-
throw devError;
|
|
201
|
-
}
|
|
202
|
-
if (data.redacted === true && renderMode === "practice") {
|
|
203
|
-
throw new Error(
|
|
204
|
-
`Gap Select "${data.id}" received redacted activity data in renderMode "practice", which grades locally and has no answer key to grade against. Render redacted data with renderMode="exam" (server grades) or "review" (pass \`outcome\`).`
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
const submitted = state === "completed";
|
|
208
|
-
const inactive = disabled === true || submitted || isReview;
|
|
209
|
-
const revealing = isReview ? outcome?.status === "scored" : !isExam && submitted;
|
|
210
|
-
const marking = revealing && policy.feedback;
|
|
211
|
-
const fireInteraction = (type, payload) => {
|
|
212
|
-
onInteraction?.({ type, activityId: data.id, timestamp: Date.now(), payload });
|
|
213
|
-
};
|
|
214
|
-
const handleSelect = (gapId, choiceId) => {
|
|
215
|
-
if (inactive) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
if (state === "idle") {
|
|
219
|
-
start();
|
|
220
|
-
}
|
|
221
|
-
const next = { ...selections, [gapId]: choiceId };
|
|
222
|
-
if (!isControlled) {
|
|
223
|
-
setInternalSelections(next);
|
|
224
|
-
}
|
|
225
|
-
onChange?.(responseOf(next));
|
|
226
|
-
fireInteraction("gap-selected", { gapId, choiceId });
|
|
227
|
-
};
|
|
228
|
-
const handleSubmit = (event) => {
|
|
229
|
-
event.preventDefault();
|
|
230
|
-
if (inactive) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
const response = responseOf(selections);
|
|
234
|
-
onSubmit?.(response);
|
|
235
|
-
if (isExam) {
|
|
236
|
-
complete();
|
|
237
|
-
setSummary(s.answerSubmitted);
|
|
238
|
-
fireInteraction("submitted", { selections });
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
const answer = lkCore.score("gap-select", data, response);
|
|
242
|
-
complete();
|
|
243
|
-
const timeSpent = getTimeSpent();
|
|
244
|
-
const counted = tries.record({
|
|
245
|
-
score: answer.score,
|
|
246
|
-
maxScore: answer.maxScore,
|
|
247
|
-
hintsRevealed
|
|
248
|
-
});
|
|
249
|
-
const mine = counted.tries[counted.tries.length - 1];
|
|
250
|
-
const costed = mine === void 0 ? answer.score : mine.scored;
|
|
251
|
-
const scoringResult = costed === answer.score ? answer : { ...answer, score: costed, passed: lkCore.computePassThreshold(data, costed) };
|
|
252
|
-
const passed = counted.score === scoringResult.score ? scoringResult.passed : lkCore.computePassThreshold(data, counted.score);
|
|
253
|
-
const xapiStatement = lkCore.xAPIBuilder.buildAnsweredStatement({
|
|
254
|
-
actor: chunkLPUWXIPR_cjs.ANONYMOUS_ACTOR,
|
|
255
|
-
object: {
|
|
256
|
-
id: chunkLPUWXIPR_cjs.objectIdFor(data.id),
|
|
257
|
-
name: { [data.locale ?? "en-US"]: data.title },
|
|
258
|
-
...lkCore.xapiDefinitionFor(data)
|
|
259
|
-
},
|
|
260
|
-
scoringResult,
|
|
261
|
-
timeSpentMs: timeSpent,
|
|
262
|
-
response: JSON.stringify(selections)
|
|
263
|
-
});
|
|
264
|
-
setResult(answer);
|
|
265
|
-
onComplete?.(
|
|
266
|
-
chunkLPUWXIPR_cjs.stampTake(
|
|
267
|
-
{ score: counted.score, maxScore: counted.maxScore, passed, timeSpent, xapiStatement },
|
|
268
|
-
chunkLPUWXIPR_cjs.mintTake()
|
|
269
|
-
)
|
|
270
|
-
);
|
|
271
|
-
setOverall(answer.feedback);
|
|
272
|
-
setSummary(
|
|
273
|
-
`${s.answerSubmitted} ${s.scoreAnnouncement(Math.round(counted.score * 100), passed)}`
|
|
274
|
-
);
|
|
275
|
-
fireInteraction("submitted", { selections, score: scoringResult.score });
|
|
276
|
-
};
|
|
277
|
-
const retry = () => {
|
|
278
|
-
reset("idle");
|
|
279
|
-
setSummary(null);
|
|
280
|
-
setOverall(null);
|
|
281
|
-
focusAfterRef.current = "answer";
|
|
282
|
-
};
|
|
283
|
-
const closeTries = () => {
|
|
284
|
-
tries.close();
|
|
285
|
-
focusAfterRef.current = "feedback";
|
|
286
|
-
};
|
|
287
|
-
const correctByGap = react.useMemo(() => {
|
|
288
|
-
if (isExam) {
|
|
289
|
-
return /* @__PURE__ */ new Map();
|
|
290
|
-
}
|
|
291
|
-
if (isReview) {
|
|
292
|
-
return outcome?.status === "scored" ? correctnessByItem(outcome.details) : /* @__PURE__ */ new Map();
|
|
293
|
-
}
|
|
294
|
-
return correctnessByItem(result?.details ?? []);
|
|
295
|
-
}, [isExam, isReview, outcome, result]);
|
|
296
|
-
const reviewSummary = react.useMemo(() => {
|
|
297
|
-
if (!isReview || outcome === void 0) {
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
if (outcome.status === "scored") {
|
|
301
|
-
return `${s.scoreAnnouncement(Math.round(outcome.score * 100), outcome.passed)}${outcome.feedback ? ` ${outcome.feedback}` : ""}`;
|
|
302
|
-
}
|
|
303
|
-
if (outcome.status === "deferred") {
|
|
304
|
-
return s.notGradedYet;
|
|
305
|
-
}
|
|
306
|
-
if (outcome.status === "graded") {
|
|
307
|
-
const percent = outcome.maxScore > 0 ? Math.round(outcome.score / outcome.maxScore * 100) : Math.round(outcome.score * 100);
|
|
308
|
-
return `${s.scoreAnnouncement(percent, outcome.passed)}${outcome.feedback ? ` ${outcome.feedback}` : ""}`;
|
|
309
|
-
}
|
|
310
|
-
return s.noGradeAvailable;
|
|
311
|
-
}, [isReview, outcome, s]);
|
|
312
|
-
const anyFeedback = data.gaps.some((gap) => gap.feedback !== void 0);
|
|
313
|
-
const extra = !isReview && policy.feedback && submitted && tries.counted !== null ? chunkKHKH5LCT_cjs.triesSummary(s, scoringPolicy, tries.counted, tries.open) : "";
|
|
314
|
-
const announced = summary === null ? null : `${summary}${extra ? ` ${extra}` : ""}${overall ? ` ${overall}` : ""}`;
|
|
315
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
316
|
-
"form",
|
|
317
|
-
{
|
|
318
|
-
ref: formRef,
|
|
319
|
-
className: "lk-gs",
|
|
320
|
-
"aria-label": data.title,
|
|
321
|
-
lang: locale,
|
|
322
|
-
"data-render-mode": renderMode,
|
|
323
|
-
style: theme,
|
|
324
|
-
onSubmit: handleSubmit,
|
|
325
|
-
children: [
|
|
326
|
-
data.media ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
327
|
-
chunkNDBMKGQ5_cjs.ActivityMedia,
|
|
328
|
-
{
|
|
329
|
-
media: data.media,
|
|
330
|
-
renderMode,
|
|
331
|
-
...mediaBudget !== void 0 ? { mediaBudget } : {},
|
|
332
|
-
...mediaStrings !== void 0 ? { mediaStrings } : {},
|
|
333
|
-
...strings !== void 0 ? { strings } : {},
|
|
334
|
-
...onInteraction !== void 0 ? { onInteraction } : {},
|
|
335
|
-
...locale !== void 0 ? { locale } : {}
|
|
336
|
-
}
|
|
337
|
-
) : null,
|
|
338
|
-
/* @__PURE__ */ jsxRuntime.jsxs("fieldset", { disabled: inactive, children: [
|
|
339
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-gs-passage", children: segments.map((seg, i) => {
|
|
340
|
-
if (seg.kind === "text") {
|
|
341
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: seg.value }, `t${i}`);
|
|
342
|
-
}
|
|
343
|
-
const gap = gapById.get(seg.id);
|
|
344
|
-
if (!gap) {
|
|
345
|
-
return null;
|
|
346
|
-
}
|
|
347
|
-
const choices = choicesByGap.get(seg.id) ?? [];
|
|
348
|
-
const correctness = correctByGap.get(seg.id);
|
|
349
|
-
const gapFeedback = isExam ? void 0 : gap.feedback;
|
|
350
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "lk-gs-gap", children: [
|
|
351
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
352
|
-
"select",
|
|
353
|
-
{
|
|
354
|
-
className: "lk-gs-select",
|
|
355
|
-
"aria-label": s.gapLabel(seg.ordinal),
|
|
356
|
-
value: selections[seg.id] ?? "",
|
|
357
|
-
disabled: inactive,
|
|
358
|
-
"aria-disabled": inactive || void 0,
|
|
359
|
-
"data-correct": marking && correctness !== void 0 ? String(correctness) : void 0,
|
|
360
|
-
onChange: (e) => handleSelect(seg.id, e.target.value),
|
|
361
|
-
children: [
|
|
362
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: s.gapPlaceholder }),
|
|
363
|
-
choices.map((choice) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: choice.id, children: choice.text }, choice.id))
|
|
364
|
-
]
|
|
365
|
-
}
|
|
366
|
-
),
|
|
367
|
-
marking && !feedbackHidden && gapFeedback ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
368
|
-
"span",
|
|
369
|
-
{
|
|
370
|
-
className: "lk-gs-gap-feedback",
|
|
371
|
-
role: "note",
|
|
372
|
-
"data-correct": correctness !== void 0 ? String(correctness) : void 0,
|
|
373
|
-
children: gapFeedback
|
|
374
|
-
}
|
|
375
|
-
) : null
|
|
376
|
-
] }, seg.id);
|
|
377
|
-
}) }),
|
|
378
|
-
aiHints.offered && renderMode === "practice" ? /* @__PURE__ */ jsxRuntime.jsx(chunkKHKH5LCT_cjs.HintCost, { policy: scoringPolicy, strings: s }) : null,
|
|
379
|
-
/* @__PURE__ */ jsxRuntime.jsx(chunkKHKH5LCT_cjs.AiHints, { help: aiHints, ai, strings: s }),
|
|
380
|
-
isReview ? null : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: inactive, children: isExam ? s.submitAnswers : s.checkAnswers })
|
|
381
|
-
] }),
|
|
382
|
-
marking && anyFeedback ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
383
|
-
"button",
|
|
384
|
-
{
|
|
385
|
-
type: "button",
|
|
386
|
-
className: "lk-gs-feedback-toggle",
|
|
387
|
-
"aria-expanded": !feedbackHidden,
|
|
388
|
-
onClick: () => setFeedbackHidden((h) => !h),
|
|
389
|
-
children: feedbackHidden ? s.showFeedback : s.hideFeedback
|
|
390
|
-
}
|
|
391
|
-
) : null,
|
|
392
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
393
|
-
chunk2PNSVBLQ_cjs.FeedbackRegion,
|
|
394
|
-
{
|
|
395
|
-
id: `${data.id}-feedback`,
|
|
396
|
-
...scoringPolicy.retries > 0 ? { ref: feedbackRef } : {},
|
|
397
|
-
children: isReview ? policy.feedback || !chunk2PNSVBLQ_cjs.outcomeShowsMarks(outcome) ? reviewSummary : null : policy.feedback || summary === null ? announced : s.answerSubmitted
|
|
398
|
-
}
|
|
399
|
-
),
|
|
400
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
401
|
-
chunkKHKH5LCT_cjs.TryActions,
|
|
402
|
-
{
|
|
403
|
-
tries,
|
|
404
|
-
solutions: false,
|
|
405
|
-
strings: s,
|
|
406
|
-
onRetry: retry,
|
|
407
|
-
onClose: closeTries
|
|
408
|
-
}
|
|
409
|
-
),
|
|
410
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
411
|
-
chunkKHKH5LCT_cjs.AiExplanation,
|
|
412
|
-
{
|
|
413
|
-
ai,
|
|
414
|
-
data,
|
|
415
|
-
renderMode,
|
|
416
|
-
submitted,
|
|
417
|
-
response: { type: "gap-select", selections },
|
|
418
|
-
outcome,
|
|
419
|
-
locale,
|
|
420
|
-
onInteraction,
|
|
421
|
-
strings: s,
|
|
422
|
-
delivery: tries.open ? { ...policy, solutions: false } : policy
|
|
423
|
-
}
|
|
424
|
-
)
|
|
425
|
-
]
|
|
426
|
-
}
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
function GapSelect2(props) {
|
|
430
|
-
const strings = chunkBIGGXHAW_cjs.useLkStrings(props.strings);
|
|
431
|
-
return /* @__PURE__ */ jsxRuntime.jsx(chunkJ3C72RPK_cjs.ActivityErrorBoundary, { activityTitle: props.data?.title, strings, children: /* @__PURE__ */ jsxRuntime.jsx(GapSelect, { ...props }) });
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
exports.GapSelect = GapSelect2;
|
|
435
|
-
//# sourceMappingURL=chunk-7ALBSPYR.cjs.map
|
|
436
|
-
//# sourceMappingURL=chunk-7ALBSPYR.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/GapSelect/GapSelect.tsx","../src/components/GapSelect/index.tsx"],"names":["detailIsRight","useLkStrings","useLearnerAi","useDeliveryPolicy","useItemScoringPolicy","useMemo","isDevelopment","assertRedacted","result","validateActivity","ActivitySchemaError","useActivityState","useTries","useState","useRef","hintsOf","useEffect","randomSessionId","seededShuffle","useComponentAiHints","score","computePassThreshold","xAPIBuilder","ANONYMOUS_ACTOR","objectIdFor","xapiDefinitionFor","stampTake","mintTake","triesSummary","jsxs","jsx","ActivityMedia","HintCost","AiHints","FeedbackRegion","outcomeShowsMarks","TryActions","AiExplanation","GapSelect","ActivityErrorBoundary"],"mappings":"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","file":"chunk-7ALBSPYR.cjs","sourcesContent":["'use client';\n\nimport {\n ActivitySchemaError,\n assertRedacted,\n computePassThreshold,\n type GapSelectBank,\n type GapSelectChoice,\n type GapSelectData,\n type GapSelectGap,\n type GapSelectLearnerResponse,\n type LearnerResponse,\n type ScoringDetail,\n type ScoringResult,\n score,\n seededShuffle,\n validateActivity,\n xAPIBuilder,\n xapiDefinitionFor,\n} from '@intellectif/lk-core';\nimport { type CSSProperties, useEffect, useMemo, useRef, useState } from 'react';\nimport { useLearnerAi } from '../../ai/LkAiProvider.js';\nimport { useActivityState } from '../../hooks/useActivityState.js';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport {\n ANONYMOUS_ACTOR,\n detailIsRight,\n isDevelopment,\n objectIdFor,\n randomSessionId,\n} from '../_internal.js';\nimport { ActivityMedia } from '../shared/ActivityMedia.js';\nimport { AiExplanation, AiHints, useComponentAiHints } from '../shared/AiHelp.js';\nimport { outcomeShowsMarks, useDeliveryPolicy } from '../shared/delivery.js';\nimport { FeedbackRegion } from '../shared/FeedbackRegion.js';\nimport { mintTake, stampTake } from '../shared/sequence-slot.js';\nimport {\n HintCost,\n hintsOf,\n TryActions,\n triesSummary,\n useItemScoringPolicy,\n useTries,\n} from '../shared/tries.js';\nimport type { ActivityProps } from '../types.js';\n\nexport interface GapSelectProps extends ActivityProps<GapSelectData> {\n /**\n * Seeds the per-gap choice shuffle when `data.shuffleChoices` is set. Pass\n * the attempt id, exactly as on `<MultipleChoice>`: an order nobody can\n * reproduce cannot be reconciled with the attempt a server recorded. Without\n * one, a random per-mount seed is used — stable within the mount, and\n * deliberately not reproducible.\n */\n shuffleSeed?: string;\n}\n\nconst PLACEHOLDER = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\ntype Segment = { kind: 'text'; value: string } | { kind: 'gap'; id: string; ordinal: number };\n\n/** Splits a passage into literal text and its `{{id}}` gaps, in order. */\nfunction parsePassage(passage: string): Segment[] {\n const segments: Segment[] = [];\n const re = new RegExp(PLACEHOLDER);\n let last = 0;\n let ordinal = 0;\n let match = re.exec(passage);\n while (match !== null) {\n if (match.index > last) {\n segments.push({ kind: 'text', value: passage.slice(last, match.index) });\n }\n ordinal += 1;\n segments.push({ kind: 'gap', id: match[1] as string, ordinal });\n last = match.index + match[0].length;\n match = re.exec(passage);\n }\n if (last < passage.length) {\n segments.push({ kind: 'text', value: passage.slice(last) });\n }\n return segments;\n}\n\nconst NO_SELECTIONS: Record<string, string> = {};\n\n/**\n * The selections out of a `LearnerResponse`. A response of another activity\n * type reads as \"nothing selected\" rather than throwing — a controlled host\n * that has not yet swapped its state on an activity change would otherwise\n * crash the attempt.\n */\nfunction selectionsOf(response: LearnerResponse | undefined): Record<string, string> {\n return response !== undefined && response.type === 'gap-select'\n ? response.selections\n : NO_SELECTIONS;\n}\n\n/** Per-gap correctness keyed by gap id, from each detail's `outcome`. */\nfunction correctnessByItem(details: readonly ScoringDetail[]): Map<string, boolean> {\n const map = new Map<string, boolean>();\n for (const detail of details) {\n map.set(detail.itemId, detailIsRight(detail));\n }\n return map;\n}\n\n/**\n * The choices a gap offers: its own list, or the bank it names.\n *\n * Both survive redaction — they are what the learner picks from — so this is\n * the one resolution that works identically on full and redacted data.\n */\nfunction choicesFor(\n banks: readonly GapSelectBank[] | undefined,\n gap: GapSelectGap,\n): readonly GapSelectChoice[] {\n if (gap.choices !== undefined) {\n return gap.choices;\n }\n return banks?.find((bank) => bank.id === gap.bankId)?.choices ?? [];\n}\n\nexport function GapSelect({\n data,\n onComplete,\n onSubmit,\n onChange,\n onInteraction,\n value,\n defaultValue,\n defaultSubmitted,\n renderMode = 'practice',\n outcome,\n mediaBudget,\n mediaStrings,\n strings,\n theme,\n locale,\n disabled,\n shuffleSeed,\n ai: aiProp,\n delivery,\n scoring,\n}: GapSelectProps) {\n const isExam = renderMode === 'exam';\n const isReview = renderMode === 'review';\n const s = useLkStrings(strings);\n const ai = useLearnerAi(aiProp);\n const policy = useDeliveryPolicy(delivery);\n const scoringPolicy = useItemScoringPolicy(scoring);\n\n const devError = useMemo(() => {\n if (!isDevelopment()) {\n return null;\n }\n if (data.redacted === true) {\n try {\n assertRedacted(data);\n return null;\n } catch (error) {\n return error instanceof Error ? error : new Error(String(error));\n }\n }\n const result = validateActivity('gap-select', data);\n return result.success ? null : new ActivitySchemaError('gap-select', result.errors);\n }, [data]);\n\n const { state, start, complete, getTimeSpent, reset } = useActivityState(\n defaultSubmitted === true ? 'completed' : 'idle',\n );\n // Before anything that resets them: a new question starts with no tries.\n const tries = useTries({\n policy: scoringPolicy,\n graded: renderMode === 'practice' && policy.feedback,\n submitted: state === 'completed',\n disabled: disabled === true,\n });\n const resetTries = tries.reset;\n const isControlled = value !== undefined;\n const [internalSelections, setInternalSelections] = useState<Record<string, string>>(() =>\n selectionsOf(defaultValue),\n );\n const [result, setResult] = useState<ScoringResult | null>(null);\n const [summary, setSummary] = useState<string | null>(null);\n const [overall, setOverall] = useState<string | null>(null);\n const [feedbackHidden, setFeedbackHidden] = useState(false);\n // Hints the learner had been shown before this mount: a restored answer's\n // count stands, and the hints shown here add to it.\n const seedHintsRef = useRef(hintsOf(value ?? defaultValue));\n const formRef = useRef<HTMLFormElement>(null);\n const feedbackRef = useRef<HTMLDivElement>(null);\n const focusAfterRef = useRef<'answer' | 'feedback' | null>(null);\n\n const selections = isControlled ? selectionsOf(value) : internalSelections;\n\n const defaultValueRef = useRef(defaultValue);\n useEffect(() => {\n defaultValueRef.current = defaultValue;\n }, [defaultValue]);\n\n const defaultSubmittedRef = useRef(defaultSubmitted);\n useEffect(() => {\n defaultSubmittedRef.current = defaultSubmitted;\n }, [defaultSubmitted]);\n\n // Identity-guarded so the mount run is a no-op: without it this fires after\n // the first paint and undoes every seed it was just given (Req 3.7).\n const lastDataRef = useRef(data);\n useEffect(() => {\n if (lastDataRef.current === data) {\n return;\n }\n lastDataRef.current = data;\n setInternalSelections(selectionsOf(defaultValueRef.current));\n setResult(null);\n setSummary(null);\n setOverall(null);\n setFeedbackHidden(false);\n seedHintsRef.current = hintsOf(defaultValueRef.current);\n resetTries();\n reset(defaultSubmittedRef.current === true ? 'completed' : 'idle');\n }, [data, reset, resetTries]);\n\n const segments = useMemo(() => parsePassage(data.passage), [data.passage]);\n const gapById = useMemo(() => new Map(data.gaps.map((gap) => [gap.id, gap])), [data.gaps]);\n\n const sessionIdRef = useRef<string | null>(null);\n /**\n * The choices each gap shows, in the order it shows them.\n *\n * Seeded PER GAP, not once for the activity: two gaps drawing on the same\n * word bank must not be dealt the same order, or the bank's distractors line\n * up column-wise and the second gap becomes easier than the first.\n */\n const choicesByGap = useMemo(() => {\n const map = new Map<string, readonly GapSelectChoice[]>();\n // biome-ignore lint/suspicious/noAssignInExpressions: sanctioned lazy ref initialization\n const seedSource = shuffleSeed ?? (sessionIdRef.current ??= randomSessionId());\n for (const gap of data.gaps) {\n const choices = choicesFor(data.banks, gap);\n map.set(\n gap.id,\n data.shuffleChoices === true\n ? seededShuffle(choices, `${seedSource}:${data.id}:${gap.id}`)\n : choices,\n );\n }\n return map;\n }, [data, shuffleSeed]);\n\n // Hints are a hook, so they are read here, before the throws below.\n const answered = state === 'completed';\n const aiHints = useComponentAiHints({\n ai,\n data,\n renderMode,\n submitted: answered,\n disabled: disabled === true,\n response: { type: 'gap-select', selections },\n locale,\n onInteraction,\n strings: s,\n delivery: policy,\n });\n // Every hint the learner has been shown on this question, counted from its\n // start: what a scoring policy charges for. Hints exist only in practice.\n const hintsRevealed = renderMode === 'practice' ? seedHintsRef.current + aiHints.used : 0;\n const responseOf = (next: Record<string, string>): GapSelectLearnerResponse => ({\n type: 'gap-select',\n selections: next,\n ...(hintsRevealed > 0 ? { hintsRevealed } : {}),\n });\n // A hint shown is part of the answer's record: say so as it happens.\n const hintsSeenRef = useRef(aiHints.used);\n // biome-ignore lint/correctness/useExhaustiveDependencies: a new hint is the trigger, and the response it reports is this render's\n useEffect(() => {\n if (hintsSeenRef.current === aiHints.used) {\n return;\n }\n hintsSeenRef.current = aiHints.used;\n if (aiHints.used > 0) {\n onChange?.(responseOf(selections));\n }\n }, [aiHints.used]);\n useEffect(() => {\n const target = focusAfterRef.current;\n if (target === null) {\n return;\n }\n focusAfterRef.current = null;\n if (target === 'answer') {\n formRef.current?.querySelector<HTMLElement>('select:not(:disabled)')?.focus();\n } else {\n feedbackRef.current?.focus();\n }\n });\n\n // All hooks are called before these throws, so hook order stays stable.\n if (devError) {\n throw devError;\n }\n // Practice grades locally, and a redacted projection has no answer key to\n // grade against — `score()` would throw RedactedScoringError from the submit\n // handler, where no error boundary can reach it and after the learner has\n // answered. Fail at render instead, in production too, exactly as every other\n // built-in does.\n if (data.redacted === true && renderMode === 'practice') {\n throw new Error(\n `Gap Select \"${data.id}\" received redacted activity data in renderMode \"practice\", ` +\n 'which grades locally and has no answer key to grade against. ' +\n 'Render redacted data with renderMode=\"exam\" (server grades) or \"review\" (pass `outcome`).',\n );\n }\n\n const submitted = state === 'completed';\n const inactive = disabled === true || submitted || isReview;\n\n /**\n * Whether answer-key-derived information may be shown. Never in `exam`; in\n * `practice` only once this component has scored; in `review` only once the\n * caller supplies a SCORED outcome.\n */\n const revealing = isReview ? outcome?.status === 'scored' : !isExam && submitted;\n // What the delivery policy lets that reveal show: right and wrong, and the\n // author's feedback. A gap select never writes in the right choice, so\n // `solutions` has nothing here to hide.\n const marking = revealing && policy.feedback;\n\n const fireInteraction = (\n type: 'gap-selected' | 'submitted',\n payload: Record<string, unknown>,\n ): void => {\n onInteraction?.({ type, activityId: data.id, timestamp: Date.now(), payload });\n };\n\n const handleSelect = (gapId: string, choiceId: string): void => {\n if (inactive) {\n return;\n }\n if (state === 'idle') {\n start();\n }\n const next = { ...selections, [gapId]: choiceId };\n if (!isControlled) {\n setInternalSelections(next);\n }\n onChange?.(responseOf(next));\n fireInteraction('gap-selected', { gapId, choiceId });\n };\n\n const handleSubmit = (event: React.FormEvent): void => {\n event.preventDefault();\n if (inactive) {\n return;\n }\n const response = responseOf(selections);\n onSubmit?.(response);\n\n if (isExam) {\n // The client neither grades nor reveals: no score(), no read of any\n // answer-key field, no onComplete, and no xAPI statement — its\n // correctResponsesPattern IS the answer key.\n complete();\n setSummary(s.answerSubmitted);\n fireInteraction('submitted', { selections });\n return;\n }\n\n const answer = score('gap-select', data as GapSelectData, response);\n complete();\n const timeSpent = getTimeSpent();\n // The question's score under the policy — see MultipleChoice.\n const counted = tries.record({\n score: answer.score,\n maxScore: answer.maxScore,\n hintsRevealed,\n });\n const mine = counted.tries[counted.tries.length - 1];\n const costed = mine === undefined ? answer.score : mine.scored;\n const scoringResult =\n costed === answer.score\n ? answer\n : { ...answer, score: costed, passed: computePassThreshold(data as GapSelectData, costed) };\n const passed =\n counted.score === scoringResult.score\n ? scoringResult.passed\n : computePassThreshold(data as GapSelectData, counted.score);\n const xapiStatement = xAPIBuilder.buildAnsweredStatement({\n actor: ANONYMOUS_ACTOR,\n object: {\n id: objectIdFor(data.id),\n name: { [data.locale ?? 'en-US']: data.title },\n ...xapiDefinitionFor(data),\n },\n scoringResult,\n timeSpentMs: timeSpent,\n response: JSON.stringify(selections),\n });\n setResult(answer);\n onComplete?.(\n stampTake(\n { score: counted.score, maxScore: counted.maxScore, passed, timeSpent, xapiStatement },\n mintTake(),\n ),\n );\n setOverall(answer.feedback);\n setSummary(\n `${s.answerSubmitted} ${s.scoreAnnouncement(Math.round(counted.score * 100), passed)}`,\n );\n fireInteraction('submitted', { selections, score: scoringResult.score });\n };\n\n /** \"Try again\": the choices stay, to be changed; the marks go. */\n const retry = (): void => {\n reset('idle');\n setSummary(null);\n setOverall(null);\n focusAfterRef.current = 'answer';\n };\n\n /** \"Keep this answer\": no more tries. A gap select never writes in the right choice. */\n const closeTries = (): void => {\n tries.close();\n focusAfterRef.current = 'feedback';\n };\n\n const correctByGap = useMemo(() => {\n if (isExam) {\n return new Map<string, boolean>();\n }\n if (isReview) {\n return outcome?.status === 'scored'\n ? correctnessByItem(outcome.details)\n : new Map<string, boolean>();\n }\n return correctnessByItem(result?.details ?? []);\n }, [isExam, isReview, outcome, result]);\n\n const reviewSummary = useMemo(() => {\n if (!isReview || outcome === undefined) {\n return null;\n }\n if (outcome.status === 'scored') {\n return `${s.scoreAnnouncement(Math.round(outcome.score * 100), outcome.passed)}${\n outcome.feedback ? ` ${outcome.feedback}` : ''\n }`;\n }\n if (outcome.status === 'deferred') {\n return s.notGradedYet;\n }\n if (outcome.status === 'graded') {\n const percent =\n outcome.maxScore > 0\n ? Math.round((outcome.score / outcome.maxScore) * 100)\n : Math.round(outcome.score * 100);\n return `${s.scoreAnnouncement(percent, outcome.passed)}${\n outcome.feedback ? ` ${outcome.feedback}` : ''\n }`;\n }\n return s.noGradeAvailable;\n }, [isReview, outcome, s]);\n\n const anyFeedback = data.gaps.some((gap) => gap.feedback !== undefined);\n const extra =\n !isReview && policy.feedback && submitted && tries.counted !== null\n ? triesSummary(s, scoringPolicy, tries.counted, tries.open)\n : '';\n const announced =\n summary === null\n ? null\n : `${summary}${extra ? ` ${extra}` : ''}${overall ? ` ${overall}` : ''}`;\n\n return (\n <form\n ref={formRef}\n className=\"lk-gs\"\n aria-label={data.title}\n lang={locale}\n data-render-mode={renderMode}\n style={theme as CSSProperties | undefined}\n onSubmit={handleSubmit}\n >\n {data.media ? (\n <ActivityMedia\n media={data.media}\n renderMode={renderMode}\n {...(mediaBudget !== undefined ? { mediaBudget } : {})}\n {...(mediaStrings !== undefined ? { mediaStrings } : {})}\n {...(strings !== undefined ? { strings } : {})}\n {...(onInteraction !== undefined ? { onInteraction } : {})}\n {...(locale !== undefined ? { locale } : {})}\n />\n ) : null}\n <fieldset disabled={inactive}>\n <p className=\"lk-gs-passage\">\n {segments.map((seg, i) => {\n if (seg.kind === 'text') {\n // biome-ignore lint/suspicious/noArrayIndexKey: passage segments are positional and static\n return <span key={`t${i}`}>{seg.value}</span>;\n }\n const gap = gapById.get(seg.id);\n if (!gap) {\n return null;\n }\n const choices = choicesByGap.get(seg.id) ?? [];\n const correctness = correctByGap.get(seg.id);\n // Read defensively and never in exam: a redact() projection omits\n // both at runtime while the type still says they are there.\n const gapFeedback = isExam ? undefined : gap.feedback;\n return (\n <span key={seg.id} className=\"lk-gs-gap\">\n <select\n className=\"lk-gs-select\"\n aria-label={s.gapLabel(seg.ordinal)}\n value={selections[seg.id] ?? ''}\n disabled={inactive}\n aria-disabled={inactive || undefined}\n data-correct={\n marking && correctness !== undefined ? String(correctness) : undefined\n }\n onChange={(e) => handleSelect(seg.id, e.target.value)}\n >\n {/*\n The empty entry is part of the contract, not a decoration.\n It is how a learner leaves a gap alone — and how they take\n an answer back — so \"not answered\" stays distinguishable\n from \"answered wrongly\" all the way into ItemOutcome, where\n the scorer reports it as `incorrect-omission`.\n */}\n <option value=\"\">{s.gapPlaceholder}</option>\n {choices.map((choice) => (\n <option key={choice.id} value={choice.id}>\n {choice.text}\n </option>\n ))}\n </select>\n {marking && !feedbackHidden && gapFeedback ? (\n <span\n className=\"lk-gs-gap-feedback\"\n role=\"note\"\n data-correct={correctness !== undefined ? String(correctness) : undefined}\n >\n {gapFeedback}\n </span>\n ) : null}\n </span>\n );\n })}\n </p>\n {aiHints.offered && renderMode === 'practice' ? (\n <HintCost policy={scoringPolicy} strings={s} />\n ) : null}\n <AiHints help={aiHints} ai={ai} strings={s} />\n {isReview ? null : (\n <button type=\"submit\" disabled={inactive}>\n {isExam ? s.submitAnswers : s.checkAnswers}\n </button>\n )}\n </fieldset>\n {marking && anyFeedback ? (\n <button\n type=\"button\"\n className=\"lk-gs-feedback-toggle\"\n aria-expanded={!feedbackHidden}\n onClick={() => setFeedbackHidden((h) => !h)}\n >\n {feedbackHidden ? s.showFeedback : s.hideFeedback}\n </button>\n ) : null}\n <FeedbackRegion\n id={`${data.id}-feedback`}\n {...(scoringPolicy.retries > 0 ? { ref: feedbackRef } : {})}\n >\n {isReview\n ? policy.feedback || !outcomeShowsMarks(outcome)\n ? reviewSummary\n : null\n : policy.feedback || summary === null\n ? announced\n : s.answerSubmitted}\n </FeedbackRegion>\n <TryActions\n tries={tries}\n solutions={false}\n strings={s}\n onRetry={retry}\n onClose={closeTries}\n />\n <AiExplanation\n ai={ai}\n data={data}\n renderMode={renderMode}\n submitted={submitted}\n response={{ type: 'gap-select', selections }}\n outcome={outcome}\n locale={locale}\n onInteraction={onInteraction}\n strings={s}\n // An explanation all but always names the answer: not while another\n // try is on offer.\n delivery={tries.open ? { ...policy, solutions: false } : policy}\n />\n </form>\n );\n}\n","'use client';\n\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport { ActivityErrorBoundary } from '../ActivityErrorBoundary.js';\nimport { GapSelect as GapSelectCore, type GapSelectProps } from './GapSelect.js';\n\nexport type { GapSelectProps } from './GapSelect.js';\n\n/**\n * Public Gap Select activity: the core wrapped in `ActivityErrorBoundary` so a\n * render failure (including the dev schema-validation throw and the\n * redacted-in-`practice` guard) degrades to an accessible fallback instead of\n * crashing the host.\n */\nexport function GapSelect(props: GapSelectProps) {\n const strings = useLkStrings(props.strings);\n return (\n <ActivityErrorBoundary activityTitle={props.data?.title} strings={strings}>\n <GapSelectCore {...props} />\n </ActivityErrorBoundary>\n );\n}\n"]}
|