@intellectif/lk-react 15.0.0 → 16.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 (129) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +2 -2
  3. package/dist/{WrittenResponse-BPbhERgk.d.cts → WrittenResponse-C2zw-1jK.d.cts} +1 -1
  4. package/dist/{WrittenResponse-ZAxLR_AU.d.ts → WrittenResponse-CTiNpSCC.d.ts} +1 -1
  5. package/dist/{chunk-ZH5WT2IE.cjs → chunk-2WM2KSO7.cjs} +25 -25
  6. package/dist/{chunk-ZH5WT2IE.cjs.map → chunk-2WM2KSO7.cjs.map} +1 -1
  7. package/dist/{chunk-XMJE34FY.cjs → chunk-2YZZL5FV.cjs} +13 -13
  8. package/dist/{chunk-XMJE34FY.cjs.map → chunk-2YZZL5FV.cjs.map} +1 -1
  9. package/dist/{chunk-2HAEQDHQ.js → chunk-3IHVDQRC.js} +492 -139
  10. package/dist/chunk-3IHVDQRC.js.map +1 -0
  11. package/dist/{chunk-IE5ZNCWN.js → chunk-4AQ4SWJ3.js} +5 -5
  12. package/dist/{chunk-IE5ZNCWN.js.map → chunk-4AQ4SWJ3.js.map} +1 -1
  13. package/dist/{chunk-RT5FTHUU.js → chunk-4X7NFEDB.js} +5 -5
  14. package/dist/{chunk-RT5FTHUU.js.map → chunk-4X7NFEDB.js.map} +1 -1
  15. package/dist/{chunk-SRD4KVAP.cjs → chunk-A2CPCOJA.cjs} +503 -149
  16. package/dist/chunk-A2CPCOJA.cjs.map +1 -0
  17. package/dist/{chunk-AF72QUBI.js → chunk-AEUP63CZ.js} +5 -5
  18. package/dist/{chunk-AF72QUBI.js.map → chunk-AEUP63CZ.js.map} +1 -1
  19. package/dist/{chunk-DQ3VVU5T.cjs → chunk-ALDGRDYD.cjs} +24 -24
  20. package/dist/{chunk-DQ3VVU5T.cjs.map → chunk-ALDGRDYD.cjs.map} +1 -1
  21. package/dist/{chunk-WKOV25NP.cjs → chunk-BO64SLHL.cjs} +8 -8
  22. package/dist/{chunk-WKOV25NP.cjs.map → chunk-BO64SLHL.cjs.map} +1 -1
  23. package/dist/{chunk-L7NE7PR4.cjs → chunk-DMCFARGP.cjs} +13 -13
  24. package/dist/{chunk-L7NE7PR4.cjs.map → chunk-DMCFARGP.cjs.map} +1 -1
  25. package/dist/{chunk-QM4AV6EG.js → chunk-HJLVWZOM.js} +4 -4
  26. package/dist/{chunk-QM4AV6EG.js.map → chunk-HJLVWZOM.js.map} +1 -1
  27. package/dist/{chunk-ZJMTHPHY.js → chunk-ICAYWVNF.js} +3 -3
  28. package/dist/{chunk-ZJMTHPHY.js.map → chunk-ICAYWVNF.js.map} +1 -1
  29. package/dist/{chunk-26GQO5I2.cjs → chunk-JYC2VV3Y.cjs} +12 -12
  30. package/dist/{chunk-26GQO5I2.cjs.map → chunk-JYC2VV3Y.cjs.map} +1 -1
  31. package/dist/{chunk-UCKA22ZJ.cjs → chunk-K63VPFOV.cjs} +9 -2
  32. package/dist/chunk-K63VPFOV.cjs.map +1 -0
  33. package/dist/{chunk-YWQH35VO.js → chunk-NOF6HJDV.js} +4 -4
  34. package/dist/{chunk-YWQH35VO.js.map → chunk-NOF6HJDV.js.map} +1 -1
  35. package/dist/{chunk-I2QGW4GD.js → chunk-OOYKKO3V.js} +11 -11
  36. package/dist/{chunk-I2QGW4GD.js.map → chunk-OOYKKO3V.js.map} +1 -1
  37. package/dist/{chunk-FKGUKFC7.cjs → chunk-OXUUE3HX.cjs} +5 -5
  38. package/dist/{chunk-FKGUKFC7.cjs.map → chunk-OXUUE3HX.cjs.map} +1 -1
  39. package/dist/{chunk-53YOZOGN.cjs → chunk-P5FGJMMI.cjs} +5 -5
  40. package/dist/{chunk-53YOZOGN.cjs.map → chunk-P5FGJMMI.cjs.map} +1 -1
  41. package/dist/{chunk-UAYWLYFW.cjs → chunk-QADR2XMQ.cjs} +18 -18
  42. package/dist/{chunk-UAYWLYFW.cjs.map → chunk-QADR2XMQ.cjs.map} +1 -1
  43. package/dist/{chunk-52GXJNQ3.js → chunk-QIA5FAAW.js} +8 -2
  44. package/dist/chunk-QIA5FAAW.js.map +1 -0
  45. package/dist/{chunk-EKBEKDWO.cjs → chunk-RJGCT35F.cjs} +13 -13
  46. package/dist/{chunk-EKBEKDWO.cjs.map → chunk-RJGCT35F.cjs.map} +1 -1
  47. package/dist/{chunk-33BQNWAQ.js → chunk-T33AJYLW.js} +5 -5
  48. package/dist/{chunk-33BQNWAQ.js.map → chunk-T33AJYLW.js.map} +1 -1
  49. package/dist/{chunk-EVBYEWHO.js → chunk-UHKZXOXD.js} +9 -2
  50. package/dist/chunk-UHKZXOXD.js.map +1 -0
  51. package/dist/{chunk-HA3VRF6E.js → chunk-UIGSH2XB.js} +3 -3
  52. package/dist/{chunk-HA3VRF6E.js.map → chunk-UIGSH2XB.js.map} +1 -1
  53. package/dist/{chunk-Z6TVOAO5.cjs → chunk-UISZWFI7.cjs} +8 -2
  54. package/dist/chunk-UISZWFI7.cjs.map +1 -0
  55. package/dist/{chunk-CE6OGJE6.js → chunk-UYRQEIB7.js} +5 -5
  56. package/dist/{chunk-CE6OGJE6.js.map → chunk-UYRQEIB7.js.map} +1 -1
  57. package/dist/{chunk-QEB6O6GU.js → chunk-W32ND3ZR.js} +6 -6
  58. package/dist/{chunk-QEB6O6GU.js.map → chunk-W32ND3ZR.js.map} +1 -1
  59. package/dist/{chunk-H6I2JDNW.js → chunk-WBLRUJ77.js} +10 -10
  60. package/dist/{chunk-H6I2JDNW.js.map → chunk-WBLRUJ77.js.map} +1 -1
  61. package/dist/{chunk-DP3DM7FR.cjs → chunk-WGIMLXRW.cjs} +6 -6
  62. package/dist/{chunk-DP3DM7FR.cjs.map → chunk-WGIMLXRW.cjs.map} +1 -1
  63. package/dist/{chunk-4H3JTX74.cjs → chunk-ZA5QUQ2V.cjs} +13 -13
  64. package/dist/{chunk-4H3JTX74.cjs.map → chunk-ZA5QUQ2V.cjs.map} +1 -1
  65. package/dist/components/ActivityPreview.cjs +12 -12
  66. package/dist/components/ActivityPreview.d.cts +2 -2
  67. package/dist/components/ActivityPreview.d.ts +2 -2
  68. package/dist/components/ActivityPreview.js +11 -11
  69. package/dist/components/ActivitySequence.cjs +13 -13
  70. package/dist/components/ActivitySequence.d.cts +2 -2
  71. package/dist/components/ActivitySequence.d.ts +2 -2
  72. package/dist/components/ActivitySequence.js +12 -12
  73. package/dist/components/Dictation.cjs +5 -5
  74. package/dist/components/Dictation.d.cts +1 -1
  75. package/dist/components/Dictation.d.ts +1 -1
  76. package/dist/components/Dictation.js +4 -4
  77. package/dist/components/FillInTheBlanks.cjs +5 -5
  78. package/dist/components/FillInTheBlanks.d.cts +1 -1
  79. package/dist/components/FillInTheBlanks.d.ts +1 -1
  80. package/dist/components/FillInTheBlanks.js +4 -4
  81. package/dist/components/GapSelect.cjs +5 -5
  82. package/dist/components/GapSelect.d.cts +1 -1
  83. package/dist/components/GapSelect.d.ts +1 -1
  84. package/dist/components/GapSelect.js +4 -4
  85. package/dist/components/InteractiveVideo.cjs +15 -11
  86. package/dist/components/InteractiveVideo.d.cts +50 -4
  87. package/dist/components/InteractiveVideo.d.ts +50 -4
  88. package/dist/components/InteractiveVideo.js +10 -10
  89. package/dist/components/MultipleChoice.cjs +5 -5
  90. package/dist/components/MultipleChoice.d.cts +1 -1
  91. package/dist/components/MultipleChoice.d.ts +1 -1
  92. package/dist/components/MultipleChoice.js +4 -4
  93. package/dist/components/PronunciationFeedback.cjs +4 -4
  94. package/dist/components/PronunciationFeedback.d.cts +1 -1
  95. package/dist/components/PronunciationFeedback.d.ts +1 -1
  96. package/dist/components/PronunciationFeedback.js +3 -3
  97. package/dist/components/ReadAloud.cjs +6 -6
  98. package/dist/components/ReadAloud.d.cts +2 -2
  99. package/dist/components/ReadAloud.d.ts +2 -2
  100. package/dist/components/ReadAloud.js +5 -5
  101. package/dist/components/StimulusPanel.cjs +4 -4
  102. package/dist/components/StimulusPanel.d.cts +1 -1
  103. package/dist/components/StimulusPanel.d.ts +1 -1
  104. package/dist/components/StimulusPanel.js +3 -3
  105. package/dist/components/WrittenResponse.cjs +5 -5
  106. package/dist/components/WrittenResponse.d.cts +3 -3
  107. package/dist/components/WrittenResponse.d.ts +3 -3
  108. package/dist/components/WrittenResponse.js +4 -4
  109. package/dist/i18n/LkIntlProvider.cjs +7 -7
  110. package/dist/i18n/LkIntlProvider.d.cts +2 -2
  111. package/dist/i18n/LkIntlProvider.d.ts +2 -2
  112. package/dist/i18n/LkIntlProvider.js +1 -1
  113. package/dist/index.cjs +41 -37
  114. package/dist/index.d.cts +3 -3
  115. package/dist/index.d.ts +3 -3
  116. package/dist/index.js +15 -15
  117. package/dist/{strings-D0IWcsUm.d.ts → strings-Dgc5-DeA.d.ts} +21 -2
  118. package/dist/{strings-5588Q4Te.d.cts → strings-zY2QQYpU.d.cts} +21 -2
  119. package/dist/theme/ThemeProvider.cjs +6 -6
  120. package/dist/theme/ThemeProvider.js +1 -1
  121. package/dist/theme/defaults.css +7 -0
  122. package/dist/theme/skin.css +44 -6
  123. package/package.json +3 -3
  124. package/dist/chunk-2HAEQDHQ.js.map +0 -1
  125. package/dist/chunk-52GXJNQ3.js.map +0 -1
  126. package/dist/chunk-EVBYEWHO.js.map +0 -1
  127. package/dist/chunk-SRD4KVAP.cjs.map +0 -1
  128. package/dist/chunk-UCKA22ZJ.cjs.map +0 -1
  129. package/dist/chunk-Z6TVOAO5.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # @intellectif/lk-react
2
2
 
3
+ ## 16.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 7992fac: `<InteractiveVideo>` shows two caption languages at once: a first line and, when the learner asks for
8
+ it, a second under it — the language they are learning and their own, one line each.
9
+
10
+ - **Settings → Captions → Second language** picks the second line; the captions row reads
11
+ `English + Español`. Picking the second line's language as the first swaps them. **C** turns both
12
+ lines off and on, keeping both choices; **Shift + C** turns the second line off and on, and is listed
13
+ in the shortcut sheet.
14
+ - Each line shows its own cue, so a translation segmented differently from the audio still reads
15
+ line for line. The transcript shows the second language under each row, paired by overlap, and its
16
+ search finds either language; the spoiler limit holds for both.
17
+ - Each language loads once for the life of the video, in parallel, and a late file never lands in a
18
+ line that has moved on to another language. A second language that fails to load never takes the
19
+ first with it, and the menu says which failed.
20
+ - **`defaultPreferences`** (new): preferences a host suggests, below what the learner chose — a
21
+ language pair, say. `preferences` keeps its meaning and is now documented as a force.
22
+ **`onPreferencesChange(next, change)`** (new) reports each change the learner makes, for a host that
23
+ keeps the choice on the learner's account and passes it back as `defaultPreferences`.
24
+ `VideoPreferences` gains `secondaryCaptionLanguage`. The player now stores only the fields a learner
25
+ changed, so a host suggestion still reaches a learner who never chose that field; a payload stored
26
+ by 15.x reads as every field chosen.
27
+ - **`resolveCaptionTracks(tracks, preferences)`** (new export): the rules the player uses to choose
28
+ each line's track. A language now matches its regional tracks (`pt` finds `pt-BR`), and where two
29
+ tracks share a language the `captions` one wins. A second line appears only when the learner asked
30
+ for one — never a fallback.
31
+ - `dir="auto"` on every caption line, transcript row and menu item that shows a track's text, so an
32
+ Arabic line's punctuation lands on the right side.
33
+ - Four optional tokens style the lines: `--lk-iv-caption-color`, `--lk-iv-caption-secondary-color`
34
+ (warm yellow, clearing 4.5:1 on the caption box), `--lk-iv-caption-secondary-scale` and
35
+ `--lk-iv-caption-gap`. The second line differs by position and size as well as colour. Four new
36
+ strings, all in `docs/i18n.md`.
37
+
38
+ **One DOM change, for hosts that style the captions:** the lines now sit inside a
39
+ `<div class="lk-iv-captions">`, which is what is positioned over the video and rises with the
40
+ controls. Each line keeps `.lk-iv-caption`, its `span`, `data-size` and `data-background` (and gains
41
+ `data-role`, `lang` and `dir`), so rules that style a line's text still match. A rule that positions
42
+ `.lk-iv-caption` over the video should move to `.lk-iv-captions`.
43
+
44
+ **Major** because the peer range moves to `@intellectif/lk-core@^0.16.0`, whose tightened dictation
45
+ rule can refuse stored content. Nothing in this package was removed.
46
+
47
+ See `docs/interactive-video.md` and the 0.15 → 0.16 section of `docs/upgrading.md`.
48
+
49
+ ### Patch Changes
50
+
51
+ - Updated dependencies [7992fac]
52
+ - @intellectif/lk-core@0.16.0
53
+
3
54
  ## 15.0.0
4
55
 
5
56
  ### Major Changes
package/README.md CHANGED
@@ -72,7 +72,7 @@ export function Demo() {
72
72
  - **`<ReadAloud>`** — the learner reads a text aloud. A model recording and an optional slower one (same playback policy, and both kept silent for as long as a take is being recorded, so the microphone never picks up the model), a microphone control bounded by the item's take budget and its time limit, playback of the take before it is sent, and a word-by-word pronunciation result. The SDK captures and renders; it stores nothing and judges nothing: `recordingBinding.upload` puts the take in **your** storage and `recordingBinding.assess` (`practice` only) returns **your** server's judgement, so no audio, no key and no assessor ever sit in the component. In `exam` it uploads, submits and locks without scoring, revealing or assessing — and a take whose upload failed offers a retry and blocks submit rather than silently becoming a blank. In `review` it renders the stored `outcome`, marked from an `assessment` you pass or, failing that, rebuilt from the outcome's stored `details`.
73
73
  - **`<PronunciationFeedback>`** — the marks on their own, for a review screen that has evidence but no activity: the graded dimensions (accuracy, fluency, completeness, prosody — one the engine did not measure reads "not assessed", **never 0%**), and every word marked `correct` / `mispronounced` / `omitted` / `inserted` with a hidden sentence per word for screen readers and a glyph plus a text decoration for everyone else. A word opens onto its syllables, its sounds, what was heard instead, and a button that plays just that word. Evidence it cannot trust is checked before it is aligned, so in production a malformed assessment costs the word list — never the grade beside it.
74
74
  - **`<WrittenResponse>`** — free-text writing with a live word counter and bounds messaging, graded **asynchronously**: it emits an ungraded submission (never a fake zero) and a SUBMITTED-verb xAPI statement, and renders a returned `GradeRecord` in `review` mode with per-criterion scores and inline corrections.
75
- - **`<InteractiveVideo>`** — a video that stops at each quiz and asks its questions over itself, then plays on. One player: a progress bar that marks every quiz and previews the caption under the pointer, speed, volume, captions drawn from WebVTT it parses itself (through a `captionsLoader` when the file needs the learner's credentials), a contents and transcript panel, picture-in-picture, fullscreen and a keyboard map with a shortcut sheet. A quiz covers the video and grows the player rather than scrolling inside it, every question of an opened quiz stays mounted so a rewind loses no answer, the controls are `inert` while it is open, and a **required** quiz holds both playback and seeking until it is answered. Answers report with the slot the question sits in and the quiz it belongs to, and `onProgress` gives a resume point that is never past an unanswered required quiz. See the [interactive video guide](https://github.com/intellectif/learning-kit/blob/main/docs/interactive-video.md).
75
+ - **`<InteractiveVideo>`** — a video that stops at each quiz and asks its questions over itself, then plays on. One player: a progress bar that marks every quiz and previews the caption under the pointer, speed, volume, captions drawn from WebVTT it parses itself (through a `captionsLoader` when the file needs the learner's credentials) — in one language or two at once, a second line under the first for a learner matching what they hear to what it means — a contents and transcript panel, picture-in-picture, fullscreen and a keyboard map with a shortcut sheet. A quiz covers the video and grows the player rather than scrolling inside it, every question of an opened quiz stays mounted so a rewind loses no answer, the controls are `inert` while it is open, and a **required** quiz holds both playback and seeking until it is answered. Answers report with the slot the question sits in and the quiz it belongs to, and `onProgress` gives a resume point that is never past an unanswered required quiz. See the [interactive video guide](https://github.com/intellectif/learning-kit/blob/main/docs/interactive-video.md).
76
76
  - **`<ActivitySequence>`** — in-place "question set" pager (Previous/Next, "Question X of N", no scrolling, focus-managed). Accepts item groups and keeps their stimulus beside every question; `onSubmit` reports every raw answer with its `slotId`, which is the only response channel an `exam` sequence has. `onFinished` is the completion signal for a set that mixes scored and deferred-graded items, where `onComplete` can never fire. A read-aloud slot takes its storage from `recordingBinding`, whose methods are told which slot a take belongs to, and a `review` its per-word marks from `assessments`, keyed by `slotId` — there is a [worked example](https://github.com/intellectif/learning-kit/blob/main/docs/speech-assessment.md#in-a-question-set).
77
77
  - **Resume and review a whole attempt** — `<ActivitySequence>` takes `defaultIndex`, `responses` and `submittedSlotIds` (read at mount; remount with a `key` to show a different attempt), so an interrupted paper reopens on the right question with the right answers and already-committed questions still committed. `onIndexChange` reports every position the pager lands on, including a clamp it had to apply. Pass `renderMode="review"` plus server-computed `outcomes` to render a finished attempt read-only. Pairs with `serializeAttemptState` / `restoreAttemptState` in `lk-core`.
78
78
  - **`renderMode`** — `practice` (default: the component scores locally and reveals correctness), `exam` (never scores, never reveals; submit emits the raw response for the server to grade), `review` (read-only, marks correctness only from an `outcome` you supply). This is the single switch that takes grading off the client.
@@ -91,7 +91,7 @@ export function Demo() {
91
91
  - **`useSpeechRecorder(options)`** — the capture half of a read-aloud, usable on its own: microphone permission, an RMS level for a meter, a minimum take length, and an auto-stop measured from the **sample count** rather than a timer, so a take can never outrun its own limit. It yields **16 kHz mono 16-bit PCM WAV** — the one format `inspectWav` in `lk-core` measures without a decoder. SSR-safe by construction (support is discovered inside `start()`, never probed during render, so a server render and its hydration cannot disagree), and the microphone and the audio context are released on stop, discard, error and unmount alike. Where a Content-Security-Policy's `script-src` does not allow `blob:`, serve `CAPTURE_PROCESSOR_SOURCE` — exported beside the hook, with the contract it meets written on it — and pass its URL as `workletUrl`. A `workletUrl` that fails to load is not reported: the hook falls back to the main-thread `ScriptProcessorNode`, so check that the module is fetched.
92
92
  - **`<ThemeProvider>` + `defaults.css`** — `--lk-*` design-token system; automatic dark mode via `prefers-color-scheme` (SSR-safe with `useSyncExternalStore`).
93
93
  - **`createTailwindTheme(theme)`** — optional Tailwind interop; consume the SDK palette from your own utilities.
94
- - **`<LkIntlProvider>`** — all 163 strings the SDK's own chrome renders, replaceable in one place, with a per-component `strings` prop for the exceptions. Interpolation and plurals are **functions**, not format strings, so your `Intl.PluralRules` does the work and TypeScript checks the arity. `locale` sets `lang` and derives `dir`; the skin uses logical properties, so RTL follows. The SDK ships the mechanism and **English only** — see [docs/i18n.md](https://github.com/intellectif/learning-kit/blob/main/docs/i18n.md).
94
+ - **`<LkIntlProvider>`** — all 167 strings the SDK's own chrome renders, replaceable in one place, with a per-component `strings` prop for the exceptions. Interpolation and plurals are **functions**, not format strings, so your `Intl.PluralRules` does the work and TypeScript checks the arity. `locale` sets `lang` and derives `dir`; the skin uses logical properties, so RTL follows. The SDK ships the mechanism and **English only** — see [docs/i18n.md](https://github.com/intellectif/learning-kit/blob/main/docs/i18n.md).
95
95
  - **WCAG 2.2 AA** — axe-clean unit + Playwright e2e tests; full keyboard operability; numerically-verified contrast.
96
96
  - **RSC-compatible** — every component carries `'use client'` and hydrates inside a React Server Component tree.
97
97
 
@@ -1,5 +1,5 @@
1
1
  import { XAPIStatement, WrittenResponseData, LearnerResponse, ItemOutcome, InteractionEvent, ThemeTokens } from '@intellectif/lk-core';
2
- import { f as Renderable, e as RenderMode, H as HtmlSanitizer, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from './strings-5588Q4Te.cjs';
2
+ import { f as Renderable, e as RenderMode, H as HtmlSanitizer, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from './strings-zY2QQYpU.cjs';
3
3
 
4
4
  /**
5
5
  * Payload delivered when the learner submits a written response. Grading is
@@ -1,5 +1,5 @@
1
1
  import { XAPIStatement, WrittenResponseData, LearnerResponse, ItemOutcome, InteractionEvent, ThemeTokens } from '@intellectif/lk-core';
2
- import { f as Renderable, e as RenderMode, H as HtmlSanitizer, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from './strings-D0IWcsUm.js';
2
+ import { f as Renderable, e as RenderMode, H as HtmlSanitizer, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from './strings-Dgc5-DeA.js';
3
3
 
4
4
  /**
5
5
  * Payload delivered when the learner submits a written response. Grading is
@@ -1,14 +1,14 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkWKOV25NP_cjs = require('./chunk-WKOV25NP.cjs');
4
+ var chunkBO64SLHL_cjs = require('./chunk-BO64SLHL.cjs');
5
5
  var chunkUDCQTOVU_cjs = require('./chunk-UDCQTOVU.cjs');
6
6
  var chunkOD65OZIW_cjs = require('./chunk-OD65OZIW.cjs');
7
7
  var chunkBRPEB43C_cjs = require('./chunk-BRPEB43C.cjs');
8
- var chunk53YOZOGN_cjs = require('./chunk-53YOZOGN.cjs');
9
- var chunkFKGUKFC7_cjs = require('./chunk-FKGUKFC7.cjs');
8
+ var chunkP5FGJMMI_cjs = require('./chunk-P5FGJMMI.cjs');
9
+ var chunkOXUUE3HX_cjs = require('./chunk-OXUUE3HX.cjs');
10
10
  var chunkXOR4MPEN_cjs = require('./chunk-XOR4MPEN.cjs');
11
- var chunkZ6TVOAO5_cjs = require('./chunk-Z6TVOAO5.cjs');
11
+ var chunkUISZWFI7_cjs = require('./chunk-UISZWFI7.cjs');
12
12
  var lkCore = require('@intellectif/lk-core');
13
13
  var react = require('react');
14
14
  var jsxRuntime = require('react/jsx-runtime');
@@ -172,7 +172,7 @@ function OutcomeSummary({
172
172
  "data-status": reading.status,
173
173
  "data-passed": String(reading.grade.passed),
174
174
  children: scoreShown ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
175
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-ra-grade", children: s.scoreAnnouncement(chunkWKOV25NP_cjs.percentOfGrade(reading.grade), reading.grade.passed) }),
175
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-ra-grade", children: s.scoreAnnouncement(chunkBO64SLHL_cjs.percentOfGrade(reading.grade), reading.grade.passed) }),
176
176
  reading.grade.feedback ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-ra-grade-feedback", dir: "auto", children: reading.grade.feedback }) : null
177
177
  ] })
178
178
  }
@@ -224,11 +224,11 @@ function ReadAloud({
224
224
  }) {
225
225
  const isExam = renderMode === "exam";
226
226
  const isReview = renderMode === "review";
227
- const s = chunkZ6TVOAO5_cjs.useLkStrings(strings);
227
+ const s = chunkUISZWFI7_cjs.useLkStrings(strings);
228
228
  const slot = react.useContext(SequenceSlotContext);
229
229
  const captureGroup = slot?.captureGroup;
230
230
  const devError = react.useMemo(() => {
231
- if (!chunk53YOZOGN_cjs.isDevelopment()) {
231
+ if (!chunkP5FGJMMI_cjs.isDevelopment()) {
232
232
  return null;
233
233
  }
234
234
  if (data.redacted === true) {
@@ -419,7 +419,7 @@ function ReadAloud({
419
419
  [data, s.readAloudSlowRecording]
420
420
  );
421
421
  const takeAudio = isReview ? playbackUrl : takeUrl;
422
- const playback = chunkWKOV25NP_cjs.usePlaybackRefusal(takeAudio);
422
+ const playback = chunkBO64SLHL_cjs.usePlaybackRefusal(takeAudio);
423
423
  const submitRef = react.useRef(null);
424
424
  if (devError) {
425
425
  throw devError;
@@ -466,7 +466,7 @@ function ReadAloud({
466
466
  if (run !== runRef.current) {
467
467
  return;
468
468
  }
469
- const result = chunkWKOV25NP_cjs.readAssessResult(answer);
469
+ const result = chunkBO64SLHL_cjs.readAssessResult(answer);
470
470
  if (result.status === "failed") {
471
471
  raise({ kind: "assess-failed", take: take2, retryable: result.retryable });
472
472
  fire("assessment-failed", { takes: takes2, durationMs, retryable: result.retryable });
@@ -497,9 +497,9 @@ function ReadAloud({
497
497
  passed: grade.passed,
498
498
  timeSpent,
499
499
  xapiStatement: lkCore.xAPIBuilder.buildAnsweredStatement({
500
- actor: chunk53YOZOGN_cjs.ANONYMOUS_ACTOR,
500
+ actor: chunkP5FGJMMI_cjs.ANONYMOUS_ACTOR,
501
501
  object: {
502
- id: chunk53YOZOGN_cjs.objectIdFor(data.id),
502
+ id: chunkP5FGJMMI_cjs.objectIdFor(data.id),
503
503
  name: { [data.locale ?? "en-US"]: data.title },
504
504
  ...lkCore.xapiDefinitionFor(data)
505
505
  },
@@ -509,7 +509,7 @@ function ReadAloud({
509
509
  // optional, and an empty list is the honest reading of "no per-word
510
510
  // marks were stored" — never a mark of its own.
511
511
  scoringResult: {
512
- score: chunkWKOV25NP_cjs.fractionOfGrade(grade),
512
+ score: chunkBO64SLHL_cjs.fractionOfGrade(grade),
513
513
  maxScore: 1,
514
514
  passed: grade.passed,
515
515
  feedback: grade.feedback,
@@ -603,8 +603,8 @@ function ReadAloud({
603
603
  };
604
604
  const contentLang = typeof data.locale === "string" ? data.locale : void 0;
605
605
  const contentDir = chunkOD65OZIW_cjs.localeDirectionOf(data.locale);
606
- const outcomeReading = react.useMemo(() => chunkWKOV25NP_cjs.readOutcome(outcome), [outcome]);
607
- const keptEvidence = react.useMemo(() => chunkWKOV25NP_cjs.readEvidence(assessment), [assessment]);
606
+ const outcomeReading = react.useMemo(() => chunkBO64SLHL_cjs.readOutcome(outcome), [outcome]);
607
+ const keptEvidence = react.useMemo(() => chunkBO64SLHL_cjs.readEvidence(assessment), [assessment]);
608
608
  const storedGrade = outcomeReading?.kind === "graded" && outcomeReading.status === "graded" ? outcomeReading.grade : null;
609
609
  const storedMarks = react.useMemo(
610
610
  () => isReview && keptEvidence === null && storedGrade?.details !== void 0 ? marksFromDetails(storedGrade.details) : null,
@@ -646,7 +646,7 @@ function ReadAloud({
646
646
  case "graded": {
647
647
  const grade = phase.grade;
648
648
  return grade === null ? { text: `${s.answerSubmitted} ${s.couldNotBeGraded}`, feedback: null } : {
649
- text: `${s.answerSubmitted} ${s.scoreAnnouncement(chunkWKOV25NP_cjs.percentOfGrade(grade), grade.passed)}`,
649
+ text: `${s.answerSubmitted} ${s.scoreAnnouncement(chunkBO64SLHL_cjs.percentOfGrade(grade), grade.passed)}`,
650
650
  feedback: grade.feedback
651
651
  };
652
652
  }
@@ -679,7 +679,7 @@ function ReadAloud({
679
679
  data.media !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: "lk-ra-model", children: [
680
680
  /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "lk-ra-model-label", children: s.readAloudModelRecording }),
681
681
  /* @__PURE__ */ jsxRuntime.jsx(
682
- chunkFKGUKFC7_cjs.ActivityMedia,
682
+ chunkOXUUE3HX_cjs.ActivityMedia,
683
683
  {
684
684
  media: data.media,
685
685
  renderMode,
@@ -696,7 +696,7 @@ function ReadAloud({
696
696
  slowMedia !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: "lk-ra-model", "data-slow": "true", children: [
697
697
  /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "lk-ra-model-label", children: s.readAloudSlowRecording }),
698
698
  /* @__PURE__ */ jsxRuntime.jsx(
699
- chunkFKGUKFC7_cjs.ActivityMedia,
699
+ chunkOXUUE3HX_cjs.ActivityMedia,
700
700
  {
701
701
  media: slowMedia,
702
702
  renderMode,
@@ -829,7 +829,7 @@ function ReadAloud({
829
829
  busy ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-ra-pending", role: "status", "aria-busy": "true", children: phase.kind === "uploading" ? s.readAloudUploading : s.readAloudAssessing }) : null,
830
830
  alertText !== null ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-ra-alert", role: "alert", children: alertText }, errorNonce) : null,
831
831
  feedbackAssessment !== null ? /* @__PURE__ */ jsxRuntime.jsx(
832
- chunkWKOV25NP_cjs.PronunciationFeedback,
832
+ chunkBO64SLHL_cjs.PronunciationFeedback,
833
833
  {
834
834
  data: { referenceText: data.referenceText, locale: data.locale },
835
835
  assessment: feedbackAssessment,
@@ -843,14 +843,14 @@ function ReadAloud({
843
843
  ) : null,
844
844
  storedMarks !== null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lk-ra-marks", children: [
845
845
  /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "lk-ra-words", "aria-label": s.pronunciationWordsLabel, dir: contentDir, children: storedMarks.map((entry, index) => {
846
- const sentence = chunkWKOV25NP_cjs.markSentence(entry, s);
846
+ const sentence = chunkBO64SLHL_cjs.markSentence(entry, s);
847
847
  return /* @__PURE__ */ jsxRuntime.jsxs(
848
848
  "li",
849
849
  {
850
850
  className: "lk-ra-word",
851
851
  "data-state": entry.state,
852
852
  children: [
853
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lk-visually-hidden", style: chunkWKOV25NP_cjs.VISUALLY_HIDDEN, children: sentence }),
853
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lk-visually-hidden", style: chunkBO64SLHL_cjs.VISUALLY_HIDDEN, children: sentence }),
854
854
  /* @__PURE__ */ jsxRuntime.jsx(
855
855
  "span",
856
856
  {
@@ -874,15 +874,15 @@ function ReadAloud({
874
874
  // but a live region is the only thing that TELLS a screen-reader
875
875
  // learner a grade arrived, since nothing takes focus. Clipped rather
876
876
  // than `display: none`, which would stop it being announced at all.
877
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lk-visually-hidden", style: chunkWKOV25NP_cjs.VISUALLY_HIDDEN, children: /* @__PURE__ */ jsxRuntime.jsx(AnnouncementText, { announcement }) })
877
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lk-visually-hidden", style: chunkBO64SLHL_cjs.VISUALLY_HIDDEN, children: /* @__PURE__ */ jsxRuntime.jsx(AnnouncementText, { announcement }) })
878
878
  ) : /* @__PURE__ */ jsxRuntime.jsx(AnnouncementText, { announcement }) })
879
879
  ]
880
880
  }
881
881
  );
882
882
  }
883
883
  function ReadAloud2(props) {
884
- const strings = chunkZ6TVOAO5_cjs.useLkStrings(props.strings);
885
- return /* @__PURE__ */ jsxRuntime.jsx(chunk53YOZOGN_cjs.ActivityErrorBoundary, { activityTitle: props.data?.title, strings, children: /* @__PURE__ */ jsxRuntime.jsx(ReadAloud, { ...props }) });
884
+ const strings = chunkUISZWFI7_cjs.useLkStrings(props.strings);
885
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkP5FGJMMI_cjs.ActivityErrorBoundary, { activityTitle: props.data?.title, strings, children: /* @__PURE__ */ jsxRuntime.jsx(ReadAloud, { ...props }) });
886
886
  }
887
887
 
888
888
  exports.ReadAloud = ReadAloud2;
@@ -890,5 +890,5 @@ exports.SequenceSlotContext = SequenceSlotContext;
890
890
  exports.mintTake = mintTake;
891
891
  exports.stopCaptureGroup = stopCaptureGroup;
892
892
  exports.takeOf = takeOf;
893
- //# sourceMappingURL=chunk-ZH5WT2IE.cjs.map
894
- //# sourceMappingURL=chunk-ZH5WT2IE.cjs.map
893
+ //# sourceMappingURL=chunk-2WM2KSO7.cjs.map
894
+ //# sourceMappingURL=chunk-2WM2KSO7.cjs.map