@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.
Files changed (360) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +9 -5
  3. package/dist/ActivityErrorBoundary-B379hvtL.cjs +39 -0
  4. package/dist/ActivityErrorBoundary-B379hvtL.cjs.map +1 -0
  5. package/dist/ActivityErrorBoundary-Dw6SbWv3.js +34 -0
  6. package/dist/ActivityErrorBoundary-Dw6SbWv3.js.map +1 -0
  7. package/dist/ActivityMedia-CQQTRNl7.cjs +641 -0
  8. package/dist/ActivityMedia-CQQTRNl7.cjs.map +1 -0
  9. package/dist/ActivityMedia-vDiP-Psa.js +636 -0
  10. package/dist/ActivityMedia-vDiP-Psa.js.map +1 -0
  11. package/dist/ActivityPreview-1hhTkYuj.js +240 -0
  12. package/dist/ActivityPreview-1hhTkYuj.js.map +1 -0
  13. package/dist/ActivityPreview-BKr34exz.cjs +245 -0
  14. package/dist/ActivityPreview-BKr34exz.cjs.map +1 -0
  15. package/dist/ActivitySequence-CkX87pfB.js +839 -0
  16. package/dist/ActivitySequence-CkX87pfB.js.map +1 -0
  17. package/dist/ActivitySequence-CmoSyDnp.cjs +844 -0
  18. package/dist/ActivitySequence-CmoSyDnp.cjs.map +1 -0
  19. package/dist/Dictation-BlxRp-3k.js +926 -0
  20. package/dist/Dictation-BlxRp-3k.js.map +1 -0
  21. package/dist/Dictation-jECzL88E.cjs +931 -0
  22. package/dist/Dictation-jECzL88E.cjs.map +1 -0
  23. package/dist/FeedbackRegion-BNNMtTY-.cjs +108 -0
  24. package/dist/FeedbackRegion-BNNMtTY-.cjs.map +1 -0
  25. package/dist/FeedbackRegion-CyPSp8bA.js +85 -0
  26. package/dist/FeedbackRegion-CyPSp8bA.js.map +1 -0
  27. package/dist/FillInTheBlanks-B6xzqYXx.js +474 -0
  28. package/dist/FillInTheBlanks-B6xzqYXx.js.map +1 -0
  29. package/dist/FillInTheBlanks-BpKhdHg2.cjs +479 -0
  30. package/dist/FillInTheBlanks-BpKhdHg2.cjs.map +1 -0
  31. package/dist/GapSelect-DUSiaEQH.js +441 -0
  32. package/dist/GapSelect-DUSiaEQH.js.map +1 -0
  33. package/dist/GapSelect-payTq_Zn.cjs +446 -0
  34. package/dist/GapSelect-payTq_Zn.cjs.map +1 -0
  35. package/dist/InteractiveVideo-BguGv-HA.cjs +2955 -0
  36. package/dist/InteractiveVideo-BguGv-HA.cjs.map +1 -0
  37. package/dist/InteractiveVideo-Cg2jbU3j.js +2944 -0
  38. package/dist/InteractiveVideo-Cg2jbU3j.js.map +1 -0
  39. package/dist/LkAiProvider-DAPpA3PQ.d.cts +84 -0
  40. package/dist/LkAiProvider-DAPpA3PQ.d.cts.map +1 -0
  41. package/dist/LkAiProvider-QdEcIhoo.d.ts +84 -0
  42. package/dist/LkAiProvider-QdEcIhoo.d.ts.map +1 -0
  43. package/dist/LkIntlProvider-D_FdYXjQ.js +375 -0
  44. package/dist/LkIntlProvider-D_FdYXjQ.js.map +1 -0
  45. package/dist/LkIntlProvider-oi57lYB0.cjs +410 -0
  46. package/dist/LkIntlProvider-oi57lYB0.cjs.map +1 -0
  47. package/dist/MultipleChoice-COn5MtKY.cjs +433 -0
  48. package/dist/MultipleChoice-COn5MtKY.cjs.map +1 -0
  49. package/dist/MultipleChoice-Dra0_KYD.js +428 -0
  50. package/dist/MultipleChoice-Dra0_KYD.js.map +1 -0
  51. package/dist/PronunciationFeedback-DlMPGjkR.cjs +831 -0
  52. package/dist/PronunciationFeedback-DlMPGjkR.cjs.map +1 -0
  53. package/dist/PronunciationFeedback-Dxd6XPkO.js +772 -0
  54. package/dist/PronunciationFeedback-Dxd6XPkO.js.map +1 -0
  55. package/dist/ReadAloud-C8RhaUqV.js +1092 -0
  56. package/dist/{chunk-DC4CQCK5.js.map → ReadAloud-C8RhaUqV.js.map} +1 -1
  57. package/dist/ReadAloud-akDehitT.cjs +1103 -0
  58. package/dist/ReadAloud-akDehitT.cjs.map +1 -0
  59. package/dist/StimulusPanel-BgzByfkb.js +74 -0
  60. package/dist/StimulusPanel-BgzByfkb.js.map +1 -0
  61. package/dist/StimulusPanel-b66gaN3i.cjs +79 -0
  62. package/dist/StimulusPanel-b66gaN3i.cjs.map +1 -0
  63. package/dist/ThemeProvider-B6DyGqzh.d.cts +62 -0
  64. package/dist/ThemeProvider-B6DyGqzh.d.cts.map +1 -0
  65. package/dist/ThemeProvider-BCrxBaY-.d.ts +62 -0
  66. package/dist/ThemeProvider-BCrxBaY-.d.ts.map +1 -0
  67. package/dist/ThemeProvider-BRN1tj4n.cjs +187 -0
  68. package/dist/ThemeProvider-BRN1tj4n.cjs.map +1 -0
  69. package/dist/ThemeProvider-C7K9iMLX.js +158 -0
  70. package/dist/ThemeProvider-C7K9iMLX.js.map +1 -0
  71. package/dist/WrittenResponse-Bj3eFmGl.cjs +491 -0
  72. package/dist/WrittenResponse-Bj3eFmGl.cjs.map +1 -0
  73. package/dist/WrittenResponse-Cl8G6nO_.js +486 -0
  74. package/dist/WrittenResponse-Cl8G6nO_.js.map +1 -0
  75. package/dist/ai/LkAiProvider.cjs +34 -14
  76. package/dist/ai/LkAiProvider.cjs.map +1 -1
  77. package/dist/ai/LkAiProvider.d.cts +2 -83
  78. package/dist/ai/LkAiProvider.d.ts +2 -83
  79. package/dist/ai/LkAiProvider.js +33 -2
  80. package/dist/ai/LkAiProvider.js.map +1 -1
  81. package/dist/ai/useAiHelp.cjs +7 -25
  82. package/dist/ai/useAiHelp.d.cts +175 -177
  83. package/dist/ai/useAiHelp.d.cts.map +1 -0
  84. package/dist/ai/useAiHelp.d.ts +175 -177
  85. package/dist/ai/useAiHelp.d.ts.map +1 -0
  86. package/dist/ai/useAiHelp.js +3 -4
  87. package/dist/components/ActivityPreview.cjs +3 -29
  88. package/dist/components/ActivityPreview.d.cts +2 -81
  89. package/dist/components/ActivityPreview.d.ts +2 -81
  90. package/dist/components/ActivityPreview.js +2 -20
  91. package/dist/components/ActivitySequence.cjs +3 -30
  92. package/dist/components/ActivitySequence.d.cts +2 -432
  93. package/dist/components/ActivitySequence.d.ts +2 -432
  94. package/dist/components/ActivitySequence.js +2 -21
  95. package/dist/components/Dictation.cjs +4 -21
  96. package/dist/components/Dictation.d.cts +2 -19
  97. package/dist/components/Dictation.d.ts +2 -19
  98. package/dist/components/Dictation.js +3 -12
  99. package/dist/components/FillInTheBlanks.cjs +4 -20
  100. package/dist/components/FillInTheBlanks.d.cts +2 -30
  101. package/dist/components/FillInTheBlanks.d.ts +2 -30
  102. package/dist/components/FillInTheBlanks.js +3 -11
  103. package/dist/components/GapSelect.cjs +4 -20
  104. package/dist/components/GapSelect.d.cts +2 -27
  105. package/dist/components/GapSelect.d.ts +2 -27
  106. package/dist/components/GapSelect.js +3 -11
  107. package/dist/components/InteractiveVideo.cjs +5 -32
  108. package/dist/components/InteractiveVideo.d.cts +3 -291
  109. package/dist/components/InteractiveVideo.d.ts +3 -291
  110. package/dist/components/InteractiveVideo.js +3 -19
  111. package/dist/components/MultipleChoice.cjs +4 -20
  112. package/dist/components/MultipleChoice.d.cts +2 -26
  113. package/dist/components/MultipleChoice.d.ts +2 -26
  114. package/dist/components/MultipleChoice.js +3 -11
  115. package/dist/components/PronunciationFeedback.cjs +4 -17
  116. package/dist/components/PronunciationFeedback.d.cts +2 -90
  117. package/dist/components/PronunciationFeedback.d.ts +2 -90
  118. package/dist/components/PronunciationFeedback.js +3 -8
  119. package/dist/components/ReadAloud.cjs +4 -22
  120. package/dist/components/ReadAloud.d.cts +7 -11
  121. package/dist/components/ReadAloud.d.cts.map +1 -0
  122. package/dist/components/ReadAloud.d.ts +7 -11
  123. package/dist/components/ReadAloud.d.ts.map +1 -0
  124. package/dist/components/ReadAloud.js +3 -13
  125. package/dist/components/StimulusPanel.cjs +3 -14
  126. package/dist/components/StimulusPanel.d.cts +2 -51
  127. package/dist/components/StimulusPanel.d.ts +2 -51
  128. package/dist/components/StimulusPanel.js +2 -5
  129. package/dist/components/WrittenResponse.cjs +4 -19
  130. package/dist/components/WrittenResponse.d.cts +3 -18
  131. package/dist/components/WrittenResponse.d.ts +3 -18
  132. package/dist/components/WrittenResponse.js +3 -10
  133. package/dist/direction-Dq0_HtA5.js +183 -0
  134. package/dist/direction-Dq0_HtA5.js.map +1 -0
  135. package/dist/direction-K1pj0HCA.cjs +200 -0
  136. package/dist/direction-K1pj0HCA.cjs.map +1 -0
  137. package/dist/hooks/useActivityState.cjs +28 -10
  138. package/dist/hooks/useActivityState.cjs.map +1 -1
  139. package/dist/hooks/useActivityState.d.cts +25 -24
  140. package/dist/hooks/useActivityState.d.cts.map +1 -0
  141. package/dist/hooks/useActivityState.d.ts +25 -24
  142. package/dist/hooks/useActivityState.d.ts.map +1 -0
  143. package/dist/hooks/useActivityState.js +28 -2
  144. package/dist/hooks/useActivityState.js.map +1 -1
  145. package/dist/hooks/useSpeechRecorder.cjs +5 -16
  146. package/dist/hooks/useSpeechRecorder.d.cts +2 -127
  147. package/dist/hooks/useSpeechRecorder.d.ts +2 -127
  148. package/dist/hooks/useSpeechRecorder.js +3 -3
  149. package/dist/hooks/useXAPI.cjs +126 -10
  150. package/dist/hooks/useXAPI.cjs.map +1 -1
  151. package/dist/hooks/useXAPI.d.cts +14 -14
  152. package/dist/hooks/useXAPI.d.cts.map +1 -0
  153. package/dist/hooks/useXAPI.d.ts +14 -14
  154. package/dist/hooks/useXAPI.d.ts.map +1 -0
  155. package/dist/hooks/useXAPI.js +126 -2
  156. package/dist/hooks/useXAPI.js.map +1 -1
  157. package/dist/i18n/LkIntlProvider.cjs +9 -32
  158. package/dist/i18n/LkIntlProvider.d.cts +34 -38
  159. package/dist/i18n/LkIntlProvider.d.cts.map +1 -0
  160. package/dist/i18n/LkIntlProvider.d.ts +34 -38
  161. package/dist/i18n/LkIntlProvider.d.ts.map +1 -0
  162. package/dist/i18n/LkIntlProvider.js +3 -3
  163. package/dist/index-6P4rJHrJ.d.cts +432 -0
  164. package/dist/index-6P4rJHrJ.d.cts.map +1 -0
  165. package/dist/index-90CX504k.d.ts +90 -0
  166. package/dist/index-90CX504k.d.ts.map +1 -0
  167. package/dist/index-B_SgnjsC.d.cts +291 -0
  168. package/dist/index-B_SgnjsC.d.cts.map +1 -0
  169. package/dist/index-BavVW5z5.d.cts +25 -0
  170. package/dist/index-BavVW5z5.d.cts.map +1 -0
  171. package/dist/index-BhHv6Fiu.d.cts +28 -0
  172. package/dist/index-BhHv6Fiu.d.cts.map +1 -0
  173. package/dist/index-Bsu8VciA.d.ts +432 -0
  174. package/dist/index-Bsu8VciA.d.ts.map +1 -0
  175. package/dist/index-C1KGpD1k.d.ts +49 -0
  176. package/dist/index-C1KGpD1k.d.ts.map +1 -0
  177. package/dist/index-CKTpYTCC.d.cts +49 -0
  178. package/dist/index-CKTpYTCC.d.cts.map +1 -0
  179. package/dist/index-CO_SRFJj.d.ts +16 -0
  180. package/dist/index-CO_SRFJj.d.ts.map +1 -0
  181. package/dist/index-CSsuUsP7.d.cts +124 -0
  182. package/dist/index-CSsuUsP7.d.cts.map +1 -0
  183. package/dist/index-CunUyeuN.d.cts +78 -0
  184. package/dist/index-CunUyeuN.d.cts.map +1 -0
  185. package/dist/index-CzfRzks6.d.cts +90 -0
  186. package/dist/index-CzfRzks6.d.cts.map +1 -0
  187. package/dist/index-D14xtpBS.d.cts +24 -0
  188. package/dist/index-D14xtpBS.d.cts.map +1 -0
  189. package/dist/index-DHRPAPZf.d.ts +291 -0
  190. package/dist/index-DHRPAPZf.d.ts.map +1 -0
  191. package/dist/index-DLV6cK26.d.cts +16 -0
  192. package/dist/index-DLV6cK26.d.cts.map +1 -0
  193. package/dist/index-DbCCQ9cP.d.ts +124 -0
  194. package/dist/index-DbCCQ9cP.d.ts.map +1 -0
  195. package/dist/index-DeV5B2m5.d.ts +24 -0
  196. package/dist/index-DeV5B2m5.d.ts.map +1 -0
  197. package/dist/index-TZCJVSge.d.ts +28 -0
  198. package/dist/index-TZCJVSge.d.ts.map +1 -0
  199. package/dist/index-ZVvLHsd3.d.ts +25 -0
  200. package/dist/index-ZVvLHsd3.d.ts.map +1 -0
  201. package/dist/index-eQwBgpSw.d.ts +78 -0
  202. package/dist/index-eQwBgpSw.d.ts.map +1 -0
  203. package/dist/index.cjs +118 -163
  204. package/dist/index.cjs.map +1 -1
  205. package/dist/index.d.cts +20 -24
  206. package/dist/index.d.ts +20 -24
  207. package/dist/index.js +84 -29
  208. package/dist/index.js.map +1 -1
  209. package/dist/theme/ThemeProvider.cjs +8 -28
  210. package/dist/theme/ThemeProvider.d.cts +2 -59
  211. package/dist/theme/ThemeProvider.d.ts +2 -59
  212. package/dist/theme/ThemeProvider.js +3 -3
  213. package/dist/tries-CbbtZkdG.cjs +363 -0
  214. package/dist/tries-CbbtZkdG.cjs.map +1 -0
  215. package/dist/tries-DTHSrLCm.js +310 -0
  216. package/dist/tries-DTHSrLCm.js.map +1 -0
  217. package/dist/types-BOQd93x3.d.cts +994 -0
  218. package/dist/types-BOQd93x3.d.cts.map +1 -0
  219. package/dist/types-HIrgF_mS.d.ts +994 -0
  220. package/dist/types-HIrgF_mS.d.ts.map +1 -0
  221. package/dist/useAiHelp-B-ccDL5Q.js +906 -0
  222. package/dist/useAiHelp-B-ccDL5Q.js.map +1 -0
  223. package/dist/useAiHelp-h9yOLFqt.cjs +995 -0
  224. package/dist/useAiHelp-h9yOLFqt.cjs.map +1 -0
  225. package/dist/useSpeechRecorder--O_f-xvt.cjs +720 -0
  226. package/dist/useSpeechRecorder--O_f-xvt.cjs.map +1 -0
  227. package/dist/useSpeechRecorder-DtAYvl02.d.cts +154 -0
  228. package/dist/useSpeechRecorder-DtAYvl02.d.cts.map +1 -0
  229. package/dist/useSpeechRecorder-DtAYvl02.d.ts +154 -0
  230. package/dist/useSpeechRecorder-DtAYvl02.d.ts.map +1 -0
  231. package/dist/useSpeechRecorder-zIi9Dlw8.js +709 -0
  232. package/dist/useSpeechRecorder-zIi9Dlw8.js.map +1 -0
  233. package/package.json +10 -11
  234. package/dist/WrittenResponse-B7A5gHMj.d.ts +0 -115
  235. package/dist/WrittenResponse-BpL9p2Hn.d.cts +0 -115
  236. package/dist/ai/useAiHelp.cjs.map +0 -1
  237. package/dist/ai/useAiHelp.js.map +0 -1
  238. package/dist/chunk-2PNSVBLQ.cjs +0 -54
  239. package/dist/chunk-2PNSVBLQ.cjs.map +0 -1
  240. package/dist/chunk-2TW6WLBC.js +0 -80
  241. package/dist/chunk-2TW6WLBC.js.map +0 -1
  242. package/dist/chunk-4ZZWZSWI.js +0 -61
  243. package/dist/chunk-4ZZWZSWI.js.map +0 -1
  244. package/dist/chunk-6N43WDVG.js +0 -29
  245. package/dist/chunk-6N43WDVG.js.map +0 -1
  246. package/dist/chunk-7ALBSPYR.cjs +0 -436
  247. package/dist/chunk-7ALBSPYR.cjs.map +0 -1
  248. package/dist/chunk-7NFY3M3W.js +0 -234
  249. package/dist/chunk-7NFY3M3W.js.map +0 -1
  250. package/dist/chunk-7SB2MJA4.js +0 -29
  251. package/dist/chunk-7SB2MJA4.js.map +0 -1
  252. package/dist/chunk-ABJJ3LII.js +0 -434
  253. package/dist/chunk-ABJJ3LII.js.map +0 -1
  254. package/dist/chunk-BIGGXHAW.cjs +0 -342
  255. package/dist/chunk-BIGGXHAW.cjs.map +0 -1
  256. package/dist/chunk-C7QZE5BI.js +0 -430
  257. package/dist/chunk-C7QZE5BI.js.map +0 -1
  258. package/dist/chunk-CWTUWNV3.cjs +0 -2937
  259. package/dist/chunk-CWTUWNV3.cjs.map +0 -1
  260. package/dist/chunk-DC4CQCK5.js +0 -915
  261. package/dist/chunk-DS6HN3YR.cjs +0 -496
  262. package/dist/chunk-DS6HN3YR.cjs.map +0 -1
  263. package/dist/chunk-FDQR4GAZ.js +0 -240
  264. package/dist/chunk-FDQR4GAZ.js.map +0 -1
  265. package/dist/chunk-FKGMSOJF.js +0 -394
  266. package/dist/chunk-FKGMSOJF.js.map +0 -1
  267. package/dist/chunk-G6PXJ2SA.js +0 -823
  268. package/dist/chunk-G6PXJ2SA.js.map +0 -1
  269. package/dist/chunk-HNLRVRQR.js +0 -335
  270. package/dist/chunk-HNLRVRQR.js.map +0 -1
  271. package/dist/chunk-J3C72RPK.cjs +0 -31
  272. package/dist/chunk-J3C72RPK.cjs.map +0 -1
  273. package/dist/chunk-K63VPFOV.cjs +0 -134
  274. package/dist/chunk-K63VPFOV.cjs.map +0 -1
  275. package/dist/chunk-KFLIDTDU.cjs +0 -825
  276. package/dist/chunk-KFLIDTDU.cjs.map +0 -1
  277. package/dist/chunk-KHKH5LCT.cjs +0 -250
  278. package/dist/chunk-KHKH5LCT.cjs.map +0 -1
  279. package/dist/chunk-LBEKRN6Y.cjs +0 -664
  280. package/dist/chunk-LBEKRN6Y.cjs.map +0 -1
  281. package/dist/chunk-LPUWXIPR.cjs +0 -578
  282. package/dist/chunk-LPUWXIPR.cjs.map +0 -1
  283. package/dist/chunk-MCO52PV5.js +0 -520
  284. package/dist/chunk-MCO52PV5.js.map +0 -1
  285. package/dist/chunk-MKXEM2C5.cjs +0 -396
  286. package/dist/chunk-MKXEM2C5.cjs.map +0 -1
  287. package/dist/chunk-MXNC5UNO.js +0 -563
  288. package/dist/chunk-MXNC5UNO.js.map +0 -1
  289. package/dist/chunk-NAK55BYU.cjs +0 -859
  290. package/dist/chunk-NAK55BYU.cjs.map +0 -1
  291. package/dist/chunk-NDBMKGQ5.cjs +0 -599
  292. package/dist/chunk-NDBMKGQ5.cjs.map +0 -1
  293. package/dist/chunk-OD65OZIW.cjs +0 -159
  294. package/dist/chunk-OD65OZIW.cjs.map +0 -1
  295. package/dist/chunk-ORT3KLGI.js +0 -50
  296. package/dist/chunk-ORT3KLGI.js.map +0 -1
  297. package/dist/chunk-PNNUPUH4.cjs +0 -82
  298. package/dist/chunk-PNNUPUH4.cjs.map +0 -1
  299. package/dist/chunk-PWHECW6N.js +0 -2934
  300. package/dist/chunk-PWHECW6N.js.map +0 -1
  301. package/dist/chunk-RBS5A2DF.js +0 -857
  302. package/dist/chunk-RBS5A2DF.js.map +0 -1
  303. package/dist/chunk-RPWUDXG5.cjs +0 -63
  304. package/dist/chunk-RPWUDXG5.cjs.map +0 -1
  305. package/dist/chunk-TCDJY3H6.js +0 -494
  306. package/dist/chunk-TCDJY3H6.js.map +0 -1
  307. package/dist/chunk-TP5UMRAU.cjs +0 -918
  308. package/dist/chunk-TP5UMRAU.cjs.map +0 -1
  309. package/dist/chunk-TS7J6DTY.js +0 -597
  310. package/dist/chunk-TS7J6DTY.js.map +0 -1
  311. package/dist/chunk-TUVENMXB.cjs +0 -20
  312. package/dist/chunk-TUVENMXB.cjs.map +0 -1
  313. package/dist/chunk-UDCQTOVU.cjs +0 -523
  314. package/dist/chunk-UDCQTOVU.cjs.map +0 -1
  315. package/dist/chunk-UHKZXOXD.js +0 -128
  316. package/dist/chunk-UHKZXOXD.js.map +0 -1
  317. package/dist/chunk-V6BA44DS.cjs +0 -236
  318. package/dist/chunk-V6BA44DS.cjs.map +0 -1
  319. package/dist/chunk-XO5R73Y4.js +0 -653
  320. package/dist/chunk-XO5R73Y4.js.map +0 -1
  321. package/dist/chunk-XOR4MPEN.cjs +0 -31
  322. package/dist/chunk-XOR4MPEN.cjs.map +0 -1
  323. package/dist/chunk-YORQQXGO.js +0 -155
  324. package/dist/chunk-YORQQXGO.js.map +0 -1
  325. package/dist/chunk-YY4PFR3Z.cjs +0 -432
  326. package/dist/chunk-YY4PFR3Z.cjs.map +0 -1
  327. package/dist/chunk-ZPI6Q42R.js +0 -17
  328. package/dist/chunk-ZPI6Q42R.js.map +0 -1
  329. package/dist/components/ActivityPreview.cjs.map +0 -1
  330. package/dist/components/ActivityPreview.js.map +0 -1
  331. package/dist/components/ActivitySequence.cjs.map +0 -1
  332. package/dist/components/ActivitySequence.js.map +0 -1
  333. package/dist/components/Dictation.cjs.map +0 -1
  334. package/dist/components/Dictation.js.map +0 -1
  335. package/dist/components/FillInTheBlanks.cjs.map +0 -1
  336. package/dist/components/FillInTheBlanks.js.map +0 -1
  337. package/dist/components/GapSelect.cjs.map +0 -1
  338. package/dist/components/GapSelect.js.map +0 -1
  339. package/dist/components/InteractiveVideo.cjs.map +0 -1
  340. package/dist/components/InteractiveVideo.js.map +0 -1
  341. package/dist/components/MultipleChoice.cjs.map +0 -1
  342. package/dist/components/MultipleChoice.js.map +0 -1
  343. package/dist/components/PronunciationFeedback.cjs.map +0 -1
  344. package/dist/components/PronunciationFeedback.js.map +0 -1
  345. package/dist/components/ReadAloud.cjs.map +0 -1
  346. package/dist/components/ReadAloud.js.map +0 -1
  347. package/dist/components/StimulusPanel.cjs.map +0 -1
  348. package/dist/components/StimulusPanel.js.map +0 -1
  349. package/dist/components/WrittenResponse.cjs.map +0 -1
  350. package/dist/components/WrittenResponse.js.map +0 -1
  351. package/dist/hooks/useSpeechRecorder.cjs.map +0 -1
  352. package/dist/hooks/useSpeechRecorder.js.map +0 -1
  353. package/dist/i18n/LkIntlProvider.cjs.map +0 -1
  354. package/dist/i18n/LkIntlProvider.js.map +0 -1
  355. package/dist/machine-CuwKqWXC.d.cts +0 -26
  356. package/dist/machine-CuwKqWXC.d.ts +0 -26
  357. package/dist/theme/ThemeProvider.cjs.map +0 -1
  358. package/dist/theme/ThemeProvider.js.map +0 -1
  359. package/dist/types-C4IsUQsK.d.ts +0 -989
  360. package/dist/types-CJgZWtl4.d.cts +0 -989
@@ -0,0 +1,995 @@
1
+ 'use client';
2
+ const require_ai_LkAiProvider = require("./ai/LkAiProvider.cjs");
3
+ let react = require("react");
4
+ let _intellectif_lk_core = require("@intellectif/lk-core");
5
+ //#region src/components/shared/sequence-slot.ts
6
+ /** `null` outside a pager: a standalone component belongs to no slot. */
7
+ const SequenceSlotContext = (0, react.createContext)(null);
8
+ /**
9
+ * The last take number handed out. Module-level and never reset, so a number
10
+ * is unique for the life of the page: across mounts, across papers, and across
11
+ * two pagers side by side. A result can therefore only ever match the take that
12
+ * produced it, whatever slot and activity ids a later paper reuses — ids a host
13
+ * chooses, and can repeat, never decide it.
14
+ */
15
+ let lastTake = 0;
16
+ /** A take number no other take on this page has had, or will have. */
17
+ function mintTake() {
18
+ lastTake += 1;
19
+ return lastTake;
20
+ }
21
+ /**
22
+ * The take each reported value belongs to. A `WeakMap` rather than a field, so
23
+ * a response or a result a host receives carries no extra key it would persist
24
+ * or compare, and the number never outlives the object.
25
+ */
26
+ const takes = /* @__PURE__ */ new WeakMap();
27
+ /** Marks `value` as produced by take `take`, and returns it. */
28
+ function stampTake(value, take) {
29
+ takes.set(value, take);
30
+ return value;
31
+ }
32
+ /** The take `value` was produced by, or `undefined` when nothing stamped it. */
33
+ function takeOf(value) {
34
+ return typeof value === "object" && value !== null ? takes.get(value) : void 0;
35
+ }
36
+ //#endregion
37
+ //#region src/components/_internal.ts
38
+ /**
39
+ * Whether this is anything other than a production build — the one answer
40
+ * every development check and the error boundary's stack trace read.
41
+ *
42
+ * **The literal `process.env.NODE_ENV`, spelled exactly so.** It is the one
43
+ * expression bundlers replace at build time — Vite, webpack, esbuild, Next.js
44
+ * and Rollup's replace plugin all substitute it — and a browser has no
45
+ * `process` to read at run time. The reading this replaces,
46
+ * `globalThis.process?.env?.NODE_ENV`, is not that expression, so no bundler
47
+ * touched it, and in a browser it found no `process` and answered
48
+ * "development" in every production app: learners were shown a stack trace
49
+ * where each component's production fallback belonged. Tests running in Node
50
+ * never saw it, because Node has a `process`.
51
+ *
52
+ * This package's own build must leave the literal in its output, for the
53
+ * consumer's bundler to replace. A library build that substituted it would
54
+ * freeze every consumer into whichever mode the library was built in.
55
+ *
56
+ * The `try` covers code that reaches a runtime unbundled, with no `process`
57
+ * at all: that is development, as it always was.
58
+ */
59
+ function isDevelopment() {
60
+ try {
61
+ return process.env.NODE_ENV !== "production";
62
+ } catch {
63
+ return true;
64
+ }
65
+ }
66
+ /**
67
+ * Activity components cannot know the learner's identity: `ActivityProps`
68
+ * carries none. They emit a structurally-valid statement with this anonymous
69
+ * actor; real identity is applied by the useXAPI/LRS layer (XAPIConfig.actor).
70
+ */
71
+ const ANONYMOUS_ACTOR = {
72
+ objectType: "Agent",
73
+ account: {
74
+ homePage: "https://github.com/intellectif/learning-kit",
75
+ name: "anonymous"
76
+ }
77
+ };
78
+ /** `data.id` is not an IRI; xAPI object ids must be. Wrap it as a URN. */
79
+ function objectIdFor(id) {
80
+ return `urn:learning-kit:activity:${encodeURIComponent(id)}`;
81
+ }
82
+ /**
83
+ * Random per-mount session id for the shuffle seed. `crypto.randomUUID` is
84
+ * unavailable outside secure contexts (plain-http LAN/staging hosts), so a
85
+ * Math.random fallback keeps the component from crashing there — the seed
86
+ * only randomises presentation order, so cryptographic strength is not needed.
87
+ */
88
+ function randomSessionId() {
89
+ const c = globalThis.crypto;
90
+ if (c?.randomUUID) return c.randomUUID();
91
+ return `s-${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
92
+ }
93
+ /**
94
+ * The `correct` flag of a detail stored before lk-core 0.3, which carries it in
95
+ * place of an `outcome`; `undefined` on any other detail. The type stopped
96
+ * describing it in 1.0, but a grade of record stored then still has it. On a
97
+ * blank, a gap or a word it meant the part was right; on a multiple-choice
98
+ * option, that the learner acted rightly on it.
99
+ */
100
+ function legacyCorrect(detail) {
101
+ const { correct } = detail;
102
+ return typeof correct === "boolean" ? correct : void 0;
103
+ }
104
+ /**
105
+ * Whether a detail marks its blank, gap or word right: its `outcome`, or on a
106
+ * detail stored before lk-core 0.3, its `correct` flag.
107
+ */
108
+ function detailIsRight(detail) {
109
+ const outcome = detail.outcome;
110
+ return outcome === void 0 ? legacyCorrect(detail) === true : outcome === "correct";
111
+ }
112
+ /**
113
+ * For the fallback of a dispatch over the built-in activity types — a
114
+ * `switch` default, or the end of an `if` chain: `value` has type `never`
115
+ * there only when every built-in type was handled above it, so a type lk-core
116
+ * gains fails to compile here until it has a component. At runtime it does
117
+ * nothing; what follows it decides what an unknown or custom type gets.
118
+ */
119
+ function everyBuiltInTypeHandled(_value) {}
120
+ //#endregion
121
+ //#region src/ai/rules.ts
122
+ /**
123
+ * When AI help is offered, and what the SDK does with what a port answers.
124
+ *
125
+ * Internal: these are the rules behind {@link useAiHints} and
126
+ * {@link useAiExplanation}, which are what a host calls. They live apart from
127
+ * the hooks so the hooks' module exports nothing but the hooks themselves.
128
+ */
129
+ /** The most hints a question gives when the host names no number, and the most it may name. */
130
+ const DEFAULT_MAX_HINTS = 3;
131
+ const MAX_HINTS_CEILING = 10;
132
+ /** A host's limit as a whole number from 1 to 10; anything else is the default, 3. */
133
+ function limitOf(asked) {
134
+ return typeof asked === "number" && Number.isInteger(asked) && asked >= 1 ? Math.min(asked, MAX_HINTS_CEILING) : DEFAULT_MAX_HINTS;
135
+ }
136
+ /** `maxHints` as a whole number from 1 to 10; anything else is the default. */
137
+ function hintLimit(ai) {
138
+ return limitOf(ai?.maxHints);
139
+ }
140
+ /** `maxWritingFeedback` as a whole number from 1 to 10; anything else is the default. */
141
+ function writingFeedbackLimit(ai) {
142
+ return limitOf(ai?.maxWritingFeedback);
143
+ }
144
+ /**
145
+ * Whether the learner may ask for feedback on a draft: `practice`, before
146
+ * submit, on a written response that is not disabled or redacted, whose author
147
+ * left explanations on. The paper's policy must show feedback and solutions —
148
+ * a correction is the right form beside a wrong one — and allow AI
149
+ * explanations, which writing feedback is: a model's words about the
150
+ * learner's own answer.
151
+ */
152
+ function writingFeedbackOffered(input) {
153
+ const { data, renderMode, submitted, disabled } = input;
154
+ const delivery = input.delivery ?? _intellectif_lk_core.OPEN_DELIVERY_POLICY;
155
+ return delivery.feedback && delivery.solutions && delivery.ai.explanations && renderMode === "practice" && !submitted && !disabled && data.redacted !== true && (0, _intellectif_lk_core.aiSupports)(data.type, "writing-feedback") && (0, _intellectif_lk_core.aiAllowedByContent)(data, "writing-feedback");
156
+ }
157
+ /**
158
+ * Whether the learner may ask for a hint: `practice`, before submit, on a
159
+ * question that is not disabled, of a type that takes hints, whose author left
160
+ * hints on, and whole — a redacted item is an exam's, and gives none.
161
+ */
162
+ function hintOffered(input) {
163
+ const { data, renderMode, submitted, disabled } = input;
164
+ const delivery = input.delivery ?? _intellectif_lk_core.OPEN_DELIVERY_POLICY;
165
+ return delivery.hints && delivery.ai.hints && renderMode === "practice" && !submitted && !disabled && data.redacted !== true && (0, _intellectif_lk_core.aiSupports)(data.type, "hint") && (0, _intellectif_lk_core.aiAllowedByContent)(data, "hint");
166
+ }
167
+ /**
168
+ * Whether the learner may ask for an explanation: of a graded answer — in
169
+ * `practice` once submitted, or in `review` when the grade of record is
170
+ * scored — of a type the SDK explains, whose author left explanations on.
171
+ * Never in `exam`.
172
+ */
173
+ function explanationOffered(input) {
174
+ const { data, renderMode, submitted, outcome } = input;
175
+ const delivery = input.delivery ?? _intellectif_lk_core.OPEN_DELIVERY_POLICY;
176
+ if (!delivery.feedback || !delivery.solutions || !delivery.ai.explanations) return false;
177
+ return (renderMode === "practice" && submitted || renderMode === "review" && outcome?.status === "scored") && (0, _intellectif_lk_core.aiSupports)(data.type, "explanation") && (0, _intellectif_lk_core.aiAllowedByContent)(data, "explanation");
178
+ }
179
+ /**
180
+ * Whether the learner may ask for coaching on a reading: one whose marks are
181
+ * on screen — which a read-aloud has only once it is graded, in `practice` or
182
+ * in `review` — never in `exam`, on a read-aloud whose author left
183
+ * explanations on. The paper's policy must show feedback, since the marks are
184
+ * feedback, and allow AI explanations, which coaching is: a model's words
185
+ * about the learner's own answer. Not `solutions`: a read-aloud hides no
186
+ * answer, and its text is on screen throughout.
187
+ */
188
+ function coachingOffered(input) {
189
+ const { data, renderMode, marked } = input;
190
+ const delivery = input.delivery ?? _intellectif_lk_core.OPEN_DELIVERY_POLICY;
191
+ return delivery.feedback && delivery.ai.explanations && renderMode !== "exam" && marked && (0, _intellectif_lk_core.aiSupports)(data.type, "pronunciation-coaching") && (0, _intellectif_lk_core.aiAllowedByContent)(data, "pronunciation-coaching");
192
+ }
193
+ /** Calls a port, turning a synchronous throw into a rejection. */
194
+ function callPort(call) {
195
+ try {
196
+ return Promise.resolve(call());
197
+ } catch (error) {
198
+ return Promise.reject(error);
199
+ }
200
+ }
201
+ /** Tells a developer why a port's answer was not shown. Silent in production. */
202
+ function warnRefused(feature, activityId, reason) {
203
+ if (isDevelopment()) console.warn(`learning-kit: the AI ${feature} for "${activityId}" was not shown (${reason}). The learner saw "not available" instead.`);
204
+ }
205
+ /** The language to write in: the host's choice for the learner, else the interface language. */
206
+ const localeOf = (ai, locale) => {
207
+ const chosen = ai?.learnerLocale ?? locale;
208
+ return chosen === void 0 ? {} : { learnerLocale: chosen };
209
+ };
210
+ /** What an explanation is about: when any of it changes, the explanation shown no longer is. */
211
+ function explanationKey(renderMode, submitted, response, outcome) {
212
+ let graded = "";
213
+ if (outcome !== void 0) graded = `${outcome.status}:${"score" in outcome ? outcome.score : ""}`;
214
+ return `${renderMode}|${submitted}|${graded}|${JSON.stringify(response)}`;
215
+ }
216
+ //#endregion
217
+ //#region src/ai/useAiHelp.ts
218
+ /**
219
+ * The mode a question is answered in: what the caller says, and what the paper
220
+ * around it says.
221
+ *
222
+ * A host drawing its own question is given `renderMode` like every other prop
223
+ * and is expected to pass it on, but nothing makes it — and a hook that took
224
+ * `practice` on trust would offer hints on a paper of record, as soon as an
225
+ * `LkAiProvider` sat anywhere above the pager. So an `exam` around the question
226
+ * wins, and where the caller says nothing the paper answers for it. A question
227
+ * standing on its own belongs to no paper, and is `practice` as before.
228
+ */
229
+ function modeInForce(asked, around) {
230
+ if (around === "exam") return "exam";
231
+ return asked ?? around ?? "practice";
232
+ }
233
+ /**
234
+ * What the record of help a learner was shown carries beside the fact of it:
235
+ * who wrote it, and what the call cost — both only where the port sent them.
236
+ *
237
+ * The text is deliberately absent. A host that wants to keep what a learner
238
+ * read has it in its own port; an interaction is a record of what happened, and
239
+ * is kept for every learner and every question.
240
+ */
241
+ function shownPayload(result) {
242
+ return {
243
+ ...result.provenance !== void 0 ? { provenance: result.provenance } : {},
244
+ ...result.usage !== void 0 ? { usage: result.usage } : {}
245
+ };
246
+ }
247
+ /**
248
+ * "Explain my answer", without the SDK's own button and panel: the rules, the
249
+ * call, the checks and the record, for a question you draw yourself.
250
+ *
251
+ * It is what `<MultipleChoice>` and the others use, so a host's own question
252
+ * offers help on exactly the same terms: never in `exam`, never where the
253
+ * item's author switched explanations off, and never an explanation whose
254
+ * verdict contradicts the grade the SDK computed.
255
+ *
256
+ * ```tsx
257
+ * const { offered, status, explanation, ask } = useAiExplanation({
258
+ * data, response, submitted, renderMode, outcome, ai: question.ai,
259
+ * });
260
+ * if (!offered) return null;
261
+ * return explanation === null ? (
262
+ * <button type="button" onClick={ask} aria-busy={status === 'loading'}>Explain my answer</button>
263
+ * ) : (
264
+ * <section>
265
+ * <p>{explanation.text}</p>
266
+ * <p>Written by AI. It can make mistakes.</p>
267
+ * </section>
268
+ * );
269
+ * ```
270
+ *
271
+ * **Say who wrote it.** The SDK's own panel carries "Written by AI. It can make
272
+ * mistakes."; a page that drops that line passes a model's words off as the
273
+ * course's.
274
+ *
275
+ * When the answer or its grade changes, the explanation is dropped and a call
276
+ * still on its way is abandoned — a late explanation never lands beside an
277
+ * answer it was not written for — as it is when the caller unmounts.
278
+ */
279
+ function useAiExplanation(input) {
280
+ const { data, response, submitted, outcome } = input;
281
+ const around = (0, react.useContext)(SequenceSlotContext);
282
+ const renderMode = modeInForce(input.renderMode, around?.renderMode);
283
+ const delivery = (0, _intellectif_lk_core.combineDeliveryPolicies)(input.delivery, around?.delivery);
284
+ const ai = require_ai_LkAiProvider.useLearnerAi(input.ai);
285
+ const resetKey = explanationKey(renderMode, submitted, response, outcome);
286
+ const [state, setState] = (0, react.useState)({
287
+ key: resetKey,
288
+ status: "idle"
289
+ });
290
+ const run = (0, react.useRef)(0);
291
+ const controller = (0, react.useRef)(null);
292
+ const current = state.key === resetKey ? state : {
293
+ key: resetKey,
294
+ status: "idle"
295
+ };
296
+ const offered = ai?.explain !== void 0 && explanationOffered({
297
+ data,
298
+ renderMode,
299
+ submitted,
300
+ outcome,
301
+ delivery
302
+ });
303
+ const latest = (0, react.useRef)({
304
+ input,
305
+ renderMode,
306
+ ai,
307
+ resetKey,
308
+ offered,
309
+ current
310
+ });
311
+ latest.current = {
312
+ input,
313
+ renderMode,
314
+ ai,
315
+ resetKey,
316
+ offered,
317
+ current
318
+ };
319
+ (0, react.useEffect)(() => {
320
+ return () => {
321
+ run.current += 1;
322
+ controller.current?.abort();
323
+ controller.current = null;
324
+ };
325
+ }, [resetKey]);
326
+ const ask = (0, react.useCallback)(() => {
327
+ const now = latest.current;
328
+ const port = now.ai?.explain;
329
+ if (port === void 0 || !now.offered || now.current.status === "loading") return;
330
+ const key = now.resetKey;
331
+ const request = (0, _intellectif_lk_core.aiExplanationRequest)({
332
+ data: now.input.data,
333
+ response: now.input.response,
334
+ ...now.renderMode === "review" && now.input.outcome !== void 0 ? { outcome: now.input.outcome } : {},
335
+ ...localeOf(now.ai, now.input.locale)
336
+ });
337
+ if (request === null) {
338
+ setState({
339
+ key,
340
+ status: "unavailable"
341
+ });
342
+ return;
343
+ }
344
+ run.current += 1;
345
+ const mine = run.current;
346
+ controller.current?.abort();
347
+ const abort = new AbortController();
348
+ controller.current = abort;
349
+ setState({
350
+ key,
351
+ status: "loading"
352
+ });
353
+ callPort(() => port(request, { signal: abort.signal })).then((raw) => {
354
+ if (run.current !== mine) return;
355
+ const checked = (0, _intellectif_lk_core.checkAiExplanation)(raw, request);
356
+ if (!checked.ok) {
357
+ warnRefused("explanation", now.input.data.id, checked.refusal);
358
+ setState({
359
+ key,
360
+ status: "unavailable"
361
+ });
362
+ latest.current.input.onInteraction?.({
363
+ type: "ai-help-refused",
364
+ activityId: now.input.data.id,
365
+ timestamp: Date.now(),
366
+ payload: {
367
+ feature: "explanation",
368
+ reason: checked.refusal
369
+ }
370
+ });
371
+ return;
372
+ }
373
+ setState({
374
+ key,
375
+ status: "shown",
376
+ result: checked.result
377
+ });
378
+ latest.current.input.onInteraction?.({
379
+ type: "ai-explanation-shown",
380
+ activityId: now.input.data.id,
381
+ timestamp: Date.now(),
382
+ payload: shownPayload(checked.result)
383
+ });
384
+ }, () => {
385
+ if (run.current === mine) setState({
386
+ key,
387
+ status: "unavailable"
388
+ });
389
+ });
390
+ }, []);
391
+ return {
392
+ offered,
393
+ status: current.status,
394
+ explanation: current.status === "shown" ? current.result : null,
395
+ ask
396
+ };
397
+ }
398
+ /**
399
+ * "Get a hint", without the SDK's own button and list: the rules, the call, the
400
+ * checks and the record, for a question you draw yourself.
401
+ *
402
+ * It is what `<MultipleChoice>` and the others use, so a host's own question
403
+ * gives hints on exactly the same terms: only in `practice` before submit, up
404
+ * to the host's limit, never on a redacted item or a type the SDK does not hint
405
+ * for, and never a hint that gives the answer away — which is refused rather
406
+ * than shown, and not counted.
407
+ *
408
+ * ```tsx
409
+ * const { offered, status, hints, used, limit, ask } = useAiHints({
410
+ * data, response, submitted, renderMode, ai: question.ai,
411
+ * });
412
+ * ```
413
+ *
414
+ * **Say who wrote them**, as the SDK's own list does: "Written by AI. It can
415
+ * make mistakes."
416
+ *
417
+ * Keep the hints on screen after submit — the learner can see what they were
418
+ * given — while `offered` turns false. Another question starts with none.
419
+ */
420
+ function useAiHints(input) {
421
+ const { data, submitted } = input;
422
+ const around = (0, react.useContext)(SequenceSlotContext);
423
+ const renderMode = modeInForce(input.renderMode, around?.renderMode);
424
+ const delivery = (0, _intellectif_lk_core.combineDeliveryPolicies)(input.delivery, around?.delivery);
425
+ const disabled = input.disabled === true;
426
+ const ai = require_ai_LkAiProvider.useLearnerAi(input.ai);
427
+ const resetKey = data.id;
428
+ const [state, setState] = (0, react.useState)({
429
+ key: resetKey,
430
+ hints: [],
431
+ status: "idle"
432
+ });
433
+ const run = (0, react.useRef)(0);
434
+ const controller = (0, react.useRef)(null);
435
+ const current = state.key === resetKey ? state : {
436
+ key: resetKey,
437
+ hints: [],
438
+ status: "idle"
439
+ };
440
+ const offered = ai?.hint !== void 0 && hintOffered({
441
+ data,
442
+ renderMode,
443
+ submitted,
444
+ disabled,
445
+ delivery
446
+ });
447
+ const limit = hintLimit(ai);
448
+ const latest = (0, react.useRef)({
449
+ input,
450
+ renderMode,
451
+ ai,
452
+ offered,
453
+ limit,
454
+ current
455
+ });
456
+ latest.current = {
457
+ input,
458
+ renderMode,
459
+ ai,
460
+ offered,
461
+ limit,
462
+ current
463
+ };
464
+ (0, react.useEffect)(() => {
465
+ return () => {
466
+ run.current += 1;
467
+ controller.current?.abort();
468
+ controller.current = null;
469
+ };
470
+ }, [resetKey]);
471
+ (0, react.useEffect)(() => {
472
+ if (!offered) {
473
+ run.current += 1;
474
+ controller.current?.abort();
475
+ controller.current = null;
476
+ setState((previous) => previous.status === "loading" ? {
477
+ ...previous,
478
+ status: "idle"
479
+ } : previous);
480
+ }
481
+ }, [offered]);
482
+ const ask = (0, react.useCallback)(() => {
483
+ const now = latest.current;
484
+ const port = now.ai?.hint;
485
+ const held = now.current;
486
+ if (port === void 0 || !now.offered || held.status === "loading" || held.hints.length >= now.limit) return;
487
+ const key = held.key;
488
+ const request = (0, _intellectif_lk_core.aiHintRequest)({
489
+ data: now.input.data,
490
+ response: now.input.response,
491
+ previousHints: held.hints.map((hint) => hint.text),
492
+ ...localeOf(now.ai, now.input.locale)
493
+ });
494
+ if (request === null) {
495
+ setState({
496
+ ...held,
497
+ status: "unavailable"
498
+ });
499
+ return;
500
+ }
501
+ run.current += 1;
502
+ const mine = run.current;
503
+ controller.current?.abort();
504
+ const abort = new AbortController();
505
+ controller.current = abort;
506
+ setState({
507
+ ...held,
508
+ status: "loading"
509
+ });
510
+ callPort(() => port(request, { signal: abort.signal })).then((raw) => {
511
+ if (run.current !== mine) return;
512
+ const checked = (0, _intellectif_lk_core.checkAiHint)(raw, request);
513
+ if (!checked.ok) {
514
+ warnRefused("hint", now.input.data.id, checked.refusal);
515
+ setState((shown) => ({
516
+ ...shown,
517
+ status: "unavailable"
518
+ }));
519
+ latest.current.input.onInteraction?.({
520
+ type: "ai-help-refused",
521
+ activityId: now.input.data.id,
522
+ timestamp: Date.now(),
523
+ payload: {
524
+ feature: "hint",
525
+ reason: checked.refusal,
526
+ hintNumber: request.hintNumber
527
+ }
528
+ });
529
+ return;
530
+ }
531
+ setState((shown) => ({
532
+ ...shown,
533
+ hints: shown.key === key ? [...shown.hints, checked.result] : shown.hints,
534
+ status: "idle"
535
+ }));
536
+ latest.current.input.onInteraction?.({
537
+ type: "ai-hint-shown",
538
+ activityId: now.input.data.id,
539
+ timestamp: Date.now(),
540
+ payload: {
541
+ hintNumber: request.hintNumber,
542
+ ...shownPayload(checked.result)
543
+ }
544
+ });
545
+ }, () => {
546
+ if (run.current === mine) setState((shown) => ({
547
+ ...shown,
548
+ status: "unavailable"
549
+ }));
550
+ });
551
+ }, []);
552
+ return {
553
+ offered,
554
+ status: current.status,
555
+ hints: current.hints,
556
+ limit,
557
+ used: current.hints.length,
558
+ ask
559
+ };
560
+ }
561
+ /** The text of a written response; another type's response is no draft at all. */
562
+ const draftOf = (response) => response.type === "written-response" ? response.text : "";
563
+ /**
564
+ * "Get feedback on my draft", without the SDK's own button and panel: the
565
+ * rules, the call, the checks and the record, for a written response you draw
566
+ * yourself.
567
+ *
568
+ * It is what `<WrittenResponse>` uses, so a host's own essay box gets feedback
569
+ * on the same terms: only in `practice` before submit, up to the host's limit,
570
+ * and never feedback that corrects words the learner did not write — which is
571
+ * refused rather than shown, and not counted.
572
+ *
573
+ * ```tsx
574
+ * const { offered, status, latest, current, used, limit, ask } = useAiWritingFeedback({
575
+ * data, response, submitted, renderMode, ai: question.ai,
576
+ * });
577
+ * ```
578
+ *
579
+ * **Say who wrote it**, as the SDK's own panel does: "Written by AI. It can make
580
+ * mistakes." And show `indicativeScore` as what it is — an indication, not a
581
+ * grade.
582
+ */
583
+ function useAiWritingFeedback(input) {
584
+ const { data, submitted, response } = input;
585
+ const around = (0, react.useContext)(SequenceSlotContext);
586
+ const renderMode = modeInForce(input.renderMode, around?.renderMode);
587
+ const delivery = (0, _intellectif_lk_core.combineDeliveryPolicies)(input.delivery, around?.delivery);
588
+ const disabled = input.disabled === true;
589
+ const ai = require_ai_LkAiProvider.useLearnerAi(input.ai);
590
+ const resetKey = data.id;
591
+ const [state, setState] = (0, react.useState)({
592
+ key: resetKey,
593
+ shown: [],
594
+ status: "idle"
595
+ });
596
+ const run = (0, react.useRef)(0);
597
+ const controller = (0, react.useRef)(null);
598
+ const current = state.key === resetKey ? state : {
599
+ key: resetKey,
600
+ shown: [],
601
+ status: "idle"
602
+ };
603
+ const offered = ai?.writingFeedback !== void 0 && writingFeedbackOffered({
604
+ data,
605
+ renderMode,
606
+ submitted,
607
+ disabled,
608
+ delivery
609
+ });
610
+ const limit = writingFeedbackLimit(ai);
611
+ const latest = (0, react.useRef)({
612
+ input,
613
+ ai,
614
+ offered,
615
+ limit,
616
+ current
617
+ });
618
+ latest.current = {
619
+ input,
620
+ ai,
621
+ offered,
622
+ limit,
623
+ current
624
+ };
625
+ (0, react.useEffect)(() => {
626
+ return () => {
627
+ run.current += 1;
628
+ controller.current?.abort();
629
+ controller.current = null;
630
+ };
631
+ }, [resetKey]);
632
+ (0, react.useEffect)(() => {
633
+ if (!offered) {
634
+ run.current += 1;
635
+ controller.current?.abort();
636
+ controller.current = null;
637
+ setState((previous) => previous.status === "loading" ? {
638
+ ...previous,
639
+ status: "idle"
640
+ } : previous);
641
+ }
642
+ }, [offered]);
643
+ const ask = (0, react.useCallback)(() => {
644
+ const now = latest.current;
645
+ const port = now.ai?.writingFeedback;
646
+ const held = now.current;
647
+ if (port === void 0 || !now.offered || held.status === "loading" || held.shown.length >= now.limit) return;
648
+ const key = held.key;
649
+ const about = draftOf(now.input.response);
650
+ const request = (0, _intellectif_lk_core.aiWritingFeedbackRequest)({
651
+ data: now.input.data,
652
+ response: now.input.response,
653
+ previousFeedback: held.shown.map((one) => one.feedback.text),
654
+ ...localeOf(now.ai, now.input.locale)
655
+ });
656
+ if (request === null) return;
657
+ run.current += 1;
658
+ const mine = run.current;
659
+ controller.current?.abort();
660
+ const abort = new AbortController();
661
+ controller.current = abort;
662
+ setState({
663
+ ...held,
664
+ status: "loading"
665
+ });
666
+ callPort(() => port(request, { signal: abort.signal })).then((raw) => {
667
+ if (run.current !== mine) return;
668
+ const checked = (0, _intellectif_lk_core.checkAiWritingFeedback)(raw, request);
669
+ if (!checked.ok) {
670
+ warnRefused("writing feedback", now.input.data.id, checked.refusal);
671
+ setState((was) => ({
672
+ ...was,
673
+ status: "unavailable"
674
+ }));
675
+ latest.current.input.onInteraction?.({
676
+ type: "ai-help-refused",
677
+ activityId: now.input.data.id,
678
+ timestamp: Date.now(),
679
+ payload: {
680
+ feature: "writing-feedback",
681
+ reason: checked.refusal,
682
+ draftNumber: request.draftNumber
683
+ }
684
+ });
685
+ return;
686
+ }
687
+ const { feedback } = checked;
688
+ setState((was) => ({
689
+ ...was,
690
+ shown: was.key === key ? [...was.shown, {
691
+ feedback,
692
+ about
693
+ }] : was.shown,
694
+ status: "idle"
695
+ }));
696
+ latest.current.input.onInteraction?.({
697
+ type: "ai-writing-feedback-shown",
698
+ activityId: now.input.data.id,
699
+ timestamp: Date.now(),
700
+ payload: {
701
+ draftNumber: request.draftNumber,
702
+ corrections: feedback.corrections.length,
703
+ ...feedback.indicativeScore !== null ? { indicativeScore: feedback.indicativeScore } : {},
704
+ ...shownPayload(feedback)
705
+ }
706
+ });
707
+ }, () => {
708
+ if (run.current === mine) setState((was) => ({
709
+ ...was,
710
+ status: "unavailable"
711
+ }));
712
+ });
713
+ }, []);
714
+ const last = current.shown[current.shown.length - 1];
715
+ return {
716
+ offered,
717
+ status: current.status,
718
+ feedback: current.shown.map((one) => one.feedback),
719
+ latest: last?.feedback ?? null,
720
+ current: last !== void 0 && last.about === draftOf(response),
721
+ limit,
722
+ used: current.shown.length,
723
+ ask
724
+ };
725
+ }
726
+ /**
727
+ * "Coach me on this reading", without the SDK's own button and panel: the
728
+ * rules, the call, the checks and the record, for marks you draw yourself.
729
+ *
730
+ * It is what `<PronunciationFeedback>` and `<ReadAloud>` use, so a host's own
731
+ * marks get coaching on the same terms: never in `exam`, never where the
732
+ * item's author switched explanations off, and never coaching on a word the
733
+ * engine did not mark or a sound it did not report — which is refused whole.
734
+ *
735
+ * ```tsx
736
+ * const { offered, status, coaching, ask } = useAiCoaching({
737
+ * data: item, assessment, grade, renderMode, ai,
738
+ * });
739
+ * ```
740
+ *
741
+ * **Say who wrote it**, as the SDK's own panel does: "Written by AI. It can make
742
+ * mistakes." The marks beside it are the engine's; the coaching is a model's.
743
+ *
744
+ * Another reading — other marks, another text — drops the coaching and
745
+ * abandons a call still on its way, as the caller unmounting does.
746
+ */
747
+ function useAiCoaching(input) {
748
+ const { data, assessment, grade } = input;
749
+ const around = (0, react.useContext)(SequenceSlotContext);
750
+ const renderMode = modeInForce(input.renderMode, around?.renderMode);
751
+ const delivery = (0, _intellectif_lk_core.combineDeliveryPolicies)(input.delivery, around?.delivery);
752
+ const ai = require_ai_LkAiProvider.useLearnerAi(input.ai);
753
+ const { learnerLocale } = localeOf(ai, input.locale);
754
+ const { id, title, referenceText, locale: itemLocale, instructions, ai: permissions } = data;
755
+ const request = (0, react.useMemo)(() => {
756
+ return (0, _intellectif_lk_core.aiCoachingRequest)({
757
+ data: {
758
+ type: "read-aloud",
759
+ id,
760
+ title,
761
+ referenceText,
762
+ locale: itemLocale,
763
+ instructions,
764
+ ai: permissions
765
+ },
766
+ ...assessment !== void 0 && assessment !== null ? { assessment } : {},
767
+ ...grade !== void 0 && grade !== null ? { grade } : {},
768
+ ...learnerLocale !== void 0 ? { learnerLocale } : {}
769
+ });
770
+ }, [
771
+ id,
772
+ title,
773
+ referenceText,
774
+ itemLocale,
775
+ instructions,
776
+ permissions,
777
+ assessment,
778
+ grade,
779
+ learnerLocale
780
+ ]);
781
+ const take = typeof assessment?.recordingKey === "string" ? assessment.recordingKey : null;
782
+ const resetKey = (0, react.useMemo)(() => request === null ? "" : JSON.stringify([take, request]), [take, request]);
783
+ const [state, setState] = (0, react.useState)({
784
+ key: resetKey,
785
+ status: "idle"
786
+ });
787
+ const run = (0, react.useRef)(0);
788
+ const controller = (0, react.useRef)(null);
789
+ const current = state.key === resetKey ? state : {
790
+ key: resetKey,
791
+ status: "idle"
792
+ };
793
+ const offered = ai?.pronunciationCoaching !== void 0 && coachingOffered({
794
+ data: {
795
+ type: "read-aloud",
796
+ id,
797
+ title,
798
+ ai: permissions
799
+ },
800
+ renderMode,
801
+ marked: request !== null,
802
+ delivery
803
+ });
804
+ const latest = (0, react.useRef)({
805
+ input,
806
+ ai,
807
+ request,
808
+ resetKey,
809
+ offered,
810
+ current
811
+ });
812
+ latest.current = {
813
+ input,
814
+ ai,
815
+ request,
816
+ resetKey,
817
+ offered,
818
+ current
819
+ };
820
+ (0, react.useEffect)(() => {
821
+ return () => {
822
+ run.current += 1;
823
+ controller.current?.abort();
824
+ controller.current = null;
825
+ };
826
+ }, [resetKey]);
827
+ (0, react.useEffect)(() => {
828
+ if (!offered) {
829
+ run.current += 1;
830
+ controller.current?.abort();
831
+ controller.current = null;
832
+ setState((previous) => previous.status === "loading" ? {
833
+ key: previous.key,
834
+ status: "idle"
835
+ } : previous);
836
+ }
837
+ }, [offered]);
838
+ const ask = (0, react.useCallback)(() => {
839
+ const now = latest.current;
840
+ const port = now.ai?.pronunciationCoaching;
841
+ const request = now.request;
842
+ if (port === void 0 || !now.offered || request === null || now.current.status === "loading" || now.current.status === "shown") return;
843
+ const key = now.resetKey;
844
+ const activityId = request.facts.activityId;
845
+ run.current += 1;
846
+ const mine = run.current;
847
+ controller.current?.abort();
848
+ const abort = new AbortController();
849
+ controller.current = abort;
850
+ setState({
851
+ key,
852
+ status: "loading"
853
+ });
854
+ callPort(() => port(request, { signal: abort.signal })).then((raw) => {
855
+ if (run.current !== mine) return;
856
+ const checked = (0, _intellectif_lk_core.checkAiCoaching)(raw, request);
857
+ if (!checked.ok) {
858
+ warnRefused("pronunciation coaching", activityId, checked.refusal);
859
+ setState({
860
+ key,
861
+ status: "unavailable"
862
+ });
863
+ latest.current.input.onInteraction?.({
864
+ type: "ai-help-refused",
865
+ activityId,
866
+ timestamp: Date.now(),
867
+ payload: {
868
+ feature: "pronunciation-coaching",
869
+ reason: checked.refusal
870
+ }
871
+ });
872
+ return;
873
+ }
874
+ const { coaching } = checked;
875
+ setState({
876
+ key,
877
+ status: "shown",
878
+ coaching
879
+ });
880
+ latest.current.input.onInteraction?.({
881
+ type: "ai-coaching-shown",
882
+ activityId,
883
+ timestamp: Date.now(),
884
+ payload: {
885
+ words: coaching.words.length,
886
+ ...shownPayload(coaching)
887
+ }
888
+ });
889
+ }, () => {
890
+ if (run.current === mine) setState({
891
+ key,
892
+ status: "unavailable"
893
+ });
894
+ });
895
+ }, []);
896
+ return {
897
+ offered,
898
+ status: offered ? current.status : "idle",
899
+ coaching: offered && current.status === "shown" ? current.coaching : null,
900
+ ask
901
+ };
902
+ }
903
+ //#endregion
904
+ Object.defineProperty(exports, "ANONYMOUS_ACTOR", {
905
+ enumerable: true,
906
+ get: function() {
907
+ return ANONYMOUS_ACTOR;
908
+ }
909
+ });
910
+ Object.defineProperty(exports, "SequenceSlotContext", {
911
+ enumerable: true,
912
+ get: function() {
913
+ return SequenceSlotContext;
914
+ }
915
+ });
916
+ Object.defineProperty(exports, "detailIsRight", {
917
+ enumerable: true,
918
+ get: function() {
919
+ return detailIsRight;
920
+ }
921
+ });
922
+ Object.defineProperty(exports, "everyBuiltInTypeHandled", {
923
+ enumerable: true,
924
+ get: function() {
925
+ return everyBuiltInTypeHandled;
926
+ }
927
+ });
928
+ Object.defineProperty(exports, "isDevelopment", {
929
+ enumerable: true,
930
+ get: function() {
931
+ return isDevelopment;
932
+ }
933
+ });
934
+ Object.defineProperty(exports, "legacyCorrect", {
935
+ enumerable: true,
936
+ get: function() {
937
+ return legacyCorrect;
938
+ }
939
+ });
940
+ Object.defineProperty(exports, "mintTake", {
941
+ enumerable: true,
942
+ get: function() {
943
+ return mintTake;
944
+ }
945
+ });
946
+ Object.defineProperty(exports, "objectIdFor", {
947
+ enumerable: true,
948
+ get: function() {
949
+ return objectIdFor;
950
+ }
951
+ });
952
+ Object.defineProperty(exports, "randomSessionId", {
953
+ enumerable: true,
954
+ get: function() {
955
+ return randomSessionId;
956
+ }
957
+ });
958
+ Object.defineProperty(exports, "stampTake", {
959
+ enumerable: true,
960
+ get: function() {
961
+ return stampTake;
962
+ }
963
+ });
964
+ Object.defineProperty(exports, "takeOf", {
965
+ enumerable: true,
966
+ get: function() {
967
+ return takeOf;
968
+ }
969
+ });
970
+ Object.defineProperty(exports, "useAiCoaching", {
971
+ enumerable: true,
972
+ get: function() {
973
+ return useAiCoaching;
974
+ }
975
+ });
976
+ Object.defineProperty(exports, "useAiExplanation", {
977
+ enumerable: true,
978
+ get: function() {
979
+ return useAiExplanation;
980
+ }
981
+ });
982
+ Object.defineProperty(exports, "useAiHints", {
983
+ enumerable: true,
984
+ get: function() {
985
+ return useAiHints;
986
+ }
987
+ });
988
+ Object.defineProperty(exports, "useAiWritingFeedback", {
989
+ enumerable: true,
990
+ get: function() {
991
+ return useAiWritingFeedback;
992
+ }
993
+ });
994
+
995
+ //# sourceMappingURL=useAiHelp-h9yOLFqt.cjs.map