@intellectif/lk-react 12.0.1 → 14.0.0

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 (165) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +17 -6
  3. package/dist/{WrittenResponse-BgcpEM-e.d.ts → WrittenResponse-C0P34En1.d.ts} +1 -1
  4. package/dist/{WrittenResponse-ByzXYEoW.d.cts → WrittenResponse-pB1ik8hg.d.cts} +1 -1
  5. package/dist/chunk-36FTYJWJ.cjs +869 -0
  6. package/dist/chunk-36FTYJWJ.cjs.map +1 -0
  7. package/dist/chunk-47HHC4GD.js +763 -0
  8. package/dist/chunk-47HHC4GD.js.map +1 -0
  9. package/dist/chunk-62AKSD5Y.js +509 -0
  10. package/dist/chunk-62AKSD5Y.js.map +1 -0
  11. package/dist/{chunk-XKGBD3UK.js → chunk-72UGRIMM.js} +6 -5
  12. package/dist/chunk-72UGRIMM.js.map +1 -0
  13. package/dist/{chunk-FX7VMZHQ.cjs → chunk-B2XQLU2E.cjs} +58 -8
  14. package/dist/chunk-B2XQLU2E.cjs.map +1 -0
  15. package/dist/{chunk-ZFWC4KZC.js → chunk-BO6P723E.js} +26 -31
  16. package/dist/chunk-BO6P723E.js.map +1 -0
  17. package/dist/chunk-BRPEB43C.cjs +13 -0
  18. package/dist/chunk-BRPEB43C.cjs.map +1 -0
  19. package/dist/{chunk-6KMEB7TF.cjs → chunk-BVRUUYYR.cjs} +42 -15
  20. package/dist/chunk-BVRUUYYR.cjs.map +1 -0
  21. package/dist/{chunk-AMGK7DDM.cjs → chunk-D4DQFTA7.cjs} +2 -2
  22. package/dist/chunk-D4DQFTA7.cjs.map +1 -0
  23. package/dist/chunk-D57QZILZ.js +863 -0
  24. package/dist/chunk-D57QZILZ.js.map +1 -0
  25. package/dist/chunk-F4TBCRGI.cjs +518 -0
  26. package/dist/chunk-F4TBCRGI.cjs.map +1 -0
  27. package/dist/{chunk-V6M57YMK.js → chunk-I33FOKZ7.js} +227 -30
  28. package/dist/chunk-I33FOKZ7.js.map +1 -0
  29. package/dist/{chunk-GVBEI5R3.cjs → chunk-J2CDPIRC.cjs} +233 -36
  30. package/dist/chunk-J2CDPIRC.cjs.map +1 -0
  31. package/dist/{chunk-KYOCDRUO.cjs → chunk-LB3FEV7Z.cjs} +97 -2
  32. package/dist/chunk-LB3FEV7Z.cjs.map +1 -0
  33. package/dist/{chunk-QXYAOILF.js → chunk-LGCUOLP6.js} +6 -5
  34. package/dist/chunk-LGCUOLP6.js.map +1 -0
  35. package/dist/{chunk-GWD75Q25.js → chunk-LLXCX5KK.js} +6 -5
  36. package/dist/chunk-LLXCX5KK.js.map +1 -0
  37. package/dist/chunk-MCO52PV5.js +520 -0
  38. package/dist/chunk-MCO52PV5.js.map +1 -0
  39. package/dist/{chunk-G6PUWKQC.cjs → chunk-NDQD3ZRY.cjs} +15 -14
  40. package/dist/chunk-NDQD3ZRY.cjs.map +1 -0
  41. package/dist/chunk-OD65OZIW.cjs +159 -0
  42. package/dist/chunk-OD65OZIW.cjs.map +1 -0
  43. package/dist/chunk-RCMYEWBE.js +11 -0
  44. package/dist/chunk-RCMYEWBE.js.map +1 -0
  45. package/dist/{chunk-KSXEBV2H.cjs → chunk-RRH7ZPXC.cjs} +6 -6
  46. package/dist/{chunk-KSXEBV2H.cjs.map → chunk-RRH7ZPXC.cjs.map} +1 -1
  47. package/dist/{chunk-DQNVAXG6.js → chunk-RXS455MR.js} +2 -2
  48. package/dist/chunk-RXS455MR.js.map +1 -0
  49. package/dist/{chunk-LIHKQEIP.cjs → chunk-SE6WWDVW.cjs} +15 -14
  50. package/dist/chunk-SE6WWDVW.cjs.map +1 -0
  51. package/dist/{chunk-5IH3NRXE.js → chunk-SWY6PWXK.js} +4 -4
  52. package/dist/{chunk-5IH3NRXE.js.map → chunk-SWY6PWXK.js.map} +1 -1
  53. package/dist/chunk-TDJEKXEP.js +212 -0
  54. package/dist/chunk-TDJEKXEP.js.map +1 -0
  55. package/dist/{chunk-NK5EVL5C.cjs → chunk-U3APKQ7P.cjs} +15 -14
  56. package/dist/chunk-U3APKQ7P.cjs.map +1 -0
  57. package/dist/chunk-UDCQTOVU.cjs +523 -0
  58. package/dist/chunk-UDCQTOVU.cjs.map +1 -0
  59. package/dist/{chunk-EWTAMY6L.cjs → chunk-USBANZ7K.cjs} +27 -33
  60. package/dist/chunk-USBANZ7K.cjs.map +1 -0
  61. package/dist/chunk-WTS34S5E.cjs +765 -0
  62. package/dist/chunk-WTS34S5E.cjs.map +1 -0
  63. package/dist/{chunk-2Y6V5E7H.js → chunk-XIBOFTOL.js} +57 -7
  64. package/dist/chunk-XIBOFTOL.js.map +1 -0
  65. package/dist/{chunk-ZFSRMGWO.js → chunk-XUEIUEPI.js} +6 -5
  66. package/dist/chunk-XUEIUEPI.js.map +1 -0
  67. package/dist/{chunk-64AJVB6O.cjs → chunk-YEYKJFEC.cjs} +14 -13
  68. package/dist/chunk-YEYKJFEC.cjs.map +1 -0
  69. package/dist/{chunk-5S2YDMEJ.js → chunk-YMBBM5K7.js} +36 -9
  70. package/dist/chunk-YMBBM5K7.js.map +1 -0
  71. package/dist/chunk-YORQQXGO.js +155 -0
  72. package/dist/chunk-YORQQXGO.js.map +1 -0
  73. package/dist/components/ActivityPreview.cjs +15 -9
  74. package/dist/components/ActivityPreview.d.cts +9 -3
  75. package/dist/components/ActivityPreview.d.ts +9 -3
  76. package/dist/components/ActivityPreview.js +14 -8
  77. package/dist/components/ActivitySequence.cjs +16 -10
  78. package/dist/components/ActivitySequence.d.cts +112 -6
  79. package/dist/components/ActivitySequence.d.ts +112 -6
  80. package/dist/components/ActivitySequence.js +15 -9
  81. package/dist/components/Dictation.cjs +19 -0
  82. package/dist/components/Dictation.cjs.map +1 -0
  83. package/dist/components/Dictation.d.cts +17 -0
  84. package/dist/components/Dictation.d.ts +17 -0
  85. package/dist/components/Dictation.js +10 -0
  86. package/dist/components/Dictation.js.map +1 -0
  87. package/dist/components/FillInTheBlanks.cjs +6 -5
  88. package/dist/components/FillInTheBlanks.d.cts +2 -1
  89. package/dist/components/FillInTheBlanks.d.ts +2 -1
  90. package/dist/components/FillInTheBlanks.js +5 -4
  91. package/dist/components/GapSelect.cjs +6 -5
  92. package/dist/components/GapSelect.d.cts +2 -1
  93. package/dist/components/GapSelect.d.ts +2 -1
  94. package/dist/components/GapSelect.js +5 -4
  95. package/dist/components/MultipleChoice.cjs +6 -5
  96. package/dist/components/MultipleChoice.d.cts +2 -1
  97. package/dist/components/MultipleChoice.d.ts +2 -1
  98. package/dist/components/MultipleChoice.js +5 -4
  99. package/dist/components/PronunciationFeedback.cjs +16 -0
  100. package/dist/components/PronunciationFeedback.cjs.map +1 -0
  101. package/dist/components/PronunciationFeedback.d.cts +64 -0
  102. package/dist/components/PronunciationFeedback.d.ts +64 -0
  103. package/dist/components/PronunciationFeedback.js +7 -0
  104. package/dist/components/PronunciationFeedback.js.map +1 -0
  105. package/dist/components/ReadAloud.cjs +21 -0
  106. package/dist/components/ReadAloud.cjs.map +1 -0
  107. package/dist/components/ReadAloud.d.cts +15 -0
  108. package/dist/components/ReadAloud.d.ts +15 -0
  109. package/dist/components/ReadAloud.js +12 -0
  110. package/dist/components/ReadAloud.js.map +1 -0
  111. package/dist/components/StimulusPanel.cjs +4 -4
  112. package/dist/components/StimulusPanel.d.cts +2 -1
  113. package/dist/components/StimulusPanel.d.ts +2 -1
  114. package/dist/components/StimulusPanel.js +3 -3
  115. package/dist/components/WrittenResponse.cjs +6 -5
  116. package/dist/components/WrittenResponse.d.cts +4 -3
  117. package/dist/components/WrittenResponse.d.ts +4 -3
  118. package/dist/components/WrittenResponse.js +5 -4
  119. package/dist/hooks/useSpeechRecorder.cjs +17 -0
  120. package/dist/hooks/useSpeechRecorder.cjs.map +1 -0
  121. package/dist/hooks/useSpeechRecorder.d.cts +127 -0
  122. package/dist/hooks/useSpeechRecorder.d.ts +127 -0
  123. package/dist/hooks/useSpeechRecorder.js +4 -0
  124. package/dist/hooks/useSpeechRecorder.js.map +1 -0
  125. package/dist/i18n/LkIntlProvider.cjs +7 -7
  126. package/dist/i18n/LkIntlProvider.d.cts +3 -2
  127. package/dist/i18n/LkIntlProvider.d.ts +3 -2
  128. package/dist/i18n/LkIntlProvider.js +1 -1
  129. package/dist/index.cjs +59 -33
  130. package/dist/index.cjs.map +1 -1
  131. package/dist/index.d.cts +7 -2
  132. package/dist/index.d.ts +7 -2
  133. package/dist/index.js +17 -11
  134. package/dist/index.js.map +1 -1
  135. package/dist/machine-CuwKqWXC.d.cts +26 -0
  136. package/dist/machine-CuwKqWXC.d.ts +26 -0
  137. package/dist/{strings-CN7n-BlE.d.ts → strings--ADnHcaA.d.cts} +261 -8
  138. package/dist/{strings-CN7n-BlE.d.cts → strings-CtdSf2St.d.ts} +261 -8
  139. package/dist/theme/ThemeProvider.cjs +6 -6
  140. package/dist/theme/ThemeProvider.d.cts +4 -4
  141. package/dist/theme/ThemeProvider.d.ts +4 -4
  142. package/dist/theme/ThemeProvider.js +1 -1
  143. package/dist/theme/skin.css +1050 -3
  144. package/package.json +43 -3
  145. package/dist/chunk-2Y6V5E7H.js.map +0 -1
  146. package/dist/chunk-5S2YDMEJ.js.map +0 -1
  147. package/dist/chunk-64AJVB6O.cjs.map +0 -1
  148. package/dist/chunk-6KMEB7TF.cjs.map +0 -1
  149. package/dist/chunk-AMGK7DDM.cjs.map +0 -1
  150. package/dist/chunk-CK7Z275S.js +0 -117
  151. package/dist/chunk-CK7Z275S.js.map +0 -1
  152. package/dist/chunk-DQNVAXG6.js.map +0 -1
  153. package/dist/chunk-EWTAMY6L.cjs.map +0 -1
  154. package/dist/chunk-FX7VMZHQ.cjs.map +0 -1
  155. package/dist/chunk-G6PUWKQC.cjs.map +0 -1
  156. package/dist/chunk-GVBEI5R3.cjs.map +0 -1
  157. package/dist/chunk-GWD75Q25.js.map +0 -1
  158. package/dist/chunk-KYOCDRUO.cjs.map +0 -1
  159. package/dist/chunk-LIHKQEIP.cjs.map +0 -1
  160. package/dist/chunk-NK5EVL5C.cjs.map +0 -1
  161. package/dist/chunk-QXYAOILF.js.map +0 -1
  162. package/dist/chunk-V6M57YMK.js.map +0 -1
  163. package/dist/chunk-XKGBD3UK.js.map +0 -1
  164. package/dist/chunk-ZFSRMGWO.js.map +0 -1
  165. package/dist/chunk-ZFWC4KZC.js.map +0 -1
@@ -1,13 +1,29 @@
1
- import { SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
1
+ import { SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
2
2
  import { ComponentType } from 'react';
3
- import { A as ActivityProps, d as RenderableActivity, R as RenderMode, S as SequenceMediaBudget, a as LkStringsOverride, H as HtmlSanitizer } from '../strings-CN7n-BlE.cjs';
4
- import { a as WrittenResponseSubmission } from '../WrittenResponse-ByzXYEoW.cjs';
3
+ import { A as ActivityProps, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../strings--ADnHcaA.cjs';
4
+ import { a as WrittenResponseSubmission } from '../WrittenResponse-pB1ik8hg.cjs';
5
+ import '../machine-CuwKqWXC.cjs';
5
6
 
6
7
  /**
7
8
  * What one finished slot in a sequence produced. Two kinds, because two kinds
8
9
  * of activity exist: those the SDK scores at submit time, and those a grader
9
10
  * scores later. Collapsing them would mean inventing a score for ungraded
10
11
  * work — the exact defect the deferred outcome exists to prevent.
12
+ *
13
+ * **A read-aloud hand-in adds no arm here, deliberately.** The obvious home for
14
+ * a handed-in take is `submitted`, and it is the wrong one: that arm's payload
15
+ * is typed `WrittenResponseSubmission`, this union is published from both the
16
+ * barrel and the `components/ActivitySequence` subpath, and a consumer narrows
17
+ * on `kind === 'submitted'` and reads `.text`. Widening the payload to a union
18
+ * would break every one of those reads — a breaking change to a published
19
+ * discriminated union, bought for a type that `responded` already describes: a
20
+ * read-aloud hand-in IS a raw `LearnerResponse` with no grade, which is exactly
21
+ * what `responded` carries.
22
+ *
23
+ * What a read-aloud does add is `unsubmitted`, for the one thing no existing
24
+ * arm can say honestly: a take that never reached storage. Any response would
25
+ * be a lie about it — a `recording` of `null` is the blank a learner chooses,
26
+ * and grades as 0.
11
27
  */
12
28
  type SequenceItemOutcome = {
13
29
  kind: 'scored';
@@ -17,6 +33,14 @@ type SequenceItemOutcome = {
17
33
  slotId: string;
18
34
  activityId: string;
19
35
  result: ActivityResult;
36
+ /**
37
+ * The answer this score grades, for a slot whose grade arrives after its
38
+ * answer was handed in and whose learner may hand in another: a
39
+ * `practice` read-aloud, whose `response.recording` names the take the
40
+ * score belongs to. Absent for every other slot, whose score and answer
41
+ * arrive together.
42
+ */
43
+ response?: LearnerResponse;
20
44
  } | {
21
45
  kind: 'submitted';
22
46
  index: number;
@@ -44,8 +68,28 @@ type SequenceItemOutcome = {
44
68
  * The raw answer, with no grade of any kind. This is what an `exam` slot
45
69
  * produces: the client is forbidden to score, so a response is all there
46
70
  * is until the server grades it.
71
+ *
72
+ * A read-aloud `recording` of `null` here is always a blank the learner
73
+ * chose to hand in, never a take that failed to upload — that is
74
+ * `unsubmitted`.
47
75
  */
48
76
  response: LearnerResponse;
77
+ } | {
78
+ /**
79
+ * A question the learner tried to answer and could not hand in, and then
80
+ * left: a `practice` read-aloud whose take never reached your storage. It
81
+ * carries no response, because there is none.
82
+ *
83
+ * Deliberately not `responded` with a `recording` of `null`: that is the
84
+ * blank a learner chooses, and a grader marks it 0 with every word
85
+ * omitted — which would turn a storage outage into a zero. Grade nothing
86
+ * for this slot; the learner can still return to it, and a take stored
87
+ * then reaches you through `onSubmit`.
88
+ */
89
+ kind: 'unsubmitted';
90
+ index: number;
91
+ slotId: string;
92
+ activityId: string;
49
93
  };
50
94
  /**
51
95
  * A component that can render one activity inside a sequence. Register one per
@@ -69,6 +113,13 @@ interface ActivitySequenceProps {
69
113
  * Renderers for activity types beyond the built-ins, keyed by `data.type`.
70
114
  * A key matching a built-in overrides it, so a consumer can replace the
71
115
  * bundled renderer without forking the sequencer.
116
+ *
117
+ * A registered renderer is an `ActivityRenderer`, which is
118
+ * `ComponentType<ActivityProps>` — so it receives the shared prop contract
119
+ * and nothing beyond it. `shuffleSeed`, `recordingBinding` and `assessment`
120
+ * are all outside that contract and none of them reaches an override: a
121
+ * replacement for `read-aloud` has to be given its own binding by whoever
122
+ * wrote it.
72
123
  */
73
124
  renderers?: Readonly<Record<string, ActivityRenderer>>;
74
125
  /**
@@ -105,12 +156,44 @@ interface ActivitySequenceProps {
105
156
  * use `onFinished` for mixed sets — it is the general completion signal and
106
157
  * reports both kinds of outcome. It also carries `slotId` per item, which
107
158
  * this callback's bare array cannot.
159
+ *
160
+ * It fires straight after `onFinished`, with the same results, or never: a
161
+ * set `onFinished` reported with an ungraded slot is not reported here later,
162
+ * when a re-recorded take is graded.
108
163
  */
109
164
  onComplete?: (results: ActivityResult[]) => void;
110
165
  /**
111
166
  * Called once every activity has been completed, whether it was scored at
112
167
  * submit time or submitted for later grading. Use this for any set that
113
168
  * mixes graded and deferred-graded activities.
169
+ *
170
+ * **Once per set**, and that matters for a `practice` read-aloud, whose grade
171
+ * arrives after the submit that completed the slot. When the last slot is
172
+ * filled while a read-aloud's take is still being stored or assessed, this
173
+ * waits for it and reports the set then — with the grade in place, or with
174
+ * the slot's raw `responded` outcome when the take came back with no grade.
175
+ * A take that never settles is a question still being answered, so the set
176
+ * is not reported while it runs.
177
+ *
178
+ * **A failure the learner can still retry is in flight too.** While a take
179
+ * that failed to upload, or whose assessment failed, is offered "Try again"
180
+ * on the question the learner is looking at, the set is not reported: the
181
+ * retry may yet store and grade it. It completes once the learner moves to
182
+ * another question — as the last take the slot stored, or as `unsubmitted`
183
+ * when it never stored one, which is never a blank.
184
+ *
185
+ * **A score and a response always describe the same take.** A read-aloud
186
+ * recorded again replaces the earlier take's grade with the new take's
187
+ * `responded`, and a result that arrives for a take the learner has since
188
+ * replaced, or for a paper no longer on screen, is not recorded at all.
189
+ *
190
+ * `onComplete` fires in the same report or not at all, so the two never
191
+ * describe one set differently. What arrives after the set was reported is
192
+ * not reported here again, because a consumer who persists on this callback
193
+ * must not write one attempt twice: a later take reaches you through
194
+ * `onSubmit`, and its grade through `onActivityComplete`, the per-item persist
195
+ * hook keyed by `slotId` — which only ever grades the answer `onSubmit` last
196
+ * reported for that slot.
114
197
  */
115
198
  onFinished?: (items: SequenceItemOutcome[]) => void;
116
199
  /** Forwarded to each activity. */
@@ -127,6 +210,27 @@ interface ActivitySequenceProps {
127
210
  * {@link SequenceMediaBudget}.
128
211
  */
129
212
  mediaBudget?: SequenceMediaBudget;
213
+ /**
214
+ * Where every read-aloud take in this sequence is stored, and how a
215
+ * judgement comes back. Required by any `read-aloud` slot outside `review`:
216
+ * the component refuses to render a recorder whose take is stored nowhere.
217
+ *
218
+ * Named `recordingBinding` rather than `recording` because both
219
+ * `ReadAloudData.recording` (the bounds an item declares) and
220
+ * `ReadAloudLearnerResponse.recording` (the take a learner handed in) already
221
+ * exist — the plain name would read as one of those. Same name at both
222
+ * levels, different types, as `mediaBudget` has.
223
+ */
224
+ recordingBinding?: SequenceRecordingBinding;
225
+ /**
226
+ * Speech assessments keyed by `slotId`, forwarded to the matching read-aloud
227
+ * slot so `review` can show the per-word marks behind a stored grade.
228
+ *
229
+ * Read LIVE, like `outcomes` and unlike `responses`: an assessment is fetched
230
+ * beside the attempt it explains and lands after the first paint, and a
231
+ * mount-only read would show the grade with no marks under it for ever.
232
+ */
233
+ assessments?: Readonly<Record<string, SpeechAssessment>>;
130
234
  /** Overrides the SDK's chrome text for this sequence. See {@link LkIntlProvider}. */
131
235
  strings?: LkStringsOverride;
132
236
  /**
@@ -204,13 +308,15 @@ interface ActivitySequenceProps {
204
308
  * a different one re-declares the language of every SDK string in this
205
309
  * subtree without changing the words.
206
310
  *
207
- * It is NOT `data.locale`, which labels xAPI statements only. Authored
208
- * content in another language belongs on `stimulus.locale`, which
311
+ * It is NOT `data.locale`, which labels xAPI statements and, on a
312
+ * dictation, places the dictation's own words: `<Dictation>` puts it, and
313
+ * the direction it names, on its title, hints, marks and solution. Other
314
+ * authored content in another language belongs on `stimulus.locale`, which
209
315
  * `<StimulusPanel>` puts on the passage alone.
210
316
  */
211
317
  locale?: string;
212
318
  disabled?: boolean;
213
319
  }
214
- declare function ActivitySequence({ activities, renderers, onActivityComplete, onComplete, onFinished, onSubmit, onInteraction, renderMode, shuffle, shuffleSeed, defaultIndex, onIndexChange, responses, submittedSlotIds, outcomes, sanitizeHtml, theme, locale, disabled, mediaBudget, strings, }: ActivitySequenceProps): React.JSX.Element;
320
+ declare function ActivitySequence({ activities, renderers, onActivityComplete, onComplete, onFinished, onSubmit, onInteraction, renderMode, shuffle, shuffleSeed, defaultIndex, onIndexChange, responses, submittedSlotIds, outcomes, sanitizeHtml, theme, locale, disabled, mediaBudget, recordingBinding, assessments, strings, }: ActivitySequenceProps): React.JSX.Element;
215
321
 
216
322
  export { type ActivityRenderer, ActivitySequence, type ActivitySequenceProps, type SequenceItemOutcome };
@@ -1,13 +1,29 @@
1
- import { SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
1
+ import { SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
2
2
  import { ComponentType } from 'react';
3
- import { A as ActivityProps, d as RenderableActivity, R as RenderMode, S as SequenceMediaBudget, a as LkStringsOverride, H as HtmlSanitizer } from '../strings-CN7n-BlE.js';
4
- import { a as WrittenResponseSubmission } from '../WrittenResponse-BgcpEM-e.js';
3
+ import { A as ActivityProps, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../strings-CtdSf2St.js';
4
+ import { a as WrittenResponseSubmission } from '../WrittenResponse-C0P34En1.js';
5
+ import '../machine-CuwKqWXC.js';
5
6
 
6
7
  /**
7
8
  * What one finished slot in a sequence produced. Two kinds, because two kinds
8
9
  * of activity exist: those the SDK scores at submit time, and those a grader
9
10
  * scores later. Collapsing them would mean inventing a score for ungraded
10
11
  * work — the exact defect the deferred outcome exists to prevent.
12
+ *
13
+ * **A read-aloud hand-in adds no arm here, deliberately.** The obvious home for
14
+ * a handed-in take is `submitted`, and it is the wrong one: that arm's payload
15
+ * is typed `WrittenResponseSubmission`, this union is published from both the
16
+ * barrel and the `components/ActivitySequence` subpath, and a consumer narrows
17
+ * on `kind === 'submitted'` and reads `.text`. Widening the payload to a union
18
+ * would break every one of those reads — a breaking change to a published
19
+ * discriminated union, bought for a type that `responded` already describes: a
20
+ * read-aloud hand-in IS a raw `LearnerResponse` with no grade, which is exactly
21
+ * what `responded` carries.
22
+ *
23
+ * What a read-aloud does add is `unsubmitted`, for the one thing no existing
24
+ * arm can say honestly: a take that never reached storage. Any response would
25
+ * be a lie about it — a `recording` of `null` is the blank a learner chooses,
26
+ * and grades as 0.
11
27
  */
12
28
  type SequenceItemOutcome = {
13
29
  kind: 'scored';
@@ -17,6 +33,14 @@ type SequenceItemOutcome = {
17
33
  slotId: string;
18
34
  activityId: string;
19
35
  result: ActivityResult;
36
+ /**
37
+ * The answer this score grades, for a slot whose grade arrives after its
38
+ * answer was handed in and whose learner may hand in another: a
39
+ * `practice` read-aloud, whose `response.recording` names the take the
40
+ * score belongs to. Absent for every other slot, whose score and answer
41
+ * arrive together.
42
+ */
43
+ response?: LearnerResponse;
20
44
  } | {
21
45
  kind: 'submitted';
22
46
  index: number;
@@ -44,8 +68,28 @@ type SequenceItemOutcome = {
44
68
  * The raw answer, with no grade of any kind. This is what an `exam` slot
45
69
  * produces: the client is forbidden to score, so a response is all there
46
70
  * is until the server grades it.
71
+ *
72
+ * A read-aloud `recording` of `null` here is always a blank the learner
73
+ * chose to hand in, never a take that failed to upload — that is
74
+ * `unsubmitted`.
47
75
  */
48
76
  response: LearnerResponse;
77
+ } | {
78
+ /**
79
+ * A question the learner tried to answer and could not hand in, and then
80
+ * left: a `practice` read-aloud whose take never reached your storage. It
81
+ * carries no response, because there is none.
82
+ *
83
+ * Deliberately not `responded` with a `recording` of `null`: that is the
84
+ * blank a learner chooses, and a grader marks it 0 with every word
85
+ * omitted — which would turn a storage outage into a zero. Grade nothing
86
+ * for this slot; the learner can still return to it, and a take stored
87
+ * then reaches you through `onSubmit`.
88
+ */
89
+ kind: 'unsubmitted';
90
+ index: number;
91
+ slotId: string;
92
+ activityId: string;
49
93
  };
50
94
  /**
51
95
  * A component that can render one activity inside a sequence. Register one per
@@ -69,6 +113,13 @@ interface ActivitySequenceProps {
69
113
  * Renderers for activity types beyond the built-ins, keyed by `data.type`.
70
114
  * A key matching a built-in overrides it, so a consumer can replace the
71
115
  * bundled renderer without forking the sequencer.
116
+ *
117
+ * A registered renderer is an `ActivityRenderer`, which is
118
+ * `ComponentType<ActivityProps>` — so it receives the shared prop contract
119
+ * and nothing beyond it. `shuffleSeed`, `recordingBinding` and `assessment`
120
+ * are all outside that contract and none of them reaches an override: a
121
+ * replacement for `read-aloud` has to be given its own binding by whoever
122
+ * wrote it.
72
123
  */
73
124
  renderers?: Readonly<Record<string, ActivityRenderer>>;
74
125
  /**
@@ -105,12 +156,44 @@ interface ActivitySequenceProps {
105
156
  * use `onFinished` for mixed sets — it is the general completion signal and
106
157
  * reports both kinds of outcome. It also carries `slotId` per item, which
107
158
  * this callback's bare array cannot.
159
+ *
160
+ * It fires straight after `onFinished`, with the same results, or never: a
161
+ * set `onFinished` reported with an ungraded slot is not reported here later,
162
+ * when a re-recorded take is graded.
108
163
  */
109
164
  onComplete?: (results: ActivityResult[]) => void;
110
165
  /**
111
166
  * Called once every activity has been completed, whether it was scored at
112
167
  * submit time or submitted for later grading. Use this for any set that
113
168
  * mixes graded and deferred-graded activities.
169
+ *
170
+ * **Once per set**, and that matters for a `practice` read-aloud, whose grade
171
+ * arrives after the submit that completed the slot. When the last slot is
172
+ * filled while a read-aloud's take is still being stored or assessed, this
173
+ * waits for it and reports the set then — with the grade in place, or with
174
+ * the slot's raw `responded` outcome when the take came back with no grade.
175
+ * A take that never settles is a question still being answered, so the set
176
+ * is not reported while it runs.
177
+ *
178
+ * **A failure the learner can still retry is in flight too.** While a take
179
+ * that failed to upload, or whose assessment failed, is offered "Try again"
180
+ * on the question the learner is looking at, the set is not reported: the
181
+ * retry may yet store and grade it. It completes once the learner moves to
182
+ * another question — as the last take the slot stored, or as `unsubmitted`
183
+ * when it never stored one, which is never a blank.
184
+ *
185
+ * **A score and a response always describe the same take.** A read-aloud
186
+ * recorded again replaces the earlier take's grade with the new take's
187
+ * `responded`, and a result that arrives for a take the learner has since
188
+ * replaced, or for a paper no longer on screen, is not recorded at all.
189
+ *
190
+ * `onComplete` fires in the same report or not at all, so the two never
191
+ * describe one set differently. What arrives after the set was reported is
192
+ * not reported here again, because a consumer who persists on this callback
193
+ * must not write one attempt twice: a later take reaches you through
194
+ * `onSubmit`, and its grade through `onActivityComplete`, the per-item persist
195
+ * hook keyed by `slotId` — which only ever grades the answer `onSubmit` last
196
+ * reported for that slot.
114
197
  */
115
198
  onFinished?: (items: SequenceItemOutcome[]) => void;
116
199
  /** Forwarded to each activity. */
@@ -127,6 +210,27 @@ interface ActivitySequenceProps {
127
210
  * {@link SequenceMediaBudget}.
128
211
  */
129
212
  mediaBudget?: SequenceMediaBudget;
213
+ /**
214
+ * Where every read-aloud take in this sequence is stored, and how a
215
+ * judgement comes back. Required by any `read-aloud` slot outside `review`:
216
+ * the component refuses to render a recorder whose take is stored nowhere.
217
+ *
218
+ * Named `recordingBinding` rather than `recording` because both
219
+ * `ReadAloudData.recording` (the bounds an item declares) and
220
+ * `ReadAloudLearnerResponse.recording` (the take a learner handed in) already
221
+ * exist — the plain name would read as one of those. Same name at both
222
+ * levels, different types, as `mediaBudget` has.
223
+ */
224
+ recordingBinding?: SequenceRecordingBinding;
225
+ /**
226
+ * Speech assessments keyed by `slotId`, forwarded to the matching read-aloud
227
+ * slot so `review` can show the per-word marks behind a stored grade.
228
+ *
229
+ * Read LIVE, like `outcomes` and unlike `responses`: an assessment is fetched
230
+ * beside the attempt it explains and lands after the first paint, and a
231
+ * mount-only read would show the grade with no marks under it for ever.
232
+ */
233
+ assessments?: Readonly<Record<string, SpeechAssessment>>;
130
234
  /** Overrides the SDK's chrome text for this sequence. See {@link LkIntlProvider}. */
131
235
  strings?: LkStringsOverride;
132
236
  /**
@@ -204,13 +308,15 @@ interface ActivitySequenceProps {
204
308
  * a different one re-declares the language of every SDK string in this
205
309
  * subtree without changing the words.
206
310
  *
207
- * It is NOT `data.locale`, which labels xAPI statements only. Authored
208
- * content in another language belongs on `stimulus.locale`, which
311
+ * It is NOT `data.locale`, which labels xAPI statements and, on a
312
+ * dictation, places the dictation's own words: `<Dictation>` puts it, and
313
+ * the direction it names, on its title, hints, marks and solution. Other
314
+ * authored content in another language belongs on `stimulus.locale`, which
209
315
  * `<StimulusPanel>` puts on the passage alone.
210
316
  */
211
317
  locale?: string;
212
318
  disabled?: boolean;
213
319
  }
214
- declare function ActivitySequence({ activities, renderers, onActivityComplete, onComplete, onFinished, onSubmit, onInteraction, renderMode, shuffle, shuffleSeed, defaultIndex, onIndexChange, responses, submittedSlotIds, outcomes, sanitizeHtml, theme, locale, disabled, mediaBudget, strings, }: ActivitySequenceProps): React.JSX.Element;
320
+ declare function ActivitySequence({ activities, renderers, onActivityComplete, onComplete, onFinished, onSubmit, onInteraction, renderMode, shuffle, shuffleSeed, defaultIndex, onIndexChange, responses, submittedSlotIds, outcomes, sanitizeHtml, theme, locale, disabled, mediaBudget, recordingBinding, assessments, strings, }: ActivitySequenceProps): React.JSX.Element;
215
321
 
216
322
  export { type ActivityRenderer, ActivitySequence, type ActivitySequenceProps, type SequenceItemOutcome };
@@ -1,13 +1,19 @@
1
1
  'use client';
2
- export { ActivitySequence } from '../chunk-V6M57YMK.js';
3
- import '../chunk-QXYAOILF.js';
4
- import '../chunk-XKGBD3UK.js';
5
- import '../chunk-ZFSRMGWO.js';
6
- import '../chunk-GWD75Q25.js';
7
- import '../chunk-ZFWC4KZC.js';
2
+ export { ActivitySequence } from '../chunk-I33FOKZ7.js';
3
+ import '../chunk-SWY6PWXK.js';
4
+ import '../chunk-LLXCX5KK.js';
5
+ import '../chunk-LGCUOLP6.js';
6
+ import '../chunk-72UGRIMM.js';
7
+ import '../chunk-XUEIUEPI.js';
8
+ import '../chunk-47HHC4GD.js';
9
+ import '../chunk-D57QZILZ.js';
10
+ import '../chunk-62AKSD5Y.js';
11
+ import '../chunk-MCO52PV5.js';
12
+ import '../chunk-YORQQXGO.js';
13
+ import '../chunk-RCMYEWBE.js';
14
+ import '../chunk-BO6P723E.js';
15
+ import '../chunk-XIBOFTOL.js';
8
16
  import '../chunk-6N43WDVG.js';
9
- import '../chunk-5IH3NRXE.js';
10
- import '../chunk-2Y6V5E7H.js';
11
- import '../chunk-CK7Z275S.js';
17
+ import '../chunk-TDJEKXEP.js';
12
18
  //# sourceMappingURL=ActivitySequence.js.map
13
19
  //# sourceMappingURL=ActivitySequence.js.map
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var chunkWTS34S5E_cjs = require('../chunk-WTS34S5E.cjs');
5
+ require('../chunk-OD65OZIW.cjs');
6
+ require('../chunk-BRPEB43C.cjs');
7
+ require('../chunk-USBANZ7K.cjs');
8
+ require('../chunk-B2XQLU2E.cjs');
9
+ require('../chunk-XOR4MPEN.cjs');
10
+ require('../chunk-LB3FEV7Z.cjs');
11
+
12
+
13
+
14
+ Object.defineProperty(exports, "Dictation", {
15
+ enumerable: true,
16
+ get: function () { return chunkWTS34S5E_cjs.Dictation; }
17
+ });
18
+ //# sourceMappingURL=Dictation.cjs.map
19
+ //# sourceMappingURL=Dictation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Dictation.cjs"}
@@ -0,0 +1,17 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { DictationData } from '@intellectif/lk-core';
3
+ import { A as ActivityProps } from '../strings--ADnHcaA.cjs';
4
+ import '../machine-CuwKqWXC.cjs';
5
+
6
+ interface DictationProps extends ActivityProps<DictationData> {
7
+ }
8
+
9
+ /**
10
+ * Public Dictation activity: the core wrapped in `ActivityErrorBoundary` so a
11
+ * render failure (including the dev schema-validation throw and the
12
+ * redacted-in-`practice` guard) degrades to an accessible fallback instead of
13
+ * crashing the host.
14
+ */
15
+ declare function Dictation(props: DictationProps): react_jsx_runtime.JSX.Element;
16
+
17
+ export { Dictation, type DictationProps };
@@ -0,0 +1,17 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { DictationData } from '@intellectif/lk-core';
3
+ import { A as ActivityProps } from '../strings-CtdSf2St.js';
4
+ import '../machine-CuwKqWXC.js';
5
+
6
+ interface DictationProps extends ActivityProps<DictationData> {
7
+ }
8
+
9
+ /**
10
+ * Public Dictation activity: the core wrapped in `ActivityErrorBoundary` so a
11
+ * render failure (including the dev schema-validation throw and the
12
+ * redacted-in-`practice` guard) degrades to an accessible fallback instead of
13
+ * crashing the host.
14
+ */
15
+ declare function Dictation(props: DictationProps): react_jsx_runtime.JSX.Element;
16
+
17
+ export { Dictation, type DictationProps };
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+ export { Dictation } from '../chunk-47HHC4GD.js';
3
+ import '../chunk-YORQQXGO.js';
4
+ import '../chunk-RCMYEWBE.js';
5
+ import '../chunk-BO6P723E.js';
6
+ import '../chunk-XIBOFTOL.js';
7
+ import '../chunk-6N43WDVG.js';
8
+ import '../chunk-TDJEKXEP.js';
9
+ //# sourceMappingURL=Dictation.js.map
10
+ //# sourceMappingURL=Dictation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Dictation.js"}
@@ -1,17 +1,18 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkLIHKQEIP_cjs = require('../chunk-LIHKQEIP.cjs');
5
- require('../chunk-EWTAMY6L.cjs');
4
+ var chunkSE6WWDVW_cjs = require('../chunk-SE6WWDVW.cjs');
5
+ require('../chunk-BRPEB43C.cjs');
6
+ require('../chunk-USBANZ7K.cjs');
7
+ require('../chunk-B2XQLU2E.cjs');
6
8
  require('../chunk-XOR4MPEN.cjs');
7
- require('../chunk-FX7VMZHQ.cjs');
8
- require('../chunk-KYOCDRUO.cjs');
9
+ require('../chunk-LB3FEV7Z.cjs');
9
10
 
10
11
 
11
12
 
12
13
  Object.defineProperty(exports, "FillInTheBlanks", {
13
14
  enumerable: true,
14
- get: function () { return chunkLIHKQEIP_cjs.FillInTheBlanks; }
15
+ get: function () { return chunkSE6WWDVW_cjs.FillInTheBlanks; }
15
16
  });
16
17
  //# sourceMappingURL=FillInTheBlanks.cjs.map
17
18
  //# sourceMappingURL=FillInTheBlanks.cjs.map
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { FillInTheBlanksData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../strings-CN7n-BlE.cjs';
3
+ import { A as ActivityProps } from '../strings--ADnHcaA.cjs';
4
+ import '../machine-CuwKqWXC.cjs';
4
5
 
5
6
  interface FillInTheBlanksProps extends ActivityProps<FillInTheBlanksData> {
6
7
  /**
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { FillInTheBlanksData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../strings-CN7n-BlE.js';
3
+ import { A as ActivityProps } from '../strings-CtdSf2St.js';
4
+ import '../machine-CuwKqWXC.js';
4
5
 
5
6
  interface FillInTheBlanksProps extends ActivityProps<FillInTheBlanksData> {
6
7
  /**
@@ -1,8 +1,9 @@
1
1
  'use client';
2
- export { FillInTheBlanks } from '../chunk-XKGBD3UK.js';
3
- import '../chunk-ZFWC4KZC.js';
2
+ export { FillInTheBlanks } from '../chunk-72UGRIMM.js';
3
+ import '../chunk-RCMYEWBE.js';
4
+ import '../chunk-BO6P723E.js';
5
+ import '../chunk-XIBOFTOL.js';
4
6
  import '../chunk-6N43WDVG.js';
5
- import '../chunk-2Y6V5E7H.js';
6
- import '../chunk-CK7Z275S.js';
7
+ import '../chunk-TDJEKXEP.js';
7
8
  //# sourceMappingURL=FillInTheBlanks.js.map
8
9
  //# sourceMappingURL=FillInTheBlanks.js.map
@@ -1,17 +1,18 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkNK5EVL5C_cjs = require('../chunk-NK5EVL5C.cjs');
5
- require('../chunk-EWTAMY6L.cjs');
4
+ var chunkU3APKQ7P_cjs = require('../chunk-U3APKQ7P.cjs');
5
+ require('../chunk-BRPEB43C.cjs');
6
+ require('../chunk-USBANZ7K.cjs');
7
+ require('../chunk-B2XQLU2E.cjs');
6
8
  require('../chunk-XOR4MPEN.cjs');
7
- require('../chunk-FX7VMZHQ.cjs');
8
- require('../chunk-KYOCDRUO.cjs');
9
+ require('../chunk-LB3FEV7Z.cjs');
9
10
 
10
11
 
11
12
 
12
13
  Object.defineProperty(exports, "GapSelect", {
13
14
  enumerable: true,
14
- get: function () { return chunkNK5EVL5C_cjs.GapSelect; }
15
+ get: function () { return chunkU3APKQ7P_cjs.GapSelect; }
15
16
  });
16
17
  //# sourceMappingURL=GapSelect.cjs.map
17
18
  //# sourceMappingURL=GapSelect.cjs.map
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { GapSelectData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../strings-CN7n-BlE.cjs';
3
+ import { A as ActivityProps } from '../strings--ADnHcaA.cjs';
4
+ import '../machine-CuwKqWXC.cjs';
4
5
 
5
6
  interface GapSelectProps extends ActivityProps<GapSelectData> {
6
7
  /**
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { GapSelectData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../strings-CN7n-BlE.js';
3
+ import { A as ActivityProps } from '../strings-CtdSf2St.js';
4
+ import '../machine-CuwKqWXC.js';
4
5
 
5
6
  interface GapSelectProps extends ActivityProps<GapSelectData> {
6
7
  /**
@@ -1,8 +1,9 @@
1
1
  'use client';
2
- export { GapSelect } from '../chunk-ZFSRMGWO.js';
3
- import '../chunk-ZFWC4KZC.js';
2
+ export { GapSelect } from '../chunk-XUEIUEPI.js';
3
+ import '../chunk-RCMYEWBE.js';
4
+ import '../chunk-BO6P723E.js';
5
+ import '../chunk-XIBOFTOL.js';
4
6
  import '../chunk-6N43WDVG.js';
5
- import '../chunk-2Y6V5E7H.js';
6
- import '../chunk-CK7Z275S.js';
7
+ import '../chunk-TDJEKXEP.js';
7
8
  //# sourceMappingURL=GapSelect.js.map
8
9
  //# sourceMappingURL=GapSelect.js.map
@@ -1,17 +1,18 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkG6PUWKQC_cjs = require('../chunk-G6PUWKQC.cjs');
5
- require('../chunk-EWTAMY6L.cjs');
4
+ var chunkNDQD3ZRY_cjs = require('../chunk-NDQD3ZRY.cjs');
5
+ require('../chunk-BRPEB43C.cjs');
6
+ require('../chunk-USBANZ7K.cjs');
7
+ require('../chunk-B2XQLU2E.cjs');
6
8
  require('../chunk-XOR4MPEN.cjs');
7
- require('../chunk-FX7VMZHQ.cjs');
8
- require('../chunk-KYOCDRUO.cjs');
9
+ require('../chunk-LB3FEV7Z.cjs');
9
10
 
10
11
 
11
12
 
12
13
  Object.defineProperty(exports, "MultipleChoice", {
13
14
  enumerable: true,
14
- get: function () { return chunkG6PUWKQC_cjs.MultipleChoice; }
15
+ get: function () { return chunkNDQD3ZRY_cjs.MultipleChoice; }
15
16
  });
16
17
  //# sourceMappingURL=MultipleChoice.cjs.map
17
18
  //# sourceMappingURL=MultipleChoice.cjs.map
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { MultipleChoiceData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../strings-CN7n-BlE.cjs';
3
+ import { A as ActivityProps } from '../strings--ADnHcaA.cjs';
4
+ import '../machine-CuwKqWXC.cjs';
4
5
 
5
6
  interface MultipleChoiceProps extends ActivityProps<MultipleChoiceData> {
6
7
  /**
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { MultipleChoiceData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../strings-CN7n-BlE.js';
3
+ import { A as ActivityProps } from '../strings-CtdSf2St.js';
4
+ import '../machine-CuwKqWXC.js';
4
5
 
5
6
  interface MultipleChoiceProps extends ActivityProps<MultipleChoiceData> {
6
7
  /**
@@ -1,8 +1,9 @@
1
1
  'use client';
2
- export { MultipleChoice } from '../chunk-QXYAOILF.js';
3
- import '../chunk-ZFWC4KZC.js';
2
+ export { MultipleChoice } from '../chunk-LGCUOLP6.js';
3
+ import '../chunk-RCMYEWBE.js';
4
+ import '../chunk-BO6P723E.js';
5
+ import '../chunk-XIBOFTOL.js';
4
6
  import '../chunk-6N43WDVG.js';
5
- import '../chunk-2Y6V5E7H.js';
6
- import '../chunk-CK7Z275S.js';
7
+ import '../chunk-TDJEKXEP.js';
7
8
  //# sourceMappingURL=MultipleChoice.js.map
8
9
  //# sourceMappingURL=MultipleChoice.js.map