@intellectif/lk-react 16.1.1 → 18.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.
- package/CHANGELOG.md +57 -0
- package/README.md +3 -1
- package/dist/{WrittenResponse-xJ7I_5yq.d.ts → WrittenResponse-B4kY-U0v.d.ts} +1 -1
- package/dist/{WrittenResponse-6tSj6U3G.d.cts → WrittenResponse-Dl3zah22.d.cts} +1 -1
- package/dist/ai/LkAiProvider.cjs +17 -0
- package/dist/ai/LkAiProvider.cjs.map +1 -0
- package/dist/ai/LkAiProvider.d.cts +60 -0
- package/dist/ai/LkAiProvider.d.ts +60 -0
- package/dist/ai/LkAiProvider.js +4 -0
- package/dist/ai/LkAiProvider.js.map +1 -0
- package/dist/{chunk-PXGJHZKJ.cjs → chunk-3FBBP5QR.cjs} +6 -6
- package/dist/{chunk-PXGJHZKJ.cjs.map → chunk-3FBBP5QR.cjs.map} +1 -1
- package/dist/{chunk-3HC3PJTB.cjs → chunk-3TJSFPO4.cjs} +26 -22
- package/dist/chunk-3TJSFPO4.cjs.map +1 -0
- package/dist/chunk-5F4Q6JT7.cjs +289 -0
- package/dist/chunk-5F4Q6JT7.cjs.map +1 -0
- package/dist/{chunk-3UXRX4KU.js → chunk-6DTW5T3Z.js} +39 -7
- package/dist/chunk-6DTW5T3Z.js.map +1 -0
- package/dist/{chunk-ML6L4LJH.cjs → chunk-6RRFH7C4.cjs} +25 -25
- package/dist/{chunk-ML6L4LJH.cjs.map → chunk-6RRFH7C4.cjs.map} +1 -1
- package/dist/{chunk-JPDR6TTA.js → chunk-7K4B2EMU.js} +4 -4
- package/dist/{chunk-JPDR6TTA.js.map → chunk-7K4B2EMU.js.map} +1 -1
- package/dist/{chunk-MQAZJQRE.cjs → chunk-AHGB5HH6.cjs} +13 -2
- package/dist/chunk-AHGB5HH6.cjs.map +1 -0
- package/dist/{chunk-5QHVYOME.js → chunk-ALH6TUX2.js} +39 -7
- package/dist/chunk-ALH6TUX2.js.map +1 -0
- package/dist/{chunk-2S3MK4VX.cjs → chunk-BAKLJKFZ.cjs} +5 -5
- package/dist/{chunk-2S3MK4VX.cjs.map → chunk-BAKLJKFZ.cjs.map} +1 -1
- package/dist/{chunk-ZPCO3CEB.js → chunk-BY4UQH2Y.js} +3 -3
- package/dist/{chunk-ZPCO3CEB.js.map → chunk-BY4UQH2Y.js.map} +1 -1
- package/dist/chunk-GR33G5QM.js +286 -0
- package/dist/chunk-GR33G5QM.js.map +1 -0
- package/dist/{chunk-ZEDMFTKD.js → chunk-H3IRVX7J.js} +10 -10
- package/dist/{chunk-ZEDMFTKD.js.map → chunk-H3IRVX7J.js.map} +1 -1
- package/dist/{chunk-PTJTC6A3.cjs → chunk-H63O5HPW.cjs} +23 -14
- package/dist/chunk-H63O5HPW.cjs.map +1 -0
- package/dist/{chunk-IQI5I2X5.js → chunk-HZMILQYO.js} +25 -7
- package/dist/chunk-HZMILQYO.js.map +1 -0
- package/dist/{chunk-ZSY4VANQ.cjs → chunk-JKMBFHER.cjs} +47 -15
- package/dist/chunk-JKMBFHER.cjs.map +1 -0
- package/dist/{chunk-GUPBIEUA.js → chunk-KP57YCYQ.js} +6 -6
- package/dist/{chunk-GUPBIEUA.js.map → chunk-KP57YCYQ.js.map} +1 -1
- package/dist/{chunk-GDMM2WEG.js → chunk-KWKB74KL.js} +16 -12
- package/dist/chunk-KWKB74KL.js.map +1 -0
- package/dist/{chunk-TRP5Z3XW.cjs → chunk-L7WY5YFQ.cjs} +5 -5
- package/dist/{chunk-TRP5Z3XW.cjs.map → chunk-L7WY5YFQ.cjs.map} +1 -1
- package/dist/{chunk-B6S5ADHR.cjs → chunk-QA42VDTA.cjs} +47 -15
- package/dist/chunk-QA42VDTA.cjs.map +1 -0
- package/dist/{chunk-VC2MPB2Y.js → chunk-QHK6PTUR.js} +39 -7
- package/dist/chunk-QHK6PTUR.js.map +1 -0
- package/dist/{chunk-BI547RIA.js → chunk-QJW3K6JN.js} +4 -4
- package/dist/{chunk-BI547RIA.js.map → chunk-QJW3K6JN.js.map} +1 -1
- package/dist/{chunk-RSQFGF5W.cjs → chunk-RZ52SEYV.cjs} +33 -15
- package/dist/chunk-RZ52SEYV.cjs.map +1 -0
- package/dist/{chunk-2TFNDHJ5.cjs → chunk-TI23GIFM.cjs} +47 -15
- package/dist/chunk-TI23GIFM.cjs.map +1 -0
- package/dist/{chunk-DFMBVA7D.cjs → chunk-UQIRDE52.cjs} +8 -8
- package/dist/{chunk-DFMBVA7D.cjs.map → chunk-UQIRDE52.cjs.map} +1 -1
- package/dist/{chunk-56WAZKPS.js → chunk-UYQBEPNZ.js} +13 -9
- package/dist/chunk-UYQBEPNZ.js.map +1 -0
- package/dist/{chunk-2XNCPLHU.js → chunk-V5BTVGPA.js} +16 -7
- package/dist/chunk-V5BTVGPA.js.map +1 -0
- package/dist/{chunk-FZWWVJE4.cjs → chunk-XEGBGKHV.cjs} +29 -25
- package/dist/chunk-XEGBGKHV.cjs.map +1 -0
- package/dist/chunk-YNDKAYW3.js +17 -0
- package/dist/chunk-YNDKAYW3.js.map +1 -0
- package/dist/{chunk-KSAINXRG.js → chunk-YRNEOBXA.js} +13 -2
- package/dist/chunk-YRNEOBXA.js.map +1 -0
- package/dist/{chunk-DKZWUIQD.js → chunk-YTGRXD23.js} +3 -3
- package/dist/{chunk-DKZWUIQD.js.map → chunk-YTGRXD23.js.map} +1 -1
- package/dist/{chunk-OO24JGYH.cjs → chunk-Z5XY66PO.cjs} +18 -18
- package/dist/{chunk-OO24JGYH.cjs.map → chunk-Z5XY66PO.cjs.map} +1 -1
- package/dist/chunk-ZDYNAWDZ.cjs +20 -0
- package/dist/chunk-ZDYNAWDZ.cjs.map +1 -0
- package/dist/components/ActivityPreview.cjs +14 -12
- package/dist/components/ActivityPreview.d.cts +3 -2
- package/dist/components/ActivityPreview.d.ts +3 -2
- package/dist/components/ActivityPreview.js +13 -11
- package/dist/components/ActivitySequence.cjs +15 -13
- package/dist/components/ActivitySequence.d.cts +12 -3
- package/dist/components/ActivitySequence.d.ts +12 -3
- package/dist/components/ActivitySequence.js +14 -12
- package/dist/components/Dictation.cjs +7 -5
- package/dist/components/Dictation.d.cts +3 -1
- package/dist/components/Dictation.d.ts +3 -1
- package/dist/components/Dictation.js +6 -4
- package/dist/components/FillInTheBlanks.cjs +7 -5
- package/dist/components/FillInTheBlanks.d.cts +3 -1
- package/dist/components/FillInTheBlanks.d.ts +3 -1
- package/dist/components/FillInTheBlanks.js +6 -4
- package/dist/components/GapSelect.cjs +7 -5
- package/dist/components/GapSelect.d.cts +3 -1
- package/dist/components/GapSelect.d.ts +3 -1
- package/dist/components/GapSelect.js +6 -4
- package/dist/components/InteractiveVideo.cjs +14 -12
- package/dist/components/InteractiveVideo.d.cts +16 -2
- package/dist/components/InteractiveVideo.d.ts +16 -2
- package/dist/components/InteractiveVideo.js +12 -10
- package/dist/components/MultipleChoice.cjs +7 -5
- package/dist/components/MultipleChoice.d.cts +3 -1
- package/dist/components/MultipleChoice.d.ts +3 -1
- package/dist/components/MultipleChoice.js +6 -4
- package/dist/components/PronunciationFeedback.cjs +4 -4
- package/dist/components/PronunciationFeedback.d.cts +3 -1
- package/dist/components/PronunciationFeedback.d.ts +3 -1
- package/dist/components/PronunciationFeedback.js +3 -3
- package/dist/components/ReadAloud.cjs +6 -6
- package/dist/components/ReadAloud.d.cts +4 -2
- package/dist/components/ReadAloud.d.ts +4 -2
- package/dist/components/ReadAloud.js +5 -5
- package/dist/components/StimulusPanel.cjs +4 -4
- package/dist/components/StimulusPanel.d.cts +3 -1
- package/dist/components/StimulusPanel.d.ts +3 -1
- package/dist/components/StimulusPanel.js +3 -3
- package/dist/components/WrittenResponse.cjs +5 -5
- package/dist/components/WrittenResponse.d.cts +5 -3
- package/dist/components/WrittenResponse.d.ts +5 -3
- package/dist/components/WrittenResponse.js +4 -4
- package/dist/i18n/LkIntlProvider.cjs +7 -7
- package/dist/i18n/LkIntlProvider.d.cts +4 -2
- package/dist/i18n/LkIntlProvider.d.ts +4 -2
- package/dist/i18n/LkIntlProvider.js +1 -1
- package/dist/index.cjs +47 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +17 -15
- package/dist/index.js.map +1 -1
- package/dist/{strings-C6wM5aUQ.d.cts → strings-BOPKhnS-.d.cts} +30 -0
- package/dist/{strings-Cd_2F-Bw.d.ts → strings-PCYKWCwd.d.ts} +30 -0
- package/dist/theme/skin.css +90 -0
- package/package.json +13 -3
- package/dist/chunk-2TFNDHJ5.cjs.map +0 -1
- package/dist/chunk-2XNCPLHU.js.map +0 -1
- package/dist/chunk-3HC3PJTB.cjs.map +0 -1
- package/dist/chunk-3UXRX4KU.js.map +0 -1
- package/dist/chunk-56WAZKPS.js.map +0 -1
- package/dist/chunk-5QHVYOME.js.map +0 -1
- package/dist/chunk-B6S5ADHR.cjs.map +0 -1
- package/dist/chunk-FZWWVJE4.cjs.map +0 -1
- package/dist/chunk-GDMM2WEG.js.map +0 -1
- package/dist/chunk-IQI5I2X5.js.map +0 -1
- package/dist/chunk-KSAINXRG.js.map +0 -1
- package/dist/chunk-MQAZJQRE.cjs.map +0 -1
- package/dist/chunk-PTJTC6A3.cjs.map +0 -1
- package/dist/chunk-RSQFGF5W.cjs.map +0 -1
- package/dist/chunk-VC2MPB2Y.js.map +0 -1
- package/dist/chunk-ZSY4VANQ.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# @intellectif/lk-react
|
|
2
2
|
|
|
3
|
+
## 18.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [71de78d]
|
|
8
|
+
- @intellectif/lk-core@0.18.0
|
|
9
|
+
|
|
10
|
+
## 17.0.0
|
|
11
|
+
|
|
12
|
+
### Major Changes
|
|
13
|
+
|
|
14
|
+
- 15a3435: Learners can ask an AI for help. "Explain my answer" appears under a graded answer, and "Get a hint"
|
|
15
|
+
before submit, in `<MultipleChoice>`, `<FillInTheBlanks>` and `<GapSelect>`. `<Dictation>` gets
|
|
16
|
+
explanations only; it has word hints of its own.
|
|
17
|
+
|
|
18
|
+
- **Your model, through ports you supply.** `<LkAiProvider ai={{ explain, hint, maxHints, learnerLocale }}>`
|
|
19
|
+
(new subpath `@intellectif/lk-react/ai/LkAiProvider`, also on the root) supplies them. So does an
|
|
20
|
+
`ai` prop on every activity, on `<ActivitySequence>` and on `<InteractiveVideo>`. A component's own
|
|
21
|
+
`ai` wins over the provider's, whole. A question a host draws — a `renderers` override, or the video's
|
|
22
|
+
`renderQuestion` (as the new `ai` field of `InteractiveVideoQuestion`) — is handed the ports in force,
|
|
23
|
+
except in `exam`. Leave a port out and that help does not appear.
|
|
24
|
+
- **Where it appears:**
|
|
25
|
+
- hints in `practice` before submit, up to `maxHints` (3 by default, at most 10), on a question that
|
|
26
|
+
is not disabled;
|
|
27
|
+
- an explanation in `practice` after submit, or in `review` when `outcome` is scored;
|
|
28
|
+
- **nothing in `exam`**, whatever is passed;
|
|
29
|
+
- nothing an item's author switched off with `ai: { hints: false }` or `ai: { explanations: false }`.
|
|
30
|
+
- **What a learner sees is checked first.** A hint containing the answer, an explanation of a verdict
|
|
31
|
+
other than the SDK's, and malformed, empty or over-long text are all refused. The learner sees "not
|
|
32
|
+
available" and can ask again, and a development build logs the reason. A refused hint is not
|
|
33
|
+
counted.
|
|
34
|
+
- **Everything a model wrote is marked:** "Written by AI. It can make mistakes."
|
|
35
|
+
- **A call only when the learner presses a button**, with an `AbortSignal` that fires when the answer
|
|
36
|
+
it was about goes away. A late answer is dropped either way, and a failure never blocks the
|
|
37
|
+
question.
|
|
38
|
+
- **For accessibility:** focus moves to an explanation when it arrives, and the buttons stay focusable
|
|
39
|
+
while working (`aria-busy`, `aria-disabled`).
|
|
40
|
+
- **Records:** `ai-hint-shown` and `ai-explanation-shown` reach `onInteraction`, each with the port's
|
|
41
|
+
`provenance`.
|
|
42
|
+
- **Styling and strings:** eleven new strings (`aiExplain` … `aiNotice`, all in `docs/i18n.md`) and
|
|
43
|
+
`.lk-ai-*` classes in the optional skin.
|
|
44
|
+
|
|
45
|
+
**Major** because the peer range moves to `@intellectif/lk-core@^0.17.0`, whose `ai` field can
|
|
46
|
+
refuse stored content (see its changelog). A host that passes no AI port sees nothing new.
|
|
47
|
+
|
|
48
|
+
See `docs/ai.md`.
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- 15a3435: `<WrittenResponse>` gives every inline correction in a returned grade a list key of its own. A grade
|
|
53
|
+
that carries the same correction twice — the same mistake made twice in one essay — used to render
|
|
54
|
+
both rows under one key. React warns about that, and when the grade re-renders it can drop or
|
|
55
|
+
duplicate a row. A correction is now keyed by its `range`, or by its position when it has no range
|
|
56
|
+
or repeats one the grader already used. No API changes.
|
|
57
|
+
- Updated dependencies [15a3435]
|
|
58
|
+
- @intellectif/lk-core@0.17.0
|
|
59
|
+
|
|
3
60
|
## 16.1.1
|
|
4
61
|
|
|
5
62
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@ export function Demo() {
|
|
|
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
75
|
- **`<InteractiveVideo>`** — a video that stops at each quiz and asks its questions over itself, then plays on. **A formative tool**, for lessons and practice — deliver official summative exams with `<ActivitySequence>`. 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. A host with renderers of its own draws any question itself through `renderQuestion` — the video still counts it, tells it when it leaves the screen so it can stop its microphone, and holds Finish while its answer is still on its way. See the [interactive video guide](https://github.com/intellectif/learning-kit/blob/main/docs/interactive-video.md).
|
|
76
|
+
- **AI help for learners** — "Explain my answer" after grading and "Get a hint" before submit, in `<MultipleChoice>`, `<FillInTheBlanks>`, `<GapSelect>` and `<Dictation>` (explanations only), through ports **you** supply with `<LkAiProvider>` or an `ai` prop (also on `<ActivitySequence>` and `<InteractiveVideo>`). The SDK never calls a model or holds a key: it builds the facts your model is given, refuses an explanation that contradicts the grade and a hint that contains the answer, marks everything a model wrote, and drops a late answer. Never in `exam`. See the [AI guide](https://github.com/intellectif/learning-kit/blob/main/docs/ai.md).
|
|
76
77
|
- **`<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
78
|
- **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
79
|
- **`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 +92,7 @@ export function Demo() {
|
|
|
91
92
|
- **`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
93
|
- **`<ThemeProvider>` + `defaults.css`** — `--lk-*` design-token system; automatic dark mode via `prefers-color-scheme` (SSR-safe with `useSyncExternalStore`).
|
|
93
94
|
- **`createTailwindTheme(theme)`** — optional Tailwind interop; consume the SDK palette from your own utilities.
|
|
94
|
-
- **`<LkIntlProvider>`** — all
|
|
95
|
+
- **`<LkIntlProvider>`** — all 179 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
96
|
- **WCAG 2.2 AA** — axe-clean unit + Playwright e2e tests; full keyboard operability; numerically-verified contrast.
|
|
96
97
|
- **RSC-compatible** — every component carries `'use client'` and hydrates inside a React Server Component tree.
|
|
97
98
|
|
|
@@ -114,6 +115,7 @@ export function Demo() {
|
|
|
114
115
|
| `@intellectif/lk-react/hooks/useActivityState` | Lifecycle + timing |
|
|
115
116
|
| `@intellectif/lk-react/hooks/useSpeechRecorder` | Microphone capture to 16 kHz mono WAV, and `CAPTURE_PROCESSOR_SOURCE` for a self-hosted worklet |
|
|
116
117
|
| `@intellectif/lk-react/hooks/useXAPI` | LRS delivery (retry, never-throws) |
|
|
118
|
+
| `@intellectif/lk-react/ai/LkAiProvider` | `<LkAiProvider>`, `useLearnerAi`, and the `LearnerAi` type |
|
|
117
119
|
| `@intellectif/lk-react/i18n/LkIntlProvider` | `<LkIntlProvider>`, `useLkStrings`, `useLkDirection`, `DEFAULT_STRINGS`, `mergeStrings`, `directionForLocale` |
|
|
118
120
|
| `@intellectif/lk-react/theme/ThemeProvider` | `<ThemeProvider>`, `darkTheme`, `useTheme`, `createTailwindTheme` |
|
|
119
121
|
| `@intellectif/lk-react/theme/defaults.css` | Tokens (required) |
|
|
@@ -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-
|
|
2
|
+
import { f as Renderable, e as RenderMode, H as HtmlSanitizer, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from './strings-PCYKWCwd.js';
|
|
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-
|
|
2
|
+
import { f as Renderable, e as RenderMode, H as HtmlSanitizer, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from './strings-BOPKhnS-.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Payload delivered when the learner submits a written response. Grading is
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var chunkZDYNAWDZ_cjs = require('../chunk-ZDYNAWDZ.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "LkAiProvider", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkZDYNAWDZ_cjs.LkAiProvider; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "useLearnerAi", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return chunkZDYNAWDZ_cjs.useLearnerAi; }
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=LkAiProvider.cjs.map
|
|
17
|
+
//# sourceMappingURL=LkAiProvider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"LkAiProvider.cjs"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AiExplanationRequest, AiTextResult, AiHintRequest } from '@intellectif/lk-core';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The model a host runs for learners, as the components call it. The SDK never
|
|
6
|
+
* calls a model, holds a key or writes a prompt: each port is the host's
|
|
7
|
+
* function — usually a request to its own server, which holds the key and the
|
|
8
|
+
* prompt and chooses the model.
|
|
9
|
+
*
|
|
10
|
+
* A port is called only when the learner asks — a button, never on render —
|
|
11
|
+
* and gets an `AbortSignal` that fires when the answer it was asked about goes
|
|
12
|
+
* away. Whatever it resolves to is checked before a learner sees it: see
|
|
13
|
+
* `checkAiExplanation` and `checkAiHint` in lk-core. A port that rejects, or
|
|
14
|
+
* resolves to something refused, costs the learner the help, never the
|
|
15
|
+
* question.
|
|
16
|
+
*
|
|
17
|
+
* Leave a port out to switch that feature off. Nothing AI renders in `exam`,
|
|
18
|
+
* whatever is passed.
|
|
19
|
+
*/
|
|
20
|
+
interface LearnerAi {
|
|
21
|
+
/** Explains a graded answer. */
|
|
22
|
+
explain?: (request: AiExplanationRequest, options: {
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
}) => Promise<AiTextResult>;
|
|
25
|
+
/** Writes the next hint for an answer not yet submitted. */
|
|
26
|
+
hint?: (request: AiHintRequest, options: {
|
|
27
|
+
signal: AbortSignal;
|
|
28
|
+
}) => Promise<AiTextResult>;
|
|
29
|
+
/** The most hints a learner can ask for on one question. Default 3, at most 10. */
|
|
30
|
+
maxHints?: number;
|
|
31
|
+
/**
|
|
32
|
+
* The language to write explanations and hints in — the learner's own,
|
|
33
|
+
* which in a language course need not be the item's. Defaults to the
|
|
34
|
+
* component's `locale`.
|
|
35
|
+
*/
|
|
36
|
+
learnerLocale?: string;
|
|
37
|
+
}
|
|
38
|
+
interface LkAiProviderProps {
|
|
39
|
+
ai: LearnerAi;
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Supplies the host's AI ports to every activity beneath, as `LkIntlProvider`
|
|
44
|
+
* supplies strings. A component's own `ai` prop wins over it, whole.
|
|
45
|
+
*
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <LkAiProvider ai={{
|
|
48
|
+
* explain: (request, { signal }) => api.explain(request, signal),
|
|
49
|
+
* hint: (request, { signal }) => api.hint(request, signal),
|
|
50
|
+
* learnerLocale: learner.language,
|
|
51
|
+
* }}>
|
|
52
|
+
* <ActivitySequence … />
|
|
53
|
+
* </LkAiProvider>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function LkAiProvider({ ai, children }: LkAiProviderProps): React.JSX.Element;
|
|
57
|
+
/** The ports in force: a component's own, else the provider's, else none. */
|
|
58
|
+
declare function useLearnerAi(override?: LearnerAi): LearnerAi | undefined;
|
|
59
|
+
|
|
60
|
+
export { type LearnerAi, LkAiProvider, type LkAiProviderProps, useLearnerAi };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AiExplanationRequest, AiTextResult, AiHintRequest } from '@intellectif/lk-core';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The model a host runs for learners, as the components call it. The SDK never
|
|
6
|
+
* calls a model, holds a key or writes a prompt: each port is the host's
|
|
7
|
+
* function — usually a request to its own server, which holds the key and the
|
|
8
|
+
* prompt and chooses the model.
|
|
9
|
+
*
|
|
10
|
+
* A port is called only when the learner asks — a button, never on render —
|
|
11
|
+
* and gets an `AbortSignal` that fires when the answer it was asked about goes
|
|
12
|
+
* away. Whatever it resolves to is checked before a learner sees it: see
|
|
13
|
+
* `checkAiExplanation` and `checkAiHint` in lk-core. A port that rejects, or
|
|
14
|
+
* resolves to something refused, costs the learner the help, never the
|
|
15
|
+
* question.
|
|
16
|
+
*
|
|
17
|
+
* Leave a port out to switch that feature off. Nothing AI renders in `exam`,
|
|
18
|
+
* whatever is passed.
|
|
19
|
+
*/
|
|
20
|
+
interface LearnerAi {
|
|
21
|
+
/** Explains a graded answer. */
|
|
22
|
+
explain?: (request: AiExplanationRequest, options: {
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
}) => Promise<AiTextResult>;
|
|
25
|
+
/** Writes the next hint for an answer not yet submitted. */
|
|
26
|
+
hint?: (request: AiHintRequest, options: {
|
|
27
|
+
signal: AbortSignal;
|
|
28
|
+
}) => Promise<AiTextResult>;
|
|
29
|
+
/** The most hints a learner can ask for on one question. Default 3, at most 10. */
|
|
30
|
+
maxHints?: number;
|
|
31
|
+
/**
|
|
32
|
+
* The language to write explanations and hints in — the learner's own,
|
|
33
|
+
* which in a language course need not be the item's. Defaults to the
|
|
34
|
+
* component's `locale`.
|
|
35
|
+
*/
|
|
36
|
+
learnerLocale?: string;
|
|
37
|
+
}
|
|
38
|
+
interface LkAiProviderProps {
|
|
39
|
+
ai: LearnerAi;
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Supplies the host's AI ports to every activity beneath, as `LkIntlProvider`
|
|
44
|
+
* supplies strings. A component's own `ai` prop wins over it, whole.
|
|
45
|
+
*
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <LkAiProvider ai={{
|
|
48
|
+
* explain: (request, { signal }) => api.explain(request, signal),
|
|
49
|
+
* hint: (request, { signal }) => api.hint(request, signal),
|
|
50
|
+
* learnerLocale: learner.language,
|
|
51
|
+
* }}>
|
|
52
|
+
* <ActivitySequence … />
|
|
53
|
+
* </LkAiProvider>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
declare function LkAiProvider({ ai, children }: LkAiProviderProps): React.JSX.Element;
|
|
57
|
+
/** The ports in force: a component's own, else the provider's, else none. */
|
|
58
|
+
declare function useLearnerAi(override?: LearnerAi): LearnerAi | undefined;
|
|
59
|
+
|
|
60
|
+
export { type LearnerAi, LkAiProvider, type LkAiProviderProps, useLearnerAi };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"LkAiProvider.js"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var chunkL7WY5YFQ_cjs = require('./chunk-L7WY5YFQ.cjs');
|
|
5
|
+
var chunkAHGB5HH6_cjs = require('./chunk-AHGB5HH6.cjs');
|
|
6
6
|
var react = require('react');
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
|
|
@@ -19,7 +19,7 @@ function StimulusPanel({
|
|
|
19
19
|
strings
|
|
20
20
|
}) {
|
|
21
21
|
const titleId = react.useId();
|
|
22
|
-
const s =
|
|
22
|
+
const s = chunkAHGB5HH6_cjs.useLkStrings(strings);
|
|
23
23
|
const bodyHtml = react.useMemo(() => {
|
|
24
24
|
if (sanitizeHtml === void 0 || typeof stimulus.bodyHtml !== "string") {
|
|
25
25
|
return null;
|
|
@@ -33,7 +33,7 @@ function StimulusPanel({
|
|
|
33
33
|
stimulus.title !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-stimulus-title", id: titleId, ...contentLang, children: stimulus.title }) : null,
|
|
34
34
|
rangeText !== null ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lk-stimulus-range", children: rangeText }) : null,
|
|
35
35
|
stimulus.media !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
36
|
-
|
|
36
|
+
chunkL7WY5YFQ_cjs.ActivityMedia,
|
|
37
37
|
{
|
|
38
38
|
media: stimulus.media,
|
|
39
39
|
...renderMode !== void 0 ? { renderMode } : {},
|
|
@@ -59,5 +59,5 @@ function StimulusPanel({
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
exports.StimulusPanel = StimulusPanel;
|
|
62
|
-
//# sourceMappingURL=chunk-
|
|
63
|
-
//# sourceMappingURL=chunk-
|
|
62
|
+
//# sourceMappingURL=chunk-3FBBP5QR.cjs.map
|
|
63
|
+
//# sourceMappingURL=chunk-3FBBP5QR.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/StimulusPanel/StimulusPanel.tsx"],"names":["useId","useLkStrings","useMemo","jsxs","jsx","ActivityMedia"],"mappings":";;;;;;;AAsDO,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA0C;AACxC,EAAA,MAAM,UAAUA,WAAA,EAAM;AACtB,EAAA,MAAM,CAAA,GAAIC,+BAAa,OAAO,CAAA;AAE9B,EAAA,MAAM,QAAA,GAAWC,cAAQ,MAAM;AAC7B,IAAA,IAAI,YAAA,KAAiB,MAAA,IAAa,OAAO,QAAA,CAAS,aAAa,QAAA,EAAU;AACvE,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,YAAA,CAAa,SAAS,QAAQ,CAAA;AAAA,EACvC,CAAA,EAAG,CAAC,QAAA,CAAS,QAAA,EAAU,YAAY,CAAC,CAAA;AAEpC,EAAA,MAAM,SAAA,GAAY,UAAU,MAAA,GAAY,IAAA,GAAO,EAAE,aAAA,CAAc,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,IAAI,CAAA;AAEtF,EAAA,MAAM,MAAA,GACJ,QAAA,CAAS,KAAA,KAAU,MAAA,GACf,EAAE,iBAAA,EAAmB,OAAA,EAAQ,GAC7B,EAAE,YAAA,EAAc,CAAA,CAAE,YAAA,CAAa,QAAA,CAAS,IAAI,CAAA,EAAE;AASpD,EAAA,MAAM,WAAA,GAAc,SAAS,MAAA,KAAW,MAAA,GAAY,EAAE,IAAA,EAAM,QAAA,CAAS,MAAA,EAAO,GAAI,EAAC;AAEjF,EAAA,uBACEC,eAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,aAAA,EAAc,WAAA,EAAW,SAAS,IAAA,EAAM,IAAA,EAAM,MAAA,EAAS,GAAG,MAAA,EAC1E,QAAA,EAAA;AAAA,IAAA,QAAA,CAAS,KAAA,KAAU,MAAA,mBAClBC,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mBAAA,EAAoB,EAAA,EAAI,OAAA,EAAU,GAAG,WAAA,EAC/C,QAAA,EAAA,QAAA,CAAS,KAAA,EACZ,CAAA,GACE,IAAA;AAAA,IACH,cAAc,IAAA,mBAAOA,cAAA,CAAC,OAAE,SAAA,EAAU,mBAAA,EAAqB,qBAAU,CAAA,GAAO,IAAA;AAAA,IACxE,QAAA,CAAS,UAAU,MAAA,mBAClBA,cAAA;AAAA,MAACC,+BAAA;AAAA,MAAA;AAAA,QACC,OAAO,QAAA,CAAS,KAAA;AAAA,QACf,GAAI,UAAA,KAAe,MAAA,GAAY,EAAE,UAAA,KAAe,EAAC;AAAA,QACjD,GAAI,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,KAAgB,EAAC;AAAA,QACnD,GAAI,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,KAAiB,EAAC;AAAA,QACrD,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY,EAAC;AAAA,QAC3C,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,KAAkB,EAAC;AAAA,QACvD,GAAI,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,KAAa,EAAC;AAAA,QAC7C,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,KAAW;AAAC;AAAA,KAC5C,GACE,IAAA;AAAA,IACH,aAAa,IAAA,mBACZD,cAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,kBAAA;AAAA,QACV,aAAA,EAAY,MAAA;AAAA,QACX,GAAG,WAAA;AAAA,QAEJ,uBAAA,EAAyB,EAAE,MAAA,EAAQ,QAAA;AAAS;AAAA,KAC9C,GACE,QAAA,CAAS,IAAA,KAAS,MAAA,kCACnB,KAAA,EAAA,EAAI,SAAA,EAAU,kBAAA,EAAmB,aAAA,EAAY,MAAA,EAAQ,GAAG,WAAA,EACtD,QAAA,EAAA,QAAA,CAAS,MACZ,CAAA,GACE,IAAA;AAAA,IACH,QAAA,CAAS,WAAA,KAAgB,MAAA,mBACxBA,cAAA,CAAC,OAAE,SAAA,EAAU,yBAAA,EAA2B,GAAG,WAAA,EACzC,QAAA,kBAAAA,cAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,QAAA,CAAS,WAAA,EAAY,GAC9B,CAAA,GACE;AAAA,GAAA,EACN,CAAA;AAEJ","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/StimulusPanel/StimulusPanel.tsx"],"names":["useId","useLkStrings","useMemo","jsxs","jsx","ActivityMedia"],"mappings":"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","file":"chunk-3FBBP5QR.cjs","sourcesContent":["'use client';\n\nimport type { InteractionEvent, Stimulus } from '@intellectif/lk-core';\nimport { useId, useMemo } from 'react';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport type { LkStringsOverride } from '../../i18n/strings.js';\nimport { ActivityMedia } from '../shared/ActivityMedia.js';\nimport type {\n HtmlSanitizer,\n MediaBudgetBinding,\n MediaTransportStrings,\n RenderMode,\n} from '../types.js';\n\nexport interface StimulusPanelProps {\n stimulus: Stimulus;\n /**\n * 1-based presented positions of the first and last question this material\n * serves, rendered as \"Questions 3–8\" so a learner knows how far the\n * passage carries.\n */\n range?: { first: number; last: number };\n /** Renders `stimulus.bodyHtml` when provided. See `HtmlSanitizer`. */\n sanitizeHtml?: HtmlSanitizer;\n locale?: string;\n /**\n * Forwarded to the stimulus's own media. `review` keeps the browser's control\n * bar even under an enforcing policy — a graded paper cannot be changed by\n * listening again.\n */\n renderMode?: RenderMode;\n /**\n * Binds this group's recording to a play budget the consumer persists. One\n * recording serves every question in the group, so the key is derived from\n * the ENTRY rather than the slot — see `stimulusMediaKey()` in lk-core.\n */\n mediaBudget?: MediaBudgetBinding;\n /** Translations for the audio transport chrome. */\n mediaStrings?: Partial<MediaTransportStrings>;\n onInteraction?: (event: InteractionEvent) => void;\n disabled?: boolean;\n /** Overrides the SDK's chrome text for this panel. See {@link LkIntlProvider}. */\n strings?: LkStringsOverride;\n}\n\n/**\n * Presents a shared stimulus — the passage, recording or image an item group's\n * questions refer to. A landmark region named by its title (or by its kind),\n * so a screen-reader user can jump back to the material from any question.\n *\n * Rich text follows the SDK-wide rule: `bodyHtml` is rendered only through a\n * caller-supplied sanitiser, and the plain `body` is the fallback — which the\n * schema guarantees exists whenever `bodyHtml` does.\n */\nexport function StimulusPanel({\n stimulus,\n range,\n sanitizeHtml,\n locale,\n renderMode,\n mediaBudget,\n mediaStrings,\n onInteraction,\n disabled,\n strings,\n}: StimulusPanelProps): React.JSX.Element {\n const titleId = useId();\n const s = useLkStrings(strings);\n\n const bodyHtml = useMemo(() => {\n if (sanitizeHtml === undefined || typeof stimulus.bodyHtml !== 'string') {\n return null;\n }\n return sanitizeHtml(stimulus.bodyHtml);\n }, [stimulus.bodyHtml, sanitizeHtml]);\n\n const rangeText = range === undefined ? null : s.stimulusRange(range.first, range.last);\n\n const naming =\n stimulus.title !== undefined\n ? { 'aria-labelledby': titleId }\n : { 'aria-label': s.stimulusKind[stimulus.kind] };\n\n // The AUTHORED parts carry the stimulus language; the SDK's own chrome does\n // not. Declaring `stimulus.locale` on the whole region made a screen reader\n // read \"Recording\" and \"Questions 3–5\" — English strings this package ships\n // — in the passage's voice, so a Spanish listening panel announced its own\n // name and the only orientation text in it with Spanish phonetics\n // (WCAG 3.1.2 Language of Parts). Scope the declaration to the content it\n // actually describes.\n const contentLang = stimulus.locale !== undefined ? { lang: stimulus.locale } : {};\n\n return (\n <section className=\"lk-stimulus\" data-kind={stimulus.kind} lang={locale} {...naming}>\n {stimulus.title !== undefined ? (\n <p className=\"lk-stimulus-title\" id={titleId} {...contentLang}>\n {stimulus.title}\n </p>\n ) : null}\n {rangeText !== null ? <p className=\"lk-stimulus-range\">{rangeText}</p> : null}\n {stimulus.media !== undefined ? (\n <ActivityMedia\n media={stimulus.media}\n {...(renderMode !== undefined ? { renderMode } : {})}\n {...(mediaBudget !== undefined ? { mediaBudget } : {})}\n {...(mediaStrings !== undefined ? { mediaStrings } : {})}\n {...(strings !== undefined ? { strings } : {})}\n {...(onInteraction !== undefined ? { onInteraction } : {})}\n {...(disabled !== undefined ? { disabled } : {})}\n {...(locale !== undefined ? { locale } : {})}\n />\n ) : null}\n {bodyHtml !== null ? (\n <div\n className=\"lk-stimulus-body\"\n data-format=\"html\"\n {...contentLang}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: rendered only through the caller-supplied HtmlSanitizer — the SDK never injects unsanitised markup\n dangerouslySetInnerHTML={{ __html: bodyHtml }}\n />\n ) : stimulus.body !== undefined ? (\n <div className=\"lk-stimulus-body\" data-format=\"text\" {...contentLang}>\n {stimulus.body}\n </div>\n ) : null}\n {stimulus.attribution !== undefined ? (\n <p className=\"lk-stimulus-attribution\" {...contentLang}>\n <cite>{stimulus.attribution}</cite>\n </p>\n ) : null}\n </section>\n );\n}\n"]}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
4
|
+
var chunkJKMBFHER_cjs = require('./chunk-JKMBFHER.cjs');
|
|
5
|
+
var chunkTI23GIFM_cjs = require('./chunk-TI23GIFM.cjs');
|
|
6
|
+
var chunkQA42VDTA_cjs = require('./chunk-QA42VDTA.cjs');
|
|
7
|
+
var chunkRZ52SEYV_cjs = require('./chunk-RZ52SEYV.cjs');
|
|
8
|
+
var chunkZDYNAWDZ_cjs = require('./chunk-ZDYNAWDZ.cjs');
|
|
9
|
+
var chunk6RRFH7C4_cjs = require('./chunk-6RRFH7C4.cjs');
|
|
10
|
+
var chunkBAKLJKFZ_cjs = require('./chunk-BAKLJKFZ.cjs');
|
|
11
|
+
var chunkAHGB5HH6_cjs = require('./chunk-AHGB5HH6.cjs');
|
|
11
12
|
var lkCore = require('@intellectif/lk-core');
|
|
12
13
|
var react = require('react');
|
|
13
14
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -1218,13 +1219,14 @@ function Player(props) {
|
|
|
1218
1219
|
theme,
|
|
1219
1220
|
sanitizeHtml
|
|
1220
1221
|
} = props;
|
|
1221
|
-
const strings =
|
|
1222
|
+
const strings = chunkAHGB5HH6_cjs.useLkStrings(props.strings);
|
|
1223
|
+
const aiInForce = chunkZDYNAWDZ_cjs.useLearnerAi(props.ai);
|
|
1222
1224
|
const group = react.useRef(props.group).current;
|
|
1223
1225
|
const timeline = group.timeline ?? { cues: [] };
|
|
1224
1226
|
const media = group.stimulus.media;
|
|
1225
1227
|
const chapters = timeline.chapters ?? [];
|
|
1226
1228
|
const devError = react.useMemo(() => {
|
|
1227
|
-
if (!
|
|
1229
|
+
if (!chunkBAKLJKFZ_cjs.isDevelopment()) {
|
|
1228
1230
|
return null;
|
|
1229
1231
|
}
|
|
1230
1232
|
if (group.timeline === void 0) {
|
|
@@ -2021,7 +2023,7 @@ function Player(props) {
|
|
|
2021
2023
|
if (reportTo.current.renderMode !== "review") {
|
|
2022
2024
|
return false;
|
|
2023
2025
|
}
|
|
2024
|
-
if (
|
|
2026
|
+
if (chunkBAKLJKFZ_cjs.isDevelopment() && !warned.has(call)) {
|
|
2025
2027
|
warned.add(call);
|
|
2026
2028
|
console.warn(
|
|
2027
2029
|
`InteractiveVideo: \`${call}()\` was called for question "${slotId}" in renderMode "review", where nothing is submittable. It was ignored.`
|
|
@@ -2112,6 +2114,7 @@ function Player(props) {
|
|
|
2112
2114
|
defaultSubmitted: submitted.has(slot.slotId),
|
|
2113
2115
|
...outcome !== void 0 ? { outcome } : {},
|
|
2114
2116
|
portalContainer,
|
|
2117
|
+
...aiInForce !== void 0 && renderMode !== "exam" ? { ai: aiInForce } : {},
|
|
2115
2118
|
...callsFor(place)
|
|
2116
2119
|
};
|
|
2117
2120
|
};
|
|
@@ -2129,12 +2132,13 @@ function Player(props) {
|
|
|
2129
2132
|
...onInteraction !== void 0 ? { onInteraction } : {},
|
|
2130
2133
|
...sanitizeHtml !== void 0 ? { sanitizeHtml } : {},
|
|
2131
2134
|
...props.strings !== void 0 ? { strings: props.strings } : {},
|
|
2135
|
+
...props.ai !== void 0 ? { ai: props.ai } : {},
|
|
2132
2136
|
...locale !== void 0 ? { locale } : {}
|
|
2133
2137
|
};
|
|
2134
2138
|
switch (activity.type) {
|
|
2135
2139
|
case "multiple-choice":
|
|
2136
2140
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2137
|
-
|
|
2141
|
+
chunkJKMBFHER_cjs.MultipleChoice,
|
|
2138
2142
|
{
|
|
2139
2143
|
data: activity,
|
|
2140
2144
|
...common,
|
|
@@ -2142,10 +2146,10 @@ function Player(props) {
|
|
|
2142
2146
|
}
|
|
2143
2147
|
);
|
|
2144
2148
|
case "fill-in-the-blanks":
|
|
2145
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2149
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkTI23GIFM_cjs.FillInTheBlanks, { data: activity, ...common });
|
|
2146
2150
|
case "gap-select":
|
|
2147
2151
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2148
|
-
|
|
2152
|
+
chunkQA42VDTA_cjs.GapSelect,
|
|
2149
2153
|
{
|
|
2150
2154
|
data: activity,
|
|
2151
2155
|
...common,
|
|
@@ -2153,12 +2157,12 @@ function Player(props) {
|
|
|
2153
2157
|
}
|
|
2154
2158
|
);
|
|
2155
2159
|
case "dictation":
|
|
2156
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2160
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkRZ52SEYV_cjs.Dictation, { data: activity, ...common });
|
|
2157
2161
|
case "read-aloud": {
|
|
2158
2162
|
const binding = slotBindings.get(slot.slotId);
|
|
2159
2163
|
const assessment = props.assessments !== void 0 && Object.hasOwn(props.assessments, slot.slotId) ? props.assessments[slot.slotId] : void 0;
|
|
2160
2164
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2161
|
-
|
|
2165
|
+
chunk6RRFH7C4_cjs.ReadAloud,
|
|
2162
2166
|
{
|
|
2163
2167
|
data: activity,
|
|
2164
2168
|
...common,
|
|
@@ -2787,7 +2791,7 @@ function SlotQuestion({
|
|
|
2787
2791
|
...content
|
|
2788
2792
|
}) {
|
|
2789
2793
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2790
|
-
|
|
2794
|
+
chunkBAKLJKFZ_cjs.ActivityErrorBoundary,
|
|
2791
2795
|
{
|
|
2792
2796
|
...title !== void 0 ? { activityTitle: title } : {},
|
|
2793
2797
|
strings,
|
|
@@ -2822,7 +2826,7 @@ function QuestionPane({
|
|
|
2822
2826
|
if (!hidden) {
|
|
2823
2827
|
return;
|
|
2824
2828
|
}
|
|
2825
|
-
|
|
2829
|
+
chunk6RRFH7C4_cjs.stopCaptureGroup(captureGroup);
|
|
2826
2830
|
for (const media of ref.current?.querySelectorAll("audio, video") ?? []) {
|
|
2827
2831
|
const element = media;
|
|
2828
2832
|
if (!element.paused) {
|
|
@@ -2830,7 +2834,7 @@ function QuestionPane({
|
|
|
2830
2834
|
}
|
|
2831
2835
|
}
|
|
2832
2836
|
}, [hidden, captureGroup]);
|
|
2833
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: "lk-iv-question", hidden, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2837
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: "lk-iv-question", hidden, children: /* @__PURE__ */ jsxRuntime.jsx(chunk6RRFH7C4_cjs.SequenceSlotContext.Provider, { value: channel, children }) });
|
|
2834
2838
|
}
|
|
2835
2839
|
function bufferedAhead(video) {
|
|
2836
2840
|
const ranges = video.buffered;
|
|
@@ -2870,9 +2874,9 @@ function markerState(quizSlots, answered, renderMode, outcomes) {
|
|
|
2870
2874
|
return "unreached";
|
|
2871
2875
|
}
|
|
2872
2876
|
function InteractiveVideo2(props) {
|
|
2873
|
-
const strings =
|
|
2877
|
+
const strings = chunkAHGB5HH6_cjs.useLkStrings(props.strings);
|
|
2874
2878
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2875
|
-
|
|
2879
|
+
chunkBAKLJKFZ_cjs.ActivityErrorBoundary,
|
|
2876
2880
|
{
|
|
2877
2881
|
...props.group?.title !== void 0 ? { activityTitle: props.group.title } : {},
|
|
2878
2882
|
strings,
|
|
@@ -2883,5 +2887,5 @@ function InteractiveVideo2(props) {
|
|
|
2883
2887
|
|
|
2884
2888
|
exports.InteractiveVideo = InteractiveVideo2;
|
|
2885
2889
|
exports.resolveCaptionTracks = resolveCaptionTracks;
|
|
2886
|
-
//# sourceMappingURL=chunk-
|
|
2887
|
-
//# sourceMappingURL=chunk-
|
|
2890
|
+
//# sourceMappingURL=chunk-3TJSFPO4.cjs.map
|
|
2891
|
+
//# sourceMappingURL=chunk-3TJSFPO4.cjs.map
|