@intellectif/lk-react 16.1.1 → 17.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 +50 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n/strings.ts","../src/i18n/LkIntlProvider.tsx"],"names":[],"mappings":"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","file":"chunk-YRNEOBXA.js","sourcesContent":["import type { ReadAloudDimension, ReadAloudWordState, Stimulus } from '@intellectif/lk-core';\nimport type { CaptionSize } from '../components/InteractiveVideo/prefs.js';\nimport type { VideoShortcutAction } from '../components/InteractiveVideo/shortcuts.js';\nimport type { MediaTransportStrings } from '../components/types.js';\nimport type { SpeechRecorderError } from '../hooks/useSpeechRecorder.js';\n\n/**\n * Every string the SDK's own chrome renders.\n *\n * Until 0.8.1 these were literals, and `locale` set only the `lang` attribute —\n * so a learner sitting a Spanish paper read a Spanish passage inside an English\n * scaffold, and \"No plays remaining\" on a listening exam was untranslatable.\n * This is the whole surface, in one place, so a consumer can replace it.\n *\n * **Interpolation and plurals are functions, not format strings.** A message\n * like `\"Question {n} of {total}\"` needs a parser, and a parser needs plural\n * rules for every locale the SDK does not know. A function hands both problems\n * to the consumer, who has `Intl.PluralRules` and knows their own language:\n *\n * ```ts\n * questionProgress: (index, total) => `Pregunta ${index} de ${total}`,\n * wordCount: (n) => `${n} ${n === 1 ? 'palabra' : 'palabras'}`,\n * ```\n *\n * It also lets a translation reorder its arguments, which a positional token\n * cannot, and TypeScript checks the arity. No parser, no message catalogue\n * format, no runtime dependency.\n *\n * **What is deliberately NOT here: thrown errors.** Every `throw` in this\n * package is addressed to the developer who wired the component up, not to the\n * learner. Translating them would make them unsearchable and would put the one\n * audience who can act on them behind a translation. They stay English.\n */\nexport interface LkStrings {\n // ── Submission ─────────────────────────────────────────────────────────\n /** Multiple Choice submit button, and Written Response. */\n submit: string;\n /** Fill-in-the-Blanks in `practice`: the learner is checking their own work. */\n checkAnswers: string;\n /** Fill-in-the-Blanks in `exam`: nothing is checked on the client. */\n submitAnswers: string;\n\n // ── Outcome, announced after submit ────────────────────────────────────\n /**\n * The scored result, read by a screen reader on submit.\n *\n * `percent` is already rounded to a whole number. The authored overall\n * feedback is appended SEPARATELY by the component, so a translation of this\n * sentence never has to carry the author's words — the two were previously\n * concatenated into one literal, which made the score sentence untranslatable\n * without also touching authored content.\n */\n scoreAnnouncement: (percent: number, passed: boolean) => string;\n /** Prefix announced on submit, before the score sentence. */\n answerSubmitted: string;\n /** An answer submitted for grading that has none yet. Never rendered as 0%. */\n notGradedYet: string;\n /** An outcome that carries no grade and never will. */\n noGradeAvailable: string;\n\n // ── Feedback disclosure ────────────────────────────────────────────────\n showFeedback: string;\n hideFeedback: string;\n\n // ── Fill-in-the-Blanks ─────────────────────────────────────────────────\n /** Accessible name of a blank's input. `ordinal` is 1-based. */\n blankLabel: (ordinal: number) => string;\n\n // ── Gap select ────────────────────────────────────────────────────────────\n /** Accessible name of the selector for one gap in a Gap Select passage. */\n gapLabel: (ordinal: number) => string;\n /**\n * The empty first entry of a gap's selector — how a learner leaves a gap\n * alone, and how they take an answer back. Never a real choice.\n */\n gapPlaceholder: string;\n showHint: string;\n hideHint: string;\n\n // ── Written Response ───────────────────────────────────────────────────\n /**\n * Announced when an essay is handed in. Distinct from {@link LkStrings.awaitingGrade},\n * which is the `review`-mode state of a submission made earlier: this one\n * confirms the act, and is the only thing a learner hears at the moment they\n * commit work that nothing on the client will grade.\n */\n responseSubmitted: string;\n /** Live word counter. Needs the count for languages whose plural rules differ. */\n wordCount: (count: number) => string;\n /** The authored bounds, e.g. \"50–200 words\". `min` is 0 when unbounded below. */\n wordBounds: (min: number, max: number) => string;\n /** A rubric criterion the grader marked not applicable. */\n notApplicable: string;\n /** A returned grade flagged for a human to look at — learner-visible by design. */\n awaitingHumanReview: string;\n /** Submitted, no grade back yet. */\n awaitingGrade: string;\n /** The grader could not produce a grade. */\n couldNotBeGraded: string;\n\n // ── Sequence pager ─────────────────────────────────────────────────────\n previous: string;\n next: string;\n /** Progress label, also the question region's accessible name. `index` is 1-based. */\n questionProgress: (index: number, total: number) => string;\n /** Shown when no renderer is registered for an activity type. */\n unsupportedActivity: string;\n\n // ── Dictation ──────────────────────────────────────────────────────────\n /** Accessible name of the box the learner types the recording into. */\n dictationInputLabel: string;\n /** Accessible name of the group holding the recording. */\n dictationRecording: string;\n /** Accessible name of the group holding the slower recording, and its default `alt`. */\n dictationSlowRecording: string;\n /** The progressive-hint button, with how many transcript words are shown so far. */\n dictationRevealNextWord: (revealed: number, total: number) => string;\n /** Hides every revealed hint word again. */\n dictationResetHints: string;\n /** The solution toggle: shows the transcript after the attempt is marked. */\n showSolution: string;\n hideSolution: string;\n /** Accessible name of the revealed transcript. */\n dictationSolutionLabel: string;\n /** Accessible name of the word-by-word marked result. */\n dictationMarksLabel: string;\n /** Tells the learner the marks compare the normalised text, not what they typed. */\n dictationDiffNote: string;\n /**\n * The four sentences a screen reader hears for a marked word — the only\n * channel the marks have for assistive technology; the glyphs and the\n * character diff are decoration.\n */\n dictationWordCorrect: (word: string) => string;\n dictationWordWrong: (word: string, expected: string) => string;\n dictationWordMissing: (expected: string) => string;\n dictationWordExtra: (word: string) => string;\n /** The legend rows; the character-level marks reuse the same four. */\n dictationLegendCorrect: string;\n dictationLegendWrong: string;\n dictationLegendMissing: string;\n dictationLegendExtra: string;\n /** Marked result of an attempt with no words in it once punctuation and spacing are ignored, an empty one included. */\n dictationNothingTyped: string;\n /**\n * Appended to the score announcement, e.g. \"4 of 6 words correct.\" — a whole\n * sentence, because authored feedback may follow it.\n */\n dictationWordsSummary: (correct: number, total: number) => string;\n\n // ── Read aloud ─────────────────────────────────────────────────────────\n /** Accessible name of the group holding the model recording. */\n readAloudModelRecording: string;\n /** Accessible name of the group holding the slower model recording, and its default `alt`. */\n readAloudSlowRecording: string;\n /** Starts a take. */\n readAloudRecord: string;\n /** Ends the take in progress. */\n readAloudStop: string;\n /** Throws the take away so the learner can start over. */\n readAloudRerecord: string;\n /** Accessible name of the player for the take the learner just made. */\n readAloudYourRecording: string;\n /**\n * In place of the player for the learner's own take, and of the buttons that\n * play one word of it, when the page refuses to play it — most often a\n * Content-Security-Policy whose `media-src` does not allow `blob:`. Said\n * rather than left as controls that do nothing when pressed.\n */\n readAloudPlaybackUnavailable: string;\n /**\n * Live progress while recording. Whole seconds, not a `m:ss` clock: a\n * recording is bounded in seconds by the item, and a translation should not\n * have to reimplement a clock to change the word around it.\n *\n * Shown on screen and hidden from assistive technology: it changes every\n * second, and a screen reader that spoke each change would speak into the\n * take being assessed. The two sentences below are what is announced instead.\n */\n readAloudRecordingProgress: (seconds: number, maxSeconds: number) => string;\n /** Announced once when a capture begins. */\n readAloudRecordingStarted: string;\n /**\n * Announced once when a capture ends, by the learner or at its own bound.\n * Carries the length because the progress counter is not announced: a take\n * that reads back as \"20 of 20 seconds\" is one that stopped itself.\n */\n readAloudRecordingStopped: (seconds: number, maxSeconds: number) => string;\n /** How many takes are left. Called with 0 as well, so the wording is one translation's. */\n readAloudTakesRemaining: (remaining: number, max: number) => string;\n /** `exam` only: hands the item in with no recording at all, deliberately. */\n readAloudSubmitWithoutRecording: string;\n /** Pending, while the take travels to the application's storage. */\n readAloudUploading: string;\n /** The take never reached storage, so nothing was submitted. */\n readAloudUploadFailed: string;\n /** Retries whichever step just failed. */\n readAloudTryAgain: string;\n /** Pending, while the assessor judges the take. */\n readAloudAssessing: string;\n /** The binding stores recordings but judges none, so there is no feedback to show. */\n readAloudAssessmentUnavailable: string;\n /** The assessor found no speech, or too little of it, in the take. */\n readAloudNotHeard: string;\n /** The assessor produced no grade for any other reason. The code itself is never shown. */\n readAloudNotAssessed: string;\n /** The assessment could not be run at all — a failure of the call, not of the reading. */\n readAloudAssessmentFailed: string;\n /**\n * What went wrong with the microphone or with the take. One function rather\n * than five keys, so a translation keeps the five sentences together and the\n * SDK keeps one name for the concept.\n */\n readAloudRecorderError: (reason: SpeechRecorderError) => string;\n\n // ── Pronunciation feedback ─────────────────────────────────────────────\n /** Accessible name of the whole feedback region. */\n pronunciationFeedbackLabel: string;\n /** Name of one scored dimension, as a learner reads it. */\n pronunciationDimension: (dimension: ReadAloudDimension) => string;\n /** A dimension or a word the engine did not measure. NEVER rendered as 0%. */\n pronunciationNotAssessed: string;\n /** Accessible name of the word-by-word marks. */\n pronunciationWordsLabel: string;\n /** One legend row per marking state — the same four states the marks carry. */\n pronunciationLegend: (state: ReadAloudWordState) => string;\n /**\n * The four sentences a screen reader hears for a marked word: the only\n * channel the marks have for assistive technology, since the glyph and the\n * decoration are both hidden from it.\n */\n pronunciationWordCorrect: (word: string) => string;\n pronunciationWordMispronounced: (word: string) => string;\n pronunciationWordOmitted: (word: string) => string;\n pronunciationWordInserted: (word: string) => string;\n /** Opens one word's syllables, sounds and timings. */\n pronunciationWordDetails: (word: string) => string;\n pronunciationSyllables: string;\n pronunciationPhonemes: string;\n /** A syllable the engine also spelled out, e.g. `('ˈhæ', 'ha')`. */\n pronunciationSyllableSpelling: (syllable: string, grapheme: string) => string;\n /** A sound the engine named no symbol for; `ordinal` is 1-based. */\n pronunciationPhonemePosition: (ordinal: number) => string;\n /** Introduces the sounds the engine thought it heard in a sound's place. */\n pronunciationHeardAs: string;\n /** Plays one word out of the learner's own take. */\n pronunciationPlayWord: (word: string) => string;\n pronunciationBreakUnexpected: string;\n pronunciationBreakMissing: string;\n /** Shown only past the caller's own monotone threshold; the SDK sets none. */\n pronunciationMonotone: string;\n /** Names the alphabet the phoneme symbols are written in. */\n pronunciationIpaNote: string;\n\n // ── Interactive video ──────────────────────────────────────────────────\n // Play, pause, mute, volume, speed, the progress bar's name and the time\n // readout are the `media` strings below: the same controls, the same words.\n /** Jump buttons, e.g. \"Back 10 seconds\". */\n videoBack: (seconds: number) => string;\n videoForward: (seconds: number) => string;\n /** The centre button once the video has ended. */\n videoReplay: string;\n /** The time readout flips between elapsed and remaining; these name what a press shows next. */\n videoShowRemaining: string;\n videoShowElapsed: string;\n /** The captions button, named by what a press does. */\n videoCaptionsShow: string;\n videoCaptionsHide: string;\n /** In the captions menu when a caption file could not be read. */\n videoCaptionsFailed: string;\n /** The same, for the second language: the first line keeps working. */\n videoSecondaryCaptionsFailed: string;\n /** A speed in the speed menu, e.g. \"1.25×\". */\n videoSpeedValue: (rate: number) => string;\n videoSettings: string;\n videoCaptionLanguage: string;\n /** The captions page's item, and page, for a second caption line under the first. */\n videoSecondCaptionLanguage: string;\n /**\n * The captions row of the settings menu when two languages show, from the\n * tracks' own labels: \"English + Español\". A translation may order them as its\n * language reads, but the first argument is always the upper line.\n */\n videoCaptionPair: (primary: string, secondary: string) => string;\n /** Announced when Shift + C finds no other language to show. */\n videoNoSecondLanguage: string;\n videoCaptionSize: string;\n videoCaptionSizeValue: (size: CaptionSize) => string;\n videoCaptionBackground: string;\n videoKeyboardShortcuts: string;\n videoShortcutList: string;\n /** Closes the shortcut list. */\n videoClose: string;\n /** A setting's state in the settings menu. */\n videoOn: string;\n videoOff: string;\n /** What each row of the shortcut list does. */\n videoShortcut: (action: VideoShortcutAction) => string;\n /** The button that opens the panel below the video, and its two tabs. */\n videoPanel: string;\n videoContents: string;\n videoTranscript: string;\n videoTranscriptSearch: string;\n videoTranscriptNoMatch: string;\n videoPictureInPicture: string;\n videoFullscreen: string;\n videoExitFullscreen: string;\n /**\n * Why the video will not play, by `MediaError.code` (1 aborted, 2 network,\n * 3 decode, 4 source), with 0 for anything else.\n */\n videoError: (code: number) => string;\n videoTryAgain: string;\n /** A quiz with no title of its own. */\n videoQuiz: string;\n /** Where the learner is inside a quiz, e.g. \"Question 2 of 5\". */\n videoQuestionProgress: (index: number, total: number) => string;\n /** A step of the quiz's step indicator, for assistive technology. */\n videoQuestionStep: (index: number, answered: boolean) => string;\n videoNextQuestion: string;\n videoContinue: string;\n videoSkipQuiz: string;\n videoRewatch: string;\n /** Exam mode, once a question is submitted: saved, not graded. */\n videoAnswerSaved: string;\n /** The end card, while an answer is still being stored or graded: why Finish waits. */\n videoAnswerPending: string;\n videoRequired: string;\n /** A quiz's progress in the contents panel and on the end screen. */\n videoQuizProgress: (answered: number, total: number) => string;\n /** Announced when a quiz opens. */\n videoQuizOpened: (time: string, questions: number) => string;\n /** Announced when a seek stopped at a required quiz. */\n videoHeldAtQuiz: (time: string) => string;\n /** Announced when a seek stopped at the furthest point reached. */\n videoHeldAhead: string;\n videoEnded: string;\n /** Practice end screen: questions answered, and the score. */\n videoEndScore: (answered: number, total: number, percent: number) => string;\n /** Exam end screen: questions answered, no score. */\n videoEndAnswered: (answered: number, total: number) => string;\n videoWatchAgain: string;\n videoFinish: string;\n\n // ── Authoring preview ──────────────────────────────────────────────────\n /**\n * `<ActivityPreview>`, in place of a draft that still has something missing.\n * Author-facing, not learner-facing — but an editor is translated too.\n */\n previewIncomplete: string;\n /** `<ActivityPreview>`, in place of a draft with something wrong in it. */\n previewInvalid: string;\n\n // ── Embedded media ────────────────────────────────────────────────────────\n /**\n * Accessible name of a provider iframe whose author supplied no `alt`.\n * `MediaSchema` requires `alt` on an embed, so validated content never\n * reaches this — but `validateActivity` is opt-in, and a screen-reader\n * learner meeting an unvalidated one should not meet it in English.\n */\n embeddedMedia: string;\n\n // ── Shared stimulus ────────────────────────────────────────────────────\n /**\n * Accessible name of the stimulus region when the author gave it no title.\n * Keyed by `Stimulus['kind']`, because \"Recording\" and \"Passage\" do not share\n * a gender or an article in every language.\n */\n stimulusKind: Record<Stimulus['kind'], string>;\n /**\n * How far the material carries, e.g. \"Questions 3–8\". Called with equal\n * `first` and `last` for a single question, so a translation can choose its\n * own singular rather than receive a pre-pluralised English one.\n */\n stimulusRange: (first: number, last: number) => string;\n\n // ── Error boundary ─────────────────────────────────────────────────────\n /** Production fallback when an activity throws during render. */\n activityFailed: string;\n /** The same, when the activity's title is known. */\n activityFailedNamed: (title: string) => string;\n /** Production fallback when the activity has no title to name. */\n activityFailedUnnamed: string;\n\n // ── AI help ────────────────────────────────────────────────────────────\n /** The button that asks for an explanation of a graded answer. */\n aiExplain: string;\n /** The same button while the explanation is being written. */\n aiExplaining: string;\n /** The heading over an explanation, and its accessible name. */\n aiExplanation: string;\n /** When no explanation can be shown: the port failed, or its answer was refused. */\n aiExplanationUnavailable: string;\n /** The button that asks for a hint. */\n aiHint: string;\n /** The same button while the hint is being written. */\n aiHintLoading: string;\n /** The label before each hint. */\n aiHintNumber: (hintNumber: number) => string;\n /** The accessible name of the list of hints. */\n aiHints: string;\n /** When no hint can be shown: the port failed, or its hint gave the answer away. */\n aiHintUnavailable: string;\n /** In place of the hint button once every hint has been used. */\n aiNoMoreHints: string;\n /** Beneath every AI text: who wrote it. */\n aiNotice: string;\n\n // ── Audio transport ────────────────────────────────────────────────────\n /**\n * The listening-paper transport. Shipped in 0.8.0 as its own `mediaStrings`\n * prop, which still works — this is the same shape, reachable from the one\n * provider so a consumer does not wire two mechanisms.\n */\n media: MediaTransportStrings;\n}\n\n/** A partial override, nested one level for {@link LkStrings.media}. */\nexport type LkStringsOverride = Partial<Omit<LkStrings, 'media' | 'stimulusKind'>> & {\n media?: Partial<MediaTransportStrings>;\n stimulusKind?: Partial<Record<Stimulus['kind'], string>>;\n};\n\n/**\n * English defaults, byte-identical to what every component rendered before the\n * strings surface existed. Supplying no override changes nothing on screen.\n */\nexport const DEFAULT_STRINGS: LkStrings = {\n submit: 'Submit',\n checkAnswers: 'Check answers',\n submitAnswers: 'Submit answers',\n\n scoreAnnouncement: (percent, passed) =>\n `Score ${percent}%. ${passed ? 'Passed.' : 'Not passed.'}`,\n answerSubmitted: 'Answer submitted.',\n notGradedYet: 'Not graded yet.',\n noGradeAvailable: 'No grade available.',\n\n showFeedback: 'Show feedback',\n hideFeedback: 'Hide feedback',\n\n blankLabel: (ordinal) => `Fill in blank ${ordinal}`,\n\n gapLabel: (ordinal) => `Choose the answer for gap ${ordinal}`,\n gapPlaceholder: 'Choose…',\n showHint: 'Show hint',\n hideHint: 'Hide hint',\n\n responseSubmitted:\n 'Response submitted. It will be graded and your result will appear here later.',\n wordCount: (count) => `${count} ${count === 1 ? 'word' : 'words'}`,\n wordBounds: (min, max) => (min > 0 ? `${min}–${max} words` : `up to ${max} words`),\n notApplicable: 'Not applicable',\n awaitingHumanReview: 'This grade is awaiting review by a teacher.',\n awaitingGrade: 'Not graded yet. This response is waiting for its grade.',\n couldNotBeGraded: 'This response could not be graded.',\n\n previous: 'Previous',\n next: 'Next',\n questionProgress: (index, total) => `Question ${index} of ${total}`,\n unsupportedActivity: 'This activity type has no renderer. Supply one through the renderers prop.',\n\n dictationInputLabel: 'Type what you hear',\n dictationRecording: 'Recording',\n dictationSlowRecording: 'Slow recording',\n dictationRevealNextWord: (revealed, total) =>\n `Reveal the next word (${revealed} of ${total} shown)`,\n dictationResetHints: 'Reset hints',\n showSolution: 'Show solution',\n hideSolution: 'Hide solution',\n dictationSolutionLabel: 'Solution',\n dictationMarksLabel: 'Your answer, word by word',\n dictationDiffNote: 'Compared after ignoring case, punctuation and extra spaces.',\n dictationWordCorrect: (word) => `“${word}” is correct`,\n dictationWordWrong: (word, expected) => `“${word}” should be “${expected}”`,\n dictationWordMissing: (expected) => `“${expected}” is missing`,\n dictationWordExtra: (word) => `“${word}” is extra`,\n dictationLegendCorrect: 'Correct',\n dictationLegendWrong: 'Wrong',\n dictationLegendMissing: 'Missing',\n dictationLegendExtra: 'Extra',\n dictationNothingTyped: 'Nothing to compare: no words were entered.',\n dictationWordsSummary: (correct, total) =>\n `${correct} of ${total} ${total === 1 ? 'word' : 'words'} correct.`,\n\n readAloudModelRecording: 'Model recording',\n readAloudSlowRecording: 'Slow model recording',\n readAloudRecord: 'Record',\n readAloudStop: 'Stop recording',\n readAloudRerecord: 'Record again',\n readAloudYourRecording: 'Your recording',\n readAloudPlaybackUnavailable: 'Your recording cannot be played back on this page.',\n readAloudRecordingProgress: (seconds, maxSeconds) =>\n `Recording: ${seconds} of ${maxSeconds} seconds`,\n readAloudRecordingStarted: 'Recording started.',\n readAloudRecordingStopped: (seconds, maxSeconds) =>\n `Recording stopped. ${seconds} of ${maxSeconds} seconds recorded.`,\n readAloudTakesRemaining: (remaining, max) =>\n `${remaining} of ${max} recording${max === 1 ? '' : 's'} left`,\n readAloudSubmitWithoutRecording: 'Submit without recording',\n readAloudUploading: 'Sending your recording…',\n readAloudUploadFailed: 'Your recording could not be sent.',\n readAloudTryAgain: 'Try again',\n readAloudAssessing: 'Checking your pronunciation…',\n readAloudAssessmentUnavailable: 'Pronunciation feedback is not available for this activity.',\n readAloudNotHeard: 'We could not hear you. Record again somewhere quieter.',\n readAloudNotAssessed: 'This recording could not be assessed. Try recording it again.',\n readAloudAssessmentFailed: 'Your pronunciation could not be checked.',\n readAloudRecorderError: (reason) => {\n switch (reason) {\n case 'permission-denied':\n return 'This page is not allowed to use the microphone.';\n case 'no-device':\n return 'No microphone was found.';\n case 'unsupported':\n return 'This browser cannot record audio.';\n case 'too-short':\n return 'That recording was too short.';\n default:\n return 'The recording could not be made.';\n }\n },\n\n pronunciationFeedbackLabel: 'Pronunciation feedback',\n pronunciationDimension: (dimension) => {\n switch (dimension) {\n case 'accuracy':\n return 'Accuracy';\n case 'fluency':\n return 'Fluency';\n case 'completeness':\n return 'Completeness';\n default:\n return 'Intonation';\n }\n },\n pronunciationNotAssessed: 'Not assessed',\n pronunciationWordsLabel: 'Your reading, word by word',\n pronunciationLegend: (state) => {\n switch (state) {\n case 'correct':\n return 'Read correctly';\n case 'mispronounced':\n return 'Mispronounced';\n case 'omitted':\n return 'Not read';\n default:\n return 'Added';\n }\n },\n pronunciationWordCorrect: (word) => `“${word}” was read correctly`,\n pronunciationWordMispronounced: (word) => `“${word}” was mispronounced`,\n pronunciationWordOmitted: (word) => `“${word}” was not read`,\n pronunciationWordInserted: (word) => `“${word}” was added`,\n pronunciationWordDetails: (word) => `Details for “${word}”`,\n pronunciationSyllables: 'Syllables',\n pronunciationPhonemes: 'Sounds',\n pronunciationSyllableSpelling: (syllable, grapheme) => `${syllable} (spelled “${grapheme}”)`,\n pronunciationPhonemePosition: (ordinal) => `Sound ${ordinal}`,\n pronunciationHeardAs: 'Heard as',\n pronunciationPlayWord: (word) => `Play “${word}”`,\n pronunciationBreakUnexpected: 'There was an unexpected pause here.',\n pronunciationBreakMissing: 'A pause was expected here.',\n pronunciationMonotone: 'Your reading stayed on one note. Try varying your pitch.',\n pronunciationIpaNote: 'Sounds are written in the International Phonetic Alphabet.',\n videoBack: (seconds) => `Back ${seconds} seconds`,\n videoForward: (seconds) => `Forward ${seconds} seconds`,\n videoReplay: 'Replay',\n videoShowRemaining: 'Show time remaining',\n videoShowElapsed: 'Show time elapsed',\n videoCaptionsShow: 'Show captions',\n videoCaptionsHide: 'Hide captions',\n videoCaptionsFailed: 'Captions could not be loaded.',\n videoSecondaryCaptionsFailed: 'The second language could not be loaded.',\n videoSpeedValue: (rate) => (rate === 1 ? 'Normal' : `${rate}×`),\n videoSettings: 'Settings',\n videoCaptionLanguage: 'Captions',\n videoSecondCaptionLanguage: 'Second language',\n videoCaptionPair: (primary, secondary) => `${primary} + ${secondary}`,\n videoNoSecondLanguage: 'No second language for this video.',\n videoCaptionSize: 'Caption size',\n videoCaptionSizeValue: (size) =>\n size === 'small' ? 'Small' : size === 'large' ? 'Large' : 'Medium',\n videoCaptionBackground: 'Caption background',\n videoKeyboardShortcuts: 'Keyboard shortcuts',\n videoShortcutList: 'Shortcut list',\n videoClose: 'Close',\n videoOn: 'On',\n videoOff: 'Off',\n videoShortcut: (action) => {\n switch (action) {\n case 'play-pause':\n return 'Play or pause';\n case 'jump-10':\n return 'Back or forward 10 seconds';\n case 'jump-5':\n return 'Back or forward 5 seconds';\n case 'jump-1':\n return 'Back or forward 1 second';\n case 'frame':\n return 'Previous or next frame, while paused';\n case 'speed':\n return 'Slower or faster';\n case 'percent':\n return 'Jump to 0% – 90%';\n case 'start-end':\n return 'Start or end';\n case 'chapter':\n return 'Previous or next chapter or quiz';\n case 'mute':\n return 'Mute';\n case 'captions':\n return 'Captions';\n case 'secondary-captions':\n return 'Second caption language on/off';\n case 'transcript':\n return 'Transcript';\n case 'picture-in-picture':\n return 'Picture in picture';\n case 'fullscreen':\n return 'Fullscreen';\n default:\n return 'This list';\n }\n },\n videoPanel: 'Contents and transcript',\n videoContents: 'Contents',\n videoTranscript: 'Transcript',\n videoTranscriptSearch: 'Search the transcript',\n videoTranscriptNoMatch: 'No lines match.',\n videoPictureInPicture: 'Picture in picture',\n videoFullscreen: 'Fullscreen',\n videoExitFullscreen: 'Exit fullscreen',\n videoError: (code) =>\n code === 2\n ? 'The connection dropped while the video was loading.'\n : code === 3\n ? 'This video file could not be played.'\n : code === 4\n ? 'The video could not be loaded.'\n : 'The video stopped before it could play.',\n videoTryAgain: 'Try again',\n videoQuiz: 'Quiz',\n videoQuestionProgress: (index, total) => `Question ${index} of ${total}`,\n videoQuestionStep: (index, answered) => `Question ${index}${answered ? ', answered' : ''}`,\n videoNextQuestion: 'Next question',\n videoContinue: 'Continue video',\n videoSkipQuiz: 'Skip quiz',\n videoRewatch: 'Rewatch',\n videoAnswerSaved: 'Answer saved',\n videoAnswerPending: 'Saving your answer…',\n videoRequired: 'Required',\n videoQuizProgress: (answered, total) =>\n answered === total\n ? 'Answered'\n : answered === 0\n ? 'Not started'\n : `${answered} of ${total} answered`,\n videoQuizOpened: (time, questions) =>\n `Video paused. Quiz at ${time}, ${questions} question${questions === 1 ? '' : 's'}.`,\n videoHeldAtQuiz: (time) => `Finish the quiz at ${time} to continue.`,\n videoHeldAhead: 'You can rewind, but not skip ahead.',\n videoEnded: 'You reached the end',\n videoEndScore: (answered, total, percent) => `You answered ${answered} of ${total} · ${percent}%`,\n videoEndAnswered: (answered, total) => `You answered ${answered} of ${total} questions`,\n videoWatchAgain: 'Watch again',\n videoFinish: 'Finish',\n\n previewIncomplete: 'This activity is not finished yet, so it cannot be previewed.',\n previewInvalid: 'This activity has a problem to fix before it can be previewed.',\n\n embeddedMedia: 'Embedded media',\n\n stimulusKind: {\n text: 'Passage',\n audio: 'Recording',\n video: 'Video',\n image: 'Image',\n mixed: 'Material',\n },\n stimulusRange: (first, last) =>\n first === last ? `Question ${first}` : `Questions ${first}–${last}`,\n\n activityFailed: 'Activity failed to render',\n activityFailedNamed: (title) => `\"${title}\" could not be displayed.`,\n activityFailedUnnamed: 'This activity could not be displayed.',\n aiExplain: 'Explain my answer',\n aiExplaining: 'Explaining…',\n aiExplanation: 'Explanation',\n aiExplanationUnavailable: 'No explanation is available right now.',\n aiHint: 'Get a hint',\n aiHintLoading: 'Finding a hint…',\n aiHintNumber: (hintNumber) => `Hint ${hintNumber}`,\n aiHints: 'Hints',\n aiHintUnavailable: 'No hint is available right now.',\n aiNoMoreHints: 'No more hints for this question.',\n aiNotice: 'Written by AI. It can make mistakes.',\n\n media: {\n play: 'Play',\n pause: 'Pause',\n preparing: 'Preparing…',\n mute: 'Mute',\n unmute: 'Unmute',\n volume: 'Volume',\n speed: 'Playback speed',\n seek: 'Seek',\n timeValue: (elapsed, duration) => `${elapsed} of ${duration}`,\n playsRemaining: (remaining, max) =>\n `${remaining} of ${max} play${max === 1 ? '' : 's'} remaining`,\n noPlaysRemaining: 'No plays remaining',\n lastPlayConfirm: 'This is your last play. Start it now?',\n lastPlayStart: 'Start last play',\n lastPlayCancel: 'Not yet',\n seekBlocked: 'Rewinding is not available for this recording.',\n rateBlocked: 'Playback speed is fixed for this recording.',\n playFailed: 'The recording could not be started. Try again.',\n },\n};\n\n/**\n * Layers an override onto a base dictionary.\n *\n * Two levels deep and no further, because the shape is two levels deep. A\n * generic deep merge would silently accept a nested object where a function\n * belongs and fail at render instead of at the call site.\n */\nexport function mergeStrings(base: LkStrings, override?: LkStringsOverride): LkStrings {\n if (override === undefined) {\n return base;\n }\n const { media, stimulusKind, ...flat } = override;\n return {\n ...base,\n ...flat,\n stimulusKind: { ...base.stimulusKind, ...stimulusKind },\n media: { ...base.media, ...media },\n };\n}\n","'use client';\n\nimport { createContext, useContext, useMemo } from 'react';\nimport type { LkStrings, LkStringsOverride } from './strings.js';\nimport { DEFAULT_STRINGS, mergeStrings } from './strings.js';\n\nexport type { LkStrings, LkStringsOverride } from './strings.js';\nexport { DEFAULT_STRINGS, mergeStrings } from './strings.js';\n\n/** Writing direction of the surrounding UI. `auto` defers to the locale. */\nexport type LkDirection = 'ltr' | 'rtl' | 'auto';\n\ninterface LkIntlValue {\n strings: LkStrings;\n locale: string | undefined;\n direction: 'ltr' | 'rtl';\n}\n\nconst LkIntlContext = createContext<LkIntlValue | null>(null);\n\n/**\n * Locales written right-to-left, by language subtag.\n *\n * A short list rather than a dependency: these are the RTL scripts in living\n * use, and the set has not changed in decades. `Intl.Locale.textInfo` would be\n * better but is not available everywhere this package runs, and an explicit\n * `direction` prop overrides this in either direction anyway.\n */\nconst RTL_LANGUAGES = new Set(['ar', 'arc', 'dv', 'fa', 'he', 'ku', 'ps', 'sd', 'ug', 'ur', 'yi']);\n\n/** Resolves a BCP 47 tag to a writing direction. */\nexport function directionForLocale(locale: string | undefined): 'ltr' | 'rtl' {\n if (locale === undefined) {\n return 'ltr';\n }\n const language = locale.split('-')[0]?.toLowerCase() ?? '';\n return RTL_LANGUAGES.has(language) ? 'rtl' : 'ltr';\n}\n\nexport interface LkIntlProviderProps {\n /**\n * Replaces the SDK's own chrome text. Anything omitted keeps its English\n * default, so a partial translation degrades to mixed rather than to blank.\n *\n * A nested provider REPLACES the one above it rather than layering onto it —\n * as a nested `ThemeProvider` restarts from `defaultTheme`. To layer, use a\n * component's own `strings` prop, or compose with `mergeStrings`.\n */\n strings?: LkStringsOverride;\n /**\n * BCP 47 tag for the SDK's chrome — NOT for the authored content, which\n * carries its own `locale`. Sets `lang` on the wrapper so a screen reader\n * reads \"Question 3 of 10\" in the interface language rather than in the\n * language of the passage beside it (WCAG 3.1.2).\n */\n locale?: string;\n /**\n * Writing direction. Defaults to `auto`, which derives it from `locale`.\n * Set it explicitly when the surrounding application already manages `dir`\n * and you do not want a second element declaring one.\n */\n direction?: LkDirection;\n children: React.ReactNode;\n}\n\n/**\n * Supplies the SDK's chrome text and writing direction to everything beneath.\n *\n * Mirrors `ThemeProvider`: a provider for the whole tree, and a per-component\n * prop for the exceptions. The component prop wins, so a single activity can\n * be relabelled without a second provider.\n *\n * ```tsx\n * <LkIntlProvider locale=\"es\" strings={{\n * submit: 'Enviar',\n * checkAnswers: 'Comprobar respuestas',\n * questionProgress: (i, total) => `Pregunta ${i} de ${total}`,\n * wordCount: (n) => `${n} ${n === 1 ? 'palabra' : 'palabras'}`,\n * media: { noPlaysRemaining: 'No quedan reproducciones' },\n * }}>\n * <ActivitySequence … />\n * </LkIntlProvider>\n * ```\n *\n * The SDK ships **English only**. Bundling Spanish, Portuguese or Arabic would\n * mean shipping translations nobody in this repo can review, and a wrong\n * \"No plays remaining\" on a listening exam is worse than an English one that a\n * teacher can see is untranslated. The mechanism is the deliverable; the words\n * belong to whoever speaks the language.\n */\nexport function LkIntlProvider({\n strings,\n locale,\n direction = 'auto',\n children,\n}: LkIntlProviderProps): React.JSX.Element {\n const value = useMemo<LkIntlValue>(\n () => ({\n strings: mergeStrings(DEFAULT_STRINGS, strings),\n locale,\n direction: direction === 'auto' ? directionForLocale(locale) : direction,\n }),\n [strings, locale, direction],\n );\n\n // Declare `dir` only when something actually told us the direction. With no\n // locale and no explicit `direction`, writing dir=\"ltr\" would flip an RTL\n // host's own subtree back to left-to-right — the context value stays\n // concrete for `useLkDirection`; it is only the DOM declaration we withhold.\n const declared = direction === 'auto' && locale === undefined ? undefined : value.direction;\n\n return (\n <LkIntlContext.Provider value={value}>\n <div className=\"lk-intl\" lang={locale} dir={declared}>\n {children}\n </div>\n </LkIntlContext.Provider>\n );\n}\n\n/**\n * The strings in force, with an optional per-component override layered on top.\n *\n * Usable without a provider: every component calls this, and one rendered\n * standalone still needs its labels. Falling back to the English defaults is\n * what keeps `<MultipleChoice>` working with no setup at all.\n */\nexport function useLkStrings(override?: LkStringsOverride): LkStrings {\n const context = useContext(LkIntlContext);\n const base = context?.strings ?? DEFAULT_STRINGS;\n return useMemo(() => mergeStrings(base, override), [base, override]);\n}\n\n/** The direction in force. `ltr` with no provider. */\nexport function useLkDirection(): 'ltr' | 'rtl' {\n return useContext(LkIntlContext)?.direction ?? 'ltr';\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { DEFAULT_STRINGS } from './chunk-
|
|
2
|
+
import { DEFAULT_STRINGS } from './chunk-YRNEOBXA.js';
|
|
3
3
|
import { Component } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -46,5 +46,5 @@ var ActivityErrorBoundary = class extends Component {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
export { ANONYMOUS_ACTOR, ActivityErrorBoundary, isDevelopment, objectIdFor, randomSessionId };
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
50
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-YTGRXD23.js.map
|
|
50
|
+
//# sourceMappingURL=chunk-YTGRXD23.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/_internal.ts","../src/components/ActivityErrorBoundary.tsx"],"names":[],"mappings":";;;;;AA8BO,SAAS,aAAA,GAAyB;AACvC,EAAA,IAAI;AACF,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,YAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOO,IAAM,eAAA,GAA6B;AAAA,EACxC,UAAA,EAAY,OAAA;AAAA,EACZ,OAAA,EAAS,EAAE,QAAA,EAAU,6CAAA,EAA+C,MAAM,WAAA;AAC5E;AAGO,SAAS,YAAY,EAAA,EAAoB;AAC9C,EAAA,OAAO,CAAA,0BAAA,EAA6B,kBAAA,CAAmB,EAAE,CAAC,CAAA,CAAA;AAC5D;AAQO,SAAS,eAAA,GAA0B;AACxC,EAAA,MAAM,IAAK,UAAA,CAA0D,MAAA;AACrE,EAAA,IAAI,GAAG,UAAA,EAAY;AACjB,IAAA,OAAO,EAAE,UAAA,EAAW;AAAA,EACtB;AACA,EAAA,OAAO,KAAK,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,IAAA,CAAK,QAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACvF;ACrCO,IAAM,qBAAA,GAAN,cAAoC,SAAA,CAGzC;AAAA,EACA,KAAA,GAAoC,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,EAElD,OAAO,yBAAyB,KAAA,EAA0C;AACxE,IAAA,OAAO,EAAE,KAAA,EAAM;AAAA,EACjB;AAAA,EAEA,MAAA,GAAoB;AAClB,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,IAAA,CAAK,KAAA;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AAAA,IACpB;AAKA,IAAA,IAAI,eAAc,EAAG;AACnB,MAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,IAAA,EAAK,OAAA,EACR,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,QAAA,EAAA,CAAA,IAAA,CAAK,KAAA,CAAM,OAAA,IAAW,iBAAiB,cAAA,EAAe,CAAA;AAAA,wBAChE,GAAA,CAAC,KAAA,EAAA,EAAK,QAAA,EAAA,KAAA,CAAM,KAAA,IAAS,MAAM,OAAA,EAAQ;AAAA,OAAA,EACrC,CAAA;AAAA,IAEJ;AAEA,IAAA,uBACE,GAAA,CAAC,SAAI,IAAA,EAAK,OAAA,EACP,eAAK,KAAA,CAAM,aAAA,GAAA,CACP,KAAK,KAAA,CAAM,OAAA,IAAW,iBAAiB,mBAAA,CAAoB,IAAA,CAAK,MAAM,aAAa,CAAA,GAAA,CACnF,KAAK,KAAA,CAAM,OAAA,IAAW,iBAAiB,qBAAA,EAC9C,CAAA;AAAA,EAEJ;AACF","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/_internal.ts","../src/components/ActivityErrorBoundary.tsx"],"names":[],"mappings":";;;;;AA8BO,SAAS,aAAA,GAAyB;AACvC,EAAA,IAAI;AACF,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,YAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOO,IAAM,eAAA,GAA6B;AAAA,EACxC,UAAA,EAAY,OAAA;AAAA,EACZ,OAAA,EAAS,EAAE,QAAA,EAAU,6CAAA,EAA+C,MAAM,WAAA;AAC5E;AAGO,SAAS,YAAY,EAAA,EAAoB;AAC9C,EAAA,OAAO,CAAA,0BAAA,EAA6B,kBAAA,CAAmB,EAAE,CAAC,CAAA,CAAA;AAC5D;AAQO,SAAS,eAAA,GAA0B;AACxC,EAAA,MAAM,IAAK,UAAA,CAA0D,MAAA;AACrE,EAAA,IAAI,GAAG,UAAA,EAAY;AACjB,IAAA,OAAO,EAAE,UAAA,EAAW;AAAA,EACtB;AACA,EAAA,OAAO,KAAK,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,IAAA,CAAK,QAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACvF;ACrCO,IAAM,qBAAA,GAAN,cAAoC,SAAA,CAGzC;AAAA,EACA,KAAA,GAAoC,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,EAElD,OAAO,yBAAyB,KAAA,EAA0C;AACxE,IAAA,OAAO,EAAE,KAAA,EAAM;AAAA,EACjB;AAAA,EAEA,MAAA,GAAoB;AAClB,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,IAAA,CAAK,KAAA;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AAAA,IACpB;AAKA,IAAA,IAAI,eAAc,EAAG;AACnB,MAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,IAAA,EAAK,OAAA,EACR,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,QAAA,EAAA,CAAA,IAAA,CAAK,KAAA,CAAM,OAAA,IAAW,iBAAiB,cAAA,EAAe,CAAA;AAAA,wBAChE,GAAA,CAAC,KAAA,EAAA,EAAK,QAAA,EAAA,KAAA,CAAM,KAAA,IAAS,MAAM,OAAA,EAAQ;AAAA,OAAA,EACrC,CAAA;AAAA,IAEJ;AAEA,IAAA,uBACE,GAAA,CAAC,SAAI,IAAA,EAAK,OAAA,EACP,eAAK,KAAA,CAAM,aAAA,GAAA,CACP,KAAK,KAAA,CAAM,OAAA,IAAW,iBAAiB,mBAAA,CAAoB,IAAA,CAAK,MAAM,aAAa,CAAA,GAAA,CACnF,KAAK,KAAA,CAAM,OAAA,IAAW,iBAAiB,qBAAA,EAC9C,CAAA;AAAA,EAEJ;AACF","file":"chunk-YTGRXD23.js","sourcesContent":["import type { XAPIActor } from '@intellectif/lk-core';\n\n/**\n * The one global this module reads by name. Declared here, not globally: this\n * package compiles without Node's types on purpose, and nothing else in it may\n * come to rely on `process`.\n */\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Whether this is anything other than a production build — the one answer\n * every development check and the error boundary's stack trace read.\n *\n * **The literal `process.env.NODE_ENV`, spelled exactly so.** It is the one\n * expression bundlers replace at build time — Vite, webpack, esbuild, Next.js\n * and Rollup's replace plugin all substitute it — and a browser has no\n * `process` to read at run time. The reading this replaces,\n * `globalThis.process?.env?.NODE_ENV`, is not that expression, so no bundler\n * touched it, and in a browser it found no `process` and answered\n * \"development\" in every production app: learners were shown a stack trace\n * where each component's production fallback belonged. Tests running in Node\n * never saw it, because Node has a `process`.\n *\n * This package's own build must leave the literal in its output, for the\n * consumer's bundler to replace. A library build that substituted it would\n * freeze every consumer into whichever mode the library was built in.\n *\n * The `try` covers code that reaches a runtime unbundled, with no `process`\n * at all: that is development, as it always was.\n */\nexport function isDevelopment(): boolean {\n try {\n return process.env.NODE_ENV !== 'production';\n } catch {\n return true;\n }\n}\n\n/**\n * Activity components cannot know the learner's identity (Req 3.1 fixes the\n * prop set). They emit a structurally-valid statement with this anonymous\n * actor; real identity is applied by the useXAPI/LRS layer (XAPIConfig.actor).\n */\nexport const ANONYMOUS_ACTOR: XAPIActor = {\n objectType: 'Agent',\n account: { homePage: 'https://github.com/intellectif/learning-kit', name: 'anonymous' },\n};\n\n/** `data.id` is not an IRI; xAPI object ids must be. Wrap it as a URN. */\nexport function objectIdFor(id: string): string {\n return `urn:learning-kit:activity:${encodeURIComponent(id)}`;\n}\n\n/**\n * Random per-mount session id for the shuffle seed. `crypto.randomUUID` is\n * unavailable outside secure contexts (plain-http LAN/staging hosts), so a\n * Math.random fallback keeps the component from crashing there — the seed\n * only randomises presentation order, so cryptographic strength is not needed.\n */\nexport function randomSessionId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `s-${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;\n}\n","'use client';\n\nimport { Component, type ReactNode } from 'react';\nimport type { LkStrings } from '../i18n/strings.js';\nimport { DEFAULT_STRINGS } from '../i18n/strings.js';\nimport { isDevelopment } from './_internal.js';\n\nexport interface ActivityErrorBoundaryProps {\n /** Shown in the production fallback when a render error occurs. */\n activityTitle?: string;\n /**\n * Chrome text. A class component cannot call `useLkStrings`, so the public\n * wrapper reads the hook and hands the resolved dictionary down.\n */\n strings?: LkStrings;\n children: ReactNode;\n}\n\ninterface ActivityErrorBoundaryState {\n error: Error | null;\n}\n\n/**\n * Catches render errors in an activity subtree. In development it renders the\n * full error stack to aid debugging; in production it renders an accessible,\n * generic fallback (optionally naming the activity) so a single broken\n * activity never crashes the host application.\n */\nexport class ActivityErrorBoundary extends Component<\n ActivityErrorBoundaryProps,\n ActivityErrorBoundaryState\n> {\n state: ActivityErrorBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): ActivityErrorBoundaryState {\n return { error };\n }\n\n render(): ReactNode {\n const { error } = this.state;\n if (!error) {\n return this.props.children;\n }\n\n // The same answer every development check reads, from the one function\n // that gives it: a boundary with a reading of its own showed a learner a\n // stack trace in every browser production build.\n if (isDevelopment()) {\n return (\n <div role=\"alert\">\n <strong>{(this.props.strings ?? DEFAULT_STRINGS).activityFailed}</strong>\n <pre>{error.stack ?? error.message}</pre>\n </div>\n );\n }\n\n return (\n <div role=\"alert\">\n {this.props.activityTitle\n ? (this.props.strings ?? DEFAULT_STRINGS).activityFailedNamed(this.props.activityTitle)\n : (this.props.strings ?? DEFAULT_STRINGS).activityFailedUnnamed}\n </div>\n );\n }\n}\n"]}
|
|
@@ -1,14 +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
|
|
11
|
-
var
|
|
4
|
+
var chunkH63O5HPW_cjs = require('./chunk-H63O5HPW.cjs');
|
|
5
|
+
var chunkJKMBFHER_cjs = require('./chunk-JKMBFHER.cjs');
|
|
6
|
+
var chunkTI23GIFM_cjs = require('./chunk-TI23GIFM.cjs');
|
|
7
|
+
var chunkQA42VDTA_cjs = require('./chunk-QA42VDTA.cjs');
|
|
8
|
+
var chunkRZ52SEYV_cjs = require('./chunk-RZ52SEYV.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');
|
|
12
12
|
var lkCore = require('@intellectif/lk-core');
|
|
13
13
|
var react = require('react');
|
|
14
14
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -39,7 +39,7 @@ function ActivityPreview({
|
|
|
39
39
|
theme,
|
|
40
40
|
locale
|
|
41
41
|
}) {
|
|
42
|
-
const s =
|
|
42
|
+
const s = chunkAHGB5HH6_cjs.useLkStrings(strings);
|
|
43
43
|
const type = isRecord(draft) && typeof draft.type === "string" ? draft.type : void 0;
|
|
44
44
|
const contentKey = contentKeyOf(draft);
|
|
45
45
|
const result = react.useMemo(
|
|
@@ -106,7 +106,7 @@ function ActivityPreview({
|
|
|
106
106
|
const data = result.data;
|
|
107
107
|
const key = `${renderMode}:${responseKey}:${recordingKeyOf(data)}`;
|
|
108
108
|
if (marking?.kind === "failed") {
|
|
109
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkBAKLJKFZ_cjs.ActivityErrorBoundary, { activityTitle: data.title, strings: s, children: /* @__PURE__ */ jsxRuntime.jsx(Rethrow, { error: marking.error }) }, key);
|
|
110
110
|
}
|
|
111
111
|
const shared = {
|
|
112
112
|
renderMode,
|
|
@@ -133,7 +133,7 @@ function ActivityPreview({
|
|
|
133
133
|
switch (data.type) {
|
|
134
134
|
case "multiple-choice":
|
|
135
135
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
136
|
-
|
|
136
|
+
chunkJKMBFHER_cjs.MultipleChoice,
|
|
137
137
|
{
|
|
138
138
|
data,
|
|
139
139
|
shuffleSeed: shuffleSeed ?? PREVIEW_SHUFFLE_SEED,
|
|
@@ -142,10 +142,10 @@ function ActivityPreview({
|
|
|
142
142
|
key
|
|
143
143
|
);
|
|
144
144
|
case "fill-in-the-blanks":
|
|
145
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
145
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkTI23GIFM_cjs.FillInTheBlanks, { data, ...shared }, key);
|
|
146
146
|
case "gap-select":
|
|
147
147
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
148
|
-
|
|
148
|
+
chunkQA42VDTA_cjs.GapSelect,
|
|
149
149
|
{
|
|
150
150
|
data,
|
|
151
151
|
shuffleSeed: shuffleSeed ?? PREVIEW_SHUFFLE_SEED,
|
|
@@ -154,11 +154,11 @@ function ActivityPreview({
|
|
|
154
154
|
key
|
|
155
155
|
);
|
|
156
156
|
case "written-response":
|
|
157
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
157
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkH63O5HPW_cjs.WrittenResponse, { data, ...shared }, key);
|
|
158
158
|
case "dictation":
|
|
159
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
159
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkRZ52SEYV_cjs.Dictation, { data, ...shared }, key);
|
|
160
160
|
case "read-aloud":
|
|
161
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
161
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunk6RRFH7C4_cjs.ReadAloud, { data, recordingBinding: PREVIEW_RECORDING, ...shared }, key);
|
|
162
162
|
default:
|
|
163
163
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lk-preview-unsupported", role: "note", children: s.unsupportedActivity });
|
|
164
164
|
}
|
|
@@ -232,5 +232,5 @@ function contentKeyOf(value, enclosing = /* @__PURE__ */ new Set()) {
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
exports.ActivityPreview = ActivityPreview;
|
|
235
|
-
//# sourceMappingURL=chunk-
|
|
236
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-Z5XY66PO.cjs.map
|
|
236
|
+
//# sourceMappingURL=chunk-Z5XY66PO.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ActivityPreview/ActivityPreview.tsx"],"names":["useLkStrings","useMemo","validateDraft","evaluate","slotMediaKey","jsx","Fragment","ActivityErrorBoundary","MultipleChoice","FillInTheBlanks","GapSelect","WrittenResponse","Dictation","ReadAloud"],"mappings":"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","file":"chunk-OO24JGYH.cjs","sourcesContent":["'use client';\n\nimport {\n type ActivityType,\n type DraftNotComplete,\n evaluate,\n type ItemOutcome,\n type LearnerResponse,\n slotMediaKey,\n type ThemeTokens,\n validateDraft,\n} from '@intellectif/lk-core';\nimport { type ReactNode, useMemo } from 'react';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport type { LkStringsOverride } from '../../i18n/strings.js';\nimport { ActivityErrorBoundary } from '../ActivityErrorBoundary.js';\nimport type { ActivityRenderer } from '../ActivitySequence/index.js';\nimport { Dictation } from '../Dictation/index.js';\nimport { FillInTheBlanks } from '../FillInTheBlanks/index.js';\nimport { GapSelect } from '../GapSelect/index.js';\nimport { MultipleChoice } from '../MultipleChoice/index.js';\nimport { ReadAloud } from '../ReadAloud/index.js';\nimport type { RecordingBinding } from '../ReadAloud/ReadAloud.js';\nimport type { HtmlSanitizer, MediaBudgetBinding, RenderMode } from '../types.js';\nimport { WrittenResponse } from '../WrittenResponse/index.js';\n\n/**\n * The option-shuffle seed a preview uses when none is given. Fixed, so a\n * shuffled question holds still while its author edits it instead of\n * re-ordering on every remount.\n */\nconst PREVIEW_SHUFFLE_SEED = 'lk-activity-preview';\n\n/**\n * The slot a previewed activity stands in for. A recording's play budget is\n * keyed to it and lives only in this mount: the preview counts plays so an\n * author hears the limit a learner gets, and records none of them.\n */\nconst PREVIEW_SLOT_ID = 'preview';\n\n/** Numbers the takes a preview mints keys for, so two are never the same take. */\nlet previewTakeCount = 0;\n\n/**\n * The store a previewed read-aloud records into: it keys the take so the whole\n * flow — record, play it back, submit — runs for the author, and keeps it\n * nowhere, like every other thing a preview does not record.\n *\n * It judges nothing, deliberately. `assess` is optional precisely so this can\n * exist: an author trying a reading out has no assessor to point at, and a\n * preview that demanded one would refuse to render the most common case. The\n * default `practice` mode then shows the \"assessment is not available\" notice,\n * which is the truth about this binding rather than a failure.\n */\nconst PREVIEW_RECORDING: RecordingBinding = {\n upload: async (take) => {\n previewTakeCount += 1;\n return {\n key: `${PREVIEW_SLOT_ID}-take-${previewTakeCount}`,\n mimeType: take.mimeType,\n durationMs: take.durationMs,\n };\n },\n};\n\nexport interface ActivityPreviewProps {\n /**\n * The activity as an editor holds it right now, finished or not. It is checked\n * with `validateDraft` before anything renders — by content, on every render —\n * so a half-written question never reaches a component that assumes a valid\n * one.\n */\n draft: unknown;\n /** The mode to preview in. Defaults to `practice`. */\n renderMode?: RenderMode;\n /**\n * A learner response to show as if a learner had given it. In `practice` and\n * `exam` it seeds the answer, which stays editable; in `review` it is the\n * submitted answer, marked by `evaluate()` unless `outcome` is given.\n */\n response?: LearnerResponse;\n /**\n * The outcome `review` marks the response with, instead of the one\n * `evaluate()` computes — which is how to preview a returned grade on a written\n * response, since the SDK cannot score one. Ignored in other modes.\n */\n outcome?: ItemOutcome;\n /**\n * Rendered in place of the activity while the draft is not complete, with the\n * issues `validateDraft` found — so an editor can list them in its own words.\n * The issue messages are English, and a preview that rendered them would put\n * untranslatable text on screen. Without it, the preview shows the\n * `previewIncomplete` or `previewInvalid` string.\n */\n fallback?: (result: DraftNotComplete) => ReactNode;\n /**\n * Renderers for activity types beyond the built-ins, keyed by `type`, as on\n * `<ActivitySequence>`. An entry receives the shared prop contract and\n * nothing else, so — like the shuffle seed below — the in-memory recording\n * binding a previewed read-aloud is given does not reach one.\n */\n renderers?: Readonly<Record<string, ActivityRenderer>>;\n /**\n * Seeds `<MultipleChoice>`'s option shuffle. Defaults to a fixed seed, so the\n * order holds while options are edited; adding or removing one deals them\n * again, because the shuffle orders by position. A `renderers` entry is given\n * no seed, as on `<ActivitySequence>`.\n */\n shuffleSeed?: string;\n /** Renders author-supplied rich text. See `HtmlSanitizer`. */\n sanitizeHtml?: HtmlSanitizer;\n /** Overrides the SDK's chrome text, for the preview's notice and the activity alike. */\n strings?: LkStringsOverride;\n /** Per-instance token overrides, passed to the activity. */\n theme?: Partial<ThemeTokens>;\n /** BCP 47 tag of the interface language, passed to the activity. */\n locale?: string;\n}\n\ntype Marking = { kind: 'marked'; outcome: ItemOutcome } | { kind: 'failed'; error: Error };\n\n/**\n * Renders an activity from an editor's draft, in any render mode, with a\n * simulated learner response — and renders a notice instead while the draft is\n * not an activity yet.\n *\n * Nothing it renders is recorded: no callback is wired, so a practice attempt in\n * a preview scores locally and goes nowhere, and a recording's play limit is\n * counted in memory only.\n *\n * A draft with no string `type`, a type nobody registered, and a `response` of a\n * different type from the draft are wiring errors, and throw.\n */\nexport function ActivityPreview({\n draft,\n renderMode = 'practice',\n response,\n outcome,\n fallback,\n renderers,\n shuffleSeed,\n sanitizeHtml,\n strings,\n theme,\n locale,\n}: ActivityPreviewProps) {\n const s = useLkStrings(strings);\n const type = isRecord(draft) && typeof draft.type === 'string' ? draft.type : undefined;\n\n // Validated on the draft's CONTENT, not its identity. The activity components\n // restart whenever `data` changes identity, and an editor that rebuilds its\n // payload on every change would otherwise restart the question an author is\n // trying out each time anything else on the page was edited. The key is read\n // on every render, so a draft changed in place is checked again too.\n const contentKey = contentKeyOf(draft);\n // biome-ignore lint/correctness/useExhaustiveDependencies: the draft's content (contentKey) is the trigger, not its identity\n const result = useMemo(\n () => (type === undefined ? undefined : validateDraft(type as ActivityType, draft)),\n [type, contentKey],\n );\n const activity = result?.status === 'complete' ? result.data : undefined;\n const responseFits = response === undefined || response.type === type;\n const responseKey = response === undefined ? 'none' : contentKeyOf(response);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: the response's content (responseKey) is the trigger, not its identity\n const marking = useMemo((): Marking | undefined => {\n if (renderMode !== 'review' || activity === undefined) {\n return undefined;\n }\n if (outcome !== undefined) {\n return { kind: 'marked', outcome };\n }\n if (response === undefined || !responseFits) {\n return undefined;\n }\n try {\n return { kind: 'marked', outcome: evaluate(activity, response) };\n } catch (thrown) {\n // Scored here, during this component's own render, where no error boundary\n // inside the activity can catch it — so it is handed to one below.\n return {\n kind: 'failed',\n error: thrown instanceof Error ? thrown : new Error(String(thrown)),\n };\n }\n }, [renderMode, activity, outcome, responseKey, responseFits]);\n\n const activityId = activity?.id;\n const mediaBudget = useMemo<MediaBudgetBinding>(\n () => ({\n key: slotMediaKey(PREVIEW_SLOT_ID),\n slotId: PREVIEW_SLOT_ID,\n index: 0,\n ...(activityId !== undefined ? { activityId } : {}),\n }),\n [activityId],\n );\n\n // All hooks are called before these throws, so hook order stays stable.\n if (type === undefined || result === undefined) {\n throw new Error(\n '<ActivityPreview> needs a draft object with a string `type`, to know which activity to check and render.',\n );\n }\n // Checked against the draft's own type, whatever state the draft is in. A\n // mis-wired response is a wiring error however unfinished the draft is, and\n // waiting for the draft to be complete would throw on the very edit that\n // completes it.\n if (response !== undefined && !responseFits) {\n throw new Error(\n `<ActivityPreview> was given a \"${response.type}\" response for a \"${type}\" activity.`,\n );\n }\n if (result.status !== 'complete') {\n if (fallback !== undefined) {\n return <>{fallback(result)}</>;\n }\n return (\n <div\n className=\"lk-preview-unavailable\"\n role=\"note\"\n data-status={result.status}\n {...(locale !== undefined ? { lang: locale } : {})}\n >\n {result.status === 'invalid' ? s.previewInvalid : s.previewIncomplete}\n </div>\n );\n }\n const data = result.data;\n\n // A different simulated response, or a different mode, mounts the activity\n // afresh, play count included: a seeded answer is read at mount, and a practice\n // attempt the author submitted must not carry over into an exam preview. So\n // does a different recording or playback policy, which is a different listening\n // budget — the transport reads its count once, when it mounts.\n const key = `${renderMode}:${responseKey}:${recordingKeyOf(data)}`;\n\n if (marking?.kind === 'failed') {\n // The response is one the scorer cannot read, or a registered scorer threw.\n // Shown as the activity's error fallback, as a render failure would be.\n return (\n <ActivityErrorBoundary key={key} activityTitle={data.title} strings={s}>\n <Rethrow error={marking.error} />\n </ActivityErrorBoundary>\n );\n }\n\n const shared = {\n renderMode,\n // Without a binding a budgeted recording counts nothing in `practice`, and in\n // `exam` the media component refuses to render at all — rightly, on a real\n // paper, where nothing would persist the count. A preview persists nothing by\n // design, so it keeps the count in memory and says so.\n mediaBudget,\n ...(sanitizeHtml !== undefined ? { sanitizeHtml } : {}),\n ...(strings !== undefined ? { strings } : {}),\n ...(theme !== undefined ? { theme } : {}),\n ...(locale !== undefined ? { locale } : {}),\n // Seeded rather than controlled, in every mode, exactly as `<ActivitySequence>`\n // hands a restored answer to its slots — so a renderer written for the\n // sequence reads it here too. `review` is read-only either way, and `key`\n // above re-seeds whenever the response changes.\n ...(response !== undefined ? { defaultValue: response } : {}),\n ...(marking !== undefined ? { outcome: marking.outcome } : {}),\n };\n\n const Custom = renderers?.[data.type];\n if (Custom !== undefined) {\n return <Custom key={key} data={data} {...shared} />;\n }\n switch (data.type) {\n case 'multiple-choice':\n return (\n <MultipleChoice\n key={key}\n data={data}\n shuffleSeed={shuffleSeed ?? PREVIEW_SHUFFLE_SEED}\n {...shared}\n />\n );\n case 'fill-in-the-blanks':\n return <FillInTheBlanks key={key} data={data} {...shared} />;\n case 'gap-select':\n return (\n <GapSelect\n key={key}\n data={data}\n shuffleSeed={shuffleSeed ?? PREVIEW_SHUFFLE_SEED}\n {...shared}\n />\n );\n case 'written-response':\n return <WrittenResponse key={key} data={data} {...shared} />;\n case 'dictation':\n return <Dictation key={key} data={data} {...shared} />;\n case 'read-aloud':\n return <ReadAloud key={key} data={data} recordingBinding={PREVIEW_RECORDING} {...shared} />;\n default:\n return (\n <div className=\"lk-preview-unsupported\" role=\"note\">\n {s.unsupportedActivity}\n </div>\n );\n }\n}\n\n/** Throws `error` while rendering, so the error boundary around it shows its fallback. */\nfunction Rethrow({ error }: { error: Error }): never {\n throw error;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * The recording and its playback policy — not its description, which changes\n * no budget — plus the slower file a dictation or a read-aloud carries, which\n * follows the same policy and must remount when it is swapped for another.\n */\nfunction recordingKeyOf(data: unknown): string {\n const media = isRecord(data) ? data.media : undefined;\n const slowMedia = isRecord(data) ? data.slowMedia : undefined;\n const slowUrl = isRecord(slowMedia) ? slowMedia.url : undefined;\n if (!isRecord(media) && slowUrl === undefined) {\n return '';\n }\n return contentKeyOf([\n isRecord(media) ? media.type : undefined,\n isRecord(media) ? media.url : undefined,\n isRecord(media) ? media.playback : undefined,\n slowUrl,\n ]);\n}\n\nconst identities = new WeakMap<object, number>();\nlet lastIdentity = 0;\n\n/** A key for a value compared by identity: the same object always gets the same one. */\nfunction identityKeyOf(value: object): string {\n let identity = identities.get(value);\n if (identity === undefined) {\n lastIdentity += 1;\n identity = lastIdentity;\n identities.set(value, identity);\n }\n return `#${identity}`;\n}\n\n/**\n * A string that changes exactly when a value's content does.\n *\n * Object keys are sorted, because key order is not content: a draft saved to a\n * JSON column comes back with its keys reordered. Every value is written in a\n * form no other value shares — JSON would write a non-finite number as `null`\n * and drop `undefined`, and those decide different issues. What JSON does not\n * describe — an instance of a class, a function, a reference back to an\n * enclosing object — is compared by identity, and a symbol by its description.\n */\nfunction contentKeyOf(value: unknown, enclosing: Set<object> = new Set()): string {\n switch (typeof value) {\n case 'string':\n return JSON.stringify(value);\n case 'number':\n // `String` keeps NaN, the infinities and every other number apart; only -0\n // needs saying.\n return Object.is(value, -0) ? '-0' : String(value);\n case 'bigint':\n return `${value}n`;\n case 'boolean':\n case 'undefined':\n return String(value);\n case 'symbol':\n return `Symbol(${JSON.stringify(value.description ?? null)})`;\n case 'function':\n return identityKeyOf(value);\n }\n // Every other `typeof` has returned above: this is `null`, or an object.\n if (value === null || typeof value !== 'object') {\n return 'null';\n }\n const prototype = Object.getPrototypeOf(value);\n const plain = Array.isArray(value) || prototype === Object.prototype || prototype === null;\n if (!plain || enclosing.has(value)) {\n return identityKeyOf(value);\n }\n enclosing.add(value);\n try {\n if (Array.isArray(value)) {\n return `[${Array.from(value, (item) => contentKeyOf(item, enclosing)).join(',')}]`;\n }\n const record = value as Record<string, unknown>;\n const fields = Object.keys(record)\n .sort()\n .map((field) => `${JSON.stringify(field)}:${contentKeyOf(record[field], enclosing)}`);\n return `{${fields.join(',')}}`;\n } finally {\n enclosing.delete(value);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/ActivityPreview/ActivityPreview.tsx"],"names":["useLkStrings","useMemo","validateDraft","evaluate","slotMediaKey","jsx","Fragment","ActivityErrorBoundary","MultipleChoice","FillInTheBlanks","GapSelect","WrittenResponse","Dictation","ReadAloud"],"mappings":"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","file":"chunk-Z5XY66PO.cjs","sourcesContent":["'use client';\n\nimport {\n type ActivityType,\n type DraftNotComplete,\n evaluate,\n type ItemOutcome,\n type LearnerResponse,\n slotMediaKey,\n type ThemeTokens,\n validateDraft,\n} from '@intellectif/lk-core';\nimport { type ReactNode, useMemo } from 'react';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport type { LkStringsOverride } from '../../i18n/strings.js';\nimport { ActivityErrorBoundary } from '../ActivityErrorBoundary.js';\nimport type { ActivityRenderer } from '../ActivitySequence/index.js';\nimport { Dictation } from '../Dictation/index.js';\nimport { FillInTheBlanks } from '../FillInTheBlanks/index.js';\nimport { GapSelect } from '../GapSelect/index.js';\nimport { MultipleChoice } from '../MultipleChoice/index.js';\nimport { ReadAloud } from '../ReadAloud/index.js';\nimport type { RecordingBinding } from '../ReadAloud/ReadAloud.js';\nimport type { HtmlSanitizer, MediaBudgetBinding, RenderMode } from '../types.js';\nimport { WrittenResponse } from '../WrittenResponse/index.js';\n\n/**\n * The option-shuffle seed a preview uses when none is given. Fixed, so a\n * shuffled question holds still while its author edits it instead of\n * re-ordering on every remount.\n */\nconst PREVIEW_SHUFFLE_SEED = 'lk-activity-preview';\n\n/**\n * The slot a previewed activity stands in for. A recording's play budget is\n * keyed to it and lives only in this mount: the preview counts plays so an\n * author hears the limit a learner gets, and records none of them.\n */\nconst PREVIEW_SLOT_ID = 'preview';\n\n/** Numbers the takes a preview mints keys for, so two are never the same take. */\nlet previewTakeCount = 0;\n\n/**\n * The store a previewed read-aloud records into: it keys the take so the whole\n * flow — record, play it back, submit — runs for the author, and keeps it\n * nowhere, like every other thing a preview does not record.\n *\n * It judges nothing, deliberately. `assess` is optional precisely so this can\n * exist: an author trying a reading out has no assessor to point at, and a\n * preview that demanded one would refuse to render the most common case. The\n * default `practice` mode then shows the \"assessment is not available\" notice,\n * which is the truth about this binding rather than a failure.\n */\nconst PREVIEW_RECORDING: RecordingBinding = {\n upload: async (take) => {\n previewTakeCount += 1;\n return {\n key: `${PREVIEW_SLOT_ID}-take-${previewTakeCount}`,\n mimeType: take.mimeType,\n durationMs: take.durationMs,\n };\n },\n};\n\nexport interface ActivityPreviewProps {\n /**\n * The activity as an editor holds it right now, finished or not. It is checked\n * with `validateDraft` before anything renders — by content, on every render —\n * so a half-written question never reaches a component that assumes a valid\n * one.\n */\n draft: unknown;\n /** The mode to preview in. Defaults to `practice`. */\n renderMode?: RenderMode;\n /**\n * A learner response to show as if a learner had given it. In `practice` and\n * `exam` it seeds the answer, which stays editable; in `review` it is the\n * submitted answer, marked by `evaluate()` unless `outcome` is given.\n */\n response?: LearnerResponse;\n /**\n * The outcome `review` marks the response with, instead of the one\n * `evaluate()` computes — which is how to preview a returned grade on a written\n * response, since the SDK cannot score one. Ignored in other modes.\n */\n outcome?: ItemOutcome;\n /**\n * Rendered in place of the activity while the draft is not complete, with the\n * issues `validateDraft` found — so an editor can list them in its own words.\n * The issue messages are English, and a preview that rendered them would put\n * untranslatable text on screen. Without it, the preview shows the\n * `previewIncomplete` or `previewInvalid` string.\n */\n fallback?: (result: DraftNotComplete) => ReactNode;\n /**\n * Renderers for activity types beyond the built-ins, keyed by `type`, as on\n * `<ActivitySequence>`. An entry receives the shared prop contract and\n * nothing else, so — like the shuffle seed below — the in-memory recording\n * binding a previewed read-aloud is given does not reach one.\n */\n renderers?: Readonly<Record<string, ActivityRenderer>>;\n /**\n * Seeds `<MultipleChoice>`'s option shuffle. Defaults to a fixed seed, so the\n * order holds while options are edited; adding or removing one deals them\n * again, because the shuffle orders by position. A `renderers` entry is given\n * no seed, as on `<ActivitySequence>`.\n */\n shuffleSeed?: string;\n /** Renders author-supplied rich text. See `HtmlSanitizer`. */\n sanitizeHtml?: HtmlSanitizer;\n /** Overrides the SDK's chrome text, for the preview's notice and the activity alike. */\n strings?: LkStringsOverride;\n /** Per-instance token overrides, passed to the activity. */\n theme?: Partial<ThemeTokens>;\n /** BCP 47 tag of the interface language, passed to the activity. */\n locale?: string;\n}\n\ntype Marking = { kind: 'marked'; outcome: ItemOutcome } | { kind: 'failed'; error: Error };\n\n/**\n * Renders an activity from an editor's draft, in any render mode, with a\n * simulated learner response — and renders a notice instead while the draft is\n * not an activity yet.\n *\n * Nothing it renders is recorded: no callback is wired, so a practice attempt in\n * a preview scores locally and goes nowhere, and a recording's play limit is\n * counted in memory only.\n *\n * A draft with no string `type`, a type nobody registered, and a `response` of a\n * different type from the draft are wiring errors, and throw.\n */\nexport function ActivityPreview({\n draft,\n renderMode = 'practice',\n response,\n outcome,\n fallback,\n renderers,\n shuffleSeed,\n sanitizeHtml,\n strings,\n theme,\n locale,\n}: ActivityPreviewProps) {\n const s = useLkStrings(strings);\n const type = isRecord(draft) && typeof draft.type === 'string' ? draft.type : undefined;\n\n // Validated on the draft's CONTENT, not its identity. The activity components\n // restart whenever `data` changes identity, and an editor that rebuilds its\n // payload on every change would otherwise restart the question an author is\n // trying out each time anything else on the page was edited. The key is read\n // on every render, so a draft changed in place is checked again too.\n const contentKey = contentKeyOf(draft);\n // biome-ignore lint/correctness/useExhaustiveDependencies: the draft's content (contentKey) is the trigger, not its identity\n const result = useMemo(\n () => (type === undefined ? undefined : validateDraft(type as ActivityType, draft)),\n [type, contentKey],\n );\n const activity = result?.status === 'complete' ? result.data : undefined;\n const responseFits = response === undefined || response.type === type;\n const responseKey = response === undefined ? 'none' : contentKeyOf(response);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: the response's content (responseKey) is the trigger, not its identity\n const marking = useMemo((): Marking | undefined => {\n if (renderMode !== 'review' || activity === undefined) {\n return undefined;\n }\n if (outcome !== undefined) {\n return { kind: 'marked', outcome };\n }\n if (response === undefined || !responseFits) {\n return undefined;\n }\n try {\n return { kind: 'marked', outcome: evaluate(activity, response) };\n } catch (thrown) {\n // Scored here, during this component's own render, where no error boundary\n // inside the activity can catch it — so it is handed to one below.\n return {\n kind: 'failed',\n error: thrown instanceof Error ? thrown : new Error(String(thrown)),\n };\n }\n }, [renderMode, activity, outcome, responseKey, responseFits]);\n\n const activityId = activity?.id;\n const mediaBudget = useMemo<MediaBudgetBinding>(\n () => ({\n key: slotMediaKey(PREVIEW_SLOT_ID),\n slotId: PREVIEW_SLOT_ID,\n index: 0,\n ...(activityId !== undefined ? { activityId } : {}),\n }),\n [activityId],\n );\n\n // All hooks are called before these throws, so hook order stays stable.\n if (type === undefined || result === undefined) {\n throw new Error(\n '<ActivityPreview> needs a draft object with a string `type`, to know which activity to check and render.',\n );\n }\n // Checked against the draft's own type, whatever state the draft is in. A\n // mis-wired response is a wiring error however unfinished the draft is, and\n // waiting for the draft to be complete would throw on the very edit that\n // completes it.\n if (response !== undefined && !responseFits) {\n throw new Error(\n `<ActivityPreview> was given a \"${response.type}\" response for a \"${type}\" activity.`,\n );\n }\n if (result.status !== 'complete') {\n if (fallback !== undefined) {\n return <>{fallback(result)}</>;\n }\n return (\n <div\n className=\"lk-preview-unavailable\"\n role=\"note\"\n data-status={result.status}\n {...(locale !== undefined ? { lang: locale } : {})}\n >\n {result.status === 'invalid' ? s.previewInvalid : s.previewIncomplete}\n </div>\n );\n }\n const data = result.data;\n\n // A different simulated response, or a different mode, mounts the activity\n // afresh, play count included: a seeded answer is read at mount, and a practice\n // attempt the author submitted must not carry over into an exam preview. So\n // does a different recording or playback policy, which is a different listening\n // budget — the transport reads its count once, when it mounts.\n const key = `${renderMode}:${responseKey}:${recordingKeyOf(data)}`;\n\n if (marking?.kind === 'failed') {\n // The response is one the scorer cannot read, or a registered scorer threw.\n // Shown as the activity's error fallback, as a render failure would be.\n return (\n <ActivityErrorBoundary key={key} activityTitle={data.title} strings={s}>\n <Rethrow error={marking.error} />\n </ActivityErrorBoundary>\n );\n }\n\n const shared = {\n renderMode,\n // Without a binding a budgeted recording counts nothing in `practice`, and in\n // `exam` the media component refuses to render at all — rightly, on a real\n // paper, where nothing would persist the count. A preview persists nothing by\n // design, so it keeps the count in memory and says so.\n mediaBudget,\n ...(sanitizeHtml !== undefined ? { sanitizeHtml } : {}),\n ...(strings !== undefined ? { strings } : {}),\n ...(theme !== undefined ? { theme } : {}),\n ...(locale !== undefined ? { locale } : {}),\n // Seeded rather than controlled, in every mode, exactly as `<ActivitySequence>`\n // hands a restored answer to its slots — so a renderer written for the\n // sequence reads it here too. `review` is read-only either way, and `key`\n // above re-seeds whenever the response changes.\n ...(response !== undefined ? { defaultValue: response } : {}),\n ...(marking !== undefined ? { outcome: marking.outcome } : {}),\n };\n\n const Custom = renderers?.[data.type];\n if (Custom !== undefined) {\n return <Custom key={key} data={data} {...shared} />;\n }\n switch (data.type) {\n case 'multiple-choice':\n return (\n <MultipleChoice\n key={key}\n data={data}\n shuffleSeed={shuffleSeed ?? PREVIEW_SHUFFLE_SEED}\n {...shared}\n />\n );\n case 'fill-in-the-blanks':\n return <FillInTheBlanks key={key} data={data} {...shared} />;\n case 'gap-select':\n return (\n <GapSelect\n key={key}\n data={data}\n shuffleSeed={shuffleSeed ?? PREVIEW_SHUFFLE_SEED}\n {...shared}\n />\n );\n case 'written-response':\n return <WrittenResponse key={key} data={data} {...shared} />;\n case 'dictation':\n return <Dictation key={key} data={data} {...shared} />;\n case 'read-aloud':\n return <ReadAloud key={key} data={data} recordingBinding={PREVIEW_RECORDING} {...shared} />;\n default:\n return (\n <div className=\"lk-preview-unsupported\" role=\"note\">\n {s.unsupportedActivity}\n </div>\n );\n }\n}\n\n/** Throws `error` while rendering, so the error boundary around it shows its fallback. */\nfunction Rethrow({ error }: { error: Error }): never {\n throw error;\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * The recording and its playback policy — not its description, which changes\n * no budget — plus the slower file a dictation or a read-aloud carries, which\n * follows the same policy and must remount when it is swapped for another.\n */\nfunction recordingKeyOf(data: unknown): string {\n const media = isRecord(data) ? data.media : undefined;\n const slowMedia = isRecord(data) ? data.slowMedia : undefined;\n const slowUrl = isRecord(slowMedia) ? slowMedia.url : undefined;\n if (!isRecord(media) && slowUrl === undefined) {\n return '';\n }\n return contentKeyOf([\n isRecord(media) ? media.type : undefined,\n isRecord(media) ? media.url : undefined,\n isRecord(media) ? media.playback : undefined,\n slowUrl,\n ]);\n}\n\nconst identities = new WeakMap<object, number>();\nlet lastIdentity = 0;\n\n/** A key for a value compared by identity: the same object always gets the same one. */\nfunction identityKeyOf(value: object): string {\n let identity = identities.get(value);\n if (identity === undefined) {\n lastIdentity += 1;\n identity = lastIdentity;\n identities.set(value, identity);\n }\n return `#${identity}`;\n}\n\n/**\n * A string that changes exactly when a value's content does.\n *\n * Object keys are sorted, because key order is not content: a draft saved to a\n * JSON column comes back with its keys reordered. Every value is written in a\n * form no other value shares — JSON would write a non-finite number as `null`\n * and drop `undefined`, and those decide different issues. What JSON does not\n * describe — an instance of a class, a function, a reference back to an\n * enclosing object — is compared by identity, and a symbol by its description.\n */\nfunction contentKeyOf(value: unknown, enclosing: Set<object> = new Set()): string {\n switch (typeof value) {\n case 'string':\n return JSON.stringify(value);\n case 'number':\n // `String` keeps NaN, the infinities and every other number apart; only -0\n // needs saying.\n return Object.is(value, -0) ? '-0' : String(value);\n case 'bigint':\n return `${value}n`;\n case 'boolean':\n case 'undefined':\n return String(value);\n case 'symbol':\n return `Symbol(${JSON.stringify(value.description ?? null)})`;\n case 'function':\n return identityKeyOf(value);\n }\n // Every other `typeof` has returned above: this is `null`, or an object.\n if (value === null || typeof value !== 'object') {\n return 'null';\n }\n const prototype = Object.getPrototypeOf(value);\n const plain = Array.isArray(value) || prototype === Object.prototype || prototype === null;\n if (!plain || enclosing.has(value)) {\n return identityKeyOf(value);\n }\n enclosing.add(value);\n try {\n if (Array.isArray(value)) {\n return `[${Array.from(value, (item) => contentKeyOf(item, enclosing)).join(',')}]`;\n }\n const record = value as Record<string, unknown>;\n const fields = Object.keys(record)\n .sort()\n .map((field) => `${JSON.stringify(field)}:${contentKeyOf(record[field], enclosing)}`);\n return `{${fields.join(',')}}`;\n } finally {\n enclosing.delete(value);\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/ai/LkAiProvider.tsx
|
|
8
|
+
var LkAiContext = react.createContext(null);
|
|
9
|
+
function LkAiProvider({ ai, children }) {
|
|
10
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LkAiContext.Provider, { value: ai, children });
|
|
11
|
+
}
|
|
12
|
+
function useLearnerAi(override) {
|
|
13
|
+
const context = react.useContext(LkAiContext);
|
|
14
|
+
return override ?? context ?? void 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.LkAiProvider = LkAiProvider;
|
|
18
|
+
exports.useLearnerAi = useLearnerAi;
|
|
19
|
+
//# sourceMappingURL=chunk-ZDYNAWDZ.cjs.map
|
|
20
|
+
//# sourceMappingURL=chunk-ZDYNAWDZ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ai/LkAiProvider.tsx"],"names":["createContext","useContext"],"mappings":";;;;;;AAuCA,IAAM,WAAA,GAAcA,oBAAgC,IAAI,CAAA;AAqBjD,SAAS,YAAA,CAAa,EAAE,EAAA,EAAI,QAAA,EAAS,EAAyC;AACnF,EAAA,sCAAQ,WAAA,CAAY,QAAA,EAAZ,EAAqB,KAAA,EAAO,IAAK,QAAA,EAAS,CAAA;AACpD;AAGO,SAAS,aAAa,QAAA,EAA6C;AACxE,EAAA,MAAM,OAAA,GAAUC,iBAAW,WAAW,CAAA;AACtC,EAAA,OAAO,YAAY,OAAA,IAAW,MAAA;AAChC","file":"chunk-ZDYNAWDZ.cjs","sourcesContent":["'use client';\n\nimport type { AiExplanationRequest, AiHintRequest, AiTextResult } from '@intellectif/lk-core';\nimport { createContext, type ReactNode, useContext } from 'react';\n\n/**\n * The model a host runs for learners, as the components call it. The SDK never\n * calls a model, holds a key or writes a prompt: each port is the host's\n * function — usually a request to its own server, which holds the key and the\n * prompt and chooses the model.\n *\n * A port is called only when the learner asks — a button, never on render —\n * and gets an `AbortSignal` that fires when the answer it was asked about goes\n * away. Whatever it resolves to is checked before a learner sees it: see\n * `checkAiExplanation` and `checkAiHint` in lk-core. A port that rejects, or\n * resolves to something refused, costs the learner the help, never the\n * question.\n *\n * Leave a port out to switch that feature off. Nothing AI renders in `exam`,\n * whatever is passed.\n */\nexport interface LearnerAi {\n /** Explains a graded answer. */\n explain?: (\n request: AiExplanationRequest,\n options: { signal: AbortSignal },\n ) => Promise<AiTextResult>;\n /** Writes the next hint for an answer not yet submitted. */\n hint?: (request: AiHintRequest, options: { signal: AbortSignal }) => Promise<AiTextResult>;\n /** The most hints a learner can ask for on one question. Default 3, at most 10. */\n maxHints?: number;\n /**\n * The language to write explanations and hints in — the learner's own,\n * which in a language course need not be the item's. Defaults to the\n * component's `locale`.\n */\n learnerLocale?: string;\n}\n\nconst LkAiContext = createContext<LearnerAi | null>(null);\n\nexport interface LkAiProviderProps {\n ai: LearnerAi;\n children: ReactNode;\n}\n\n/**\n * Supplies the host's AI ports to every activity beneath, as `LkIntlProvider`\n * supplies strings. A component's own `ai` prop wins over it, whole.\n *\n * ```tsx\n * <LkAiProvider ai={{\n * explain: (request, { signal }) => api.explain(request, signal),\n * hint: (request, { signal }) => api.hint(request, signal),\n * learnerLocale: learner.language,\n * }}>\n * <ActivitySequence … />\n * </LkAiProvider>\n * ```\n */\nexport function LkAiProvider({ ai, children }: LkAiProviderProps): React.JSX.Element {\n return <LkAiContext.Provider value={ai}>{children}</LkAiContext.Provider>;\n}\n\n/** The ports in force: a component's own, else the provider's, else none. */\nexport function useLearnerAi(override?: LearnerAi): LearnerAi | undefined {\n const context = useContext(LkAiContext);\n return override ?? context ?? undefined;\n}\n"]}
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-
|
|
6
|
-
require('../chunk-
|
|
7
|
-
require('../chunk-
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
4
|
+
var chunkZ5XY66PO_cjs = require('../chunk-Z5XY66PO.cjs');
|
|
5
|
+
require('../chunk-H63O5HPW.cjs');
|
|
6
|
+
require('../chunk-JKMBFHER.cjs');
|
|
7
|
+
require('../chunk-TI23GIFM.cjs');
|
|
8
|
+
require('../chunk-QA42VDTA.cjs');
|
|
9
|
+
require('../chunk-RZ52SEYV.cjs');
|
|
10
|
+
require('../chunk-5F4Q6JT7.cjs');
|
|
11
|
+
require('../chunk-ZDYNAWDZ.cjs');
|
|
12
|
+
require('../chunk-6RRFH7C4.cjs');
|
|
13
|
+
require('../chunk-UQIRDE52.cjs');
|
|
12
14
|
require('../chunk-UDCQTOVU.cjs');
|
|
13
15
|
require('../chunk-OD65OZIW.cjs');
|
|
14
16
|
require('../chunk-BRPEB43C.cjs');
|
|
15
|
-
require('../chunk-
|
|
16
|
-
require('../chunk-
|
|
17
|
+
require('../chunk-BAKLJKFZ.cjs');
|
|
18
|
+
require('../chunk-L7WY5YFQ.cjs');
|
|
17
19
|
require('../chunk-XOR4MPEN.cjs');
|
|
18
|
-
require('../chunk-
|
|
20
|
+
require('../chunk-AHGB5HH6.cjs');
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
Object.defineProperty(exports, "ActivityPreview", {
|
|
23
25
|
enumerable: true,
|
|
24
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkZ5XY66PO_cjs.ActivityPreview; }
|
|
25
27
|
});
|
|
26
28
|
//# sourceMappingURL=ActivityPreview.cjs.map
|
|
27
29
|
//# sourceMappingURL=ActivityPreview.cjs.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { LearnerResponse, ItemOutcome, DraftNotComplete, ThemeTokens } from '@intellectif/lk-core';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { e as RenderMode, H as HtmlSanitizer, a as LkStringsOverride } from '../strings-
|
|
4
|
+
import { e as RenderMode, H as HtmlSanitizer, a as LkStringsOverride } from '../strings-BOPKhnS-.cjs';
|
|
5
5
|
import { ActivityRenderer } from './ActivitySequence.cjs';
|
|
6
|
+
import '../ai/LkAiProvider.cjs';
|
|
6
7
|
import '../machine-CuwKqWXC.cjs';
|
|
7
|
-
import '../WrittenResponse-
|
|
8
|
+
import '../WrittenResponse-Dl3zah22.cjs';
|
|
8
9
|
|
|
9
10
|
interface ActivityPreviewProps {
|
|
10
11
|
/**
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { LearnerResponse, ItemOutcome, DraftNotComplete, ThemeTokens } from '@intellectif/lk-core';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
-
import { e as RenderMode, H as HtmlSanitizer, a as LkStringsOverride } from '../strings-
|
|
4
|
+
import { e as RenderMode, H as HtmlSanitizer, a as LkStringsOverride } from '../strings-PCYKWCwd.js';
|
|
5
5
|
import { ActivityRenderer } from './ActivitySequence.js';
|
|
6
|
+
import '../ai/LkAiProvider.js';
|
|
6
7
|
import '../machine-CuwKqWXC.js';
|
|
7
|
-
import '../WrittenResponse-
|
|
8
|
+
import '../WrittenResponse-B4kY-U0v.js';
|
|
8
9
|
|
|
9
10
|
interface ActivityPreviewProps {
|
|
10
11
|
/**
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { ActivityPreview } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import '../chunk-
|
|
8
|
-
import '../chunk-
|
|
9
|
-
import '../chunk-
|
|
2
|
+
export { ActivityPreview } from '../chunk-H3IRVX7J.js';
|
|
3
|
+
import '../chunk-V5BTVGPA.js';
|
|
4
|
+
import '../chunk-6DTW5T3Z.js';
|
|
5
|
+
import '../chunk-QHK6PTUR.js';
|
|
6
|
+
import '../chunk-ALH6TUX2.js';
|
|
7
|
+
import '../chunk-HZMILQYO.js';
|
|
8
|
+
import '../chunk-GR33G5QM.js';
|
|
9
|
+
import '../chunk-YNDKAYW3.js';
|
|
10
|
+
import '../chunk-KP57YCYQ.js';
|
|
11
|
+
import '../chunk-QJW3K6JN.js';
|
|
10
12
|
import '../chunk-MCO52PV5.js';
|
|
11
13
|
import '../chunk-YORQQXGO.js';
|
|
12
14
|
import '../chunk-RCMYEWBE.js';
|
|
13
|
-
import '../chunk-
|
|
14
|
-
import '../chunk-
|
|
15
|
+
import '../chunk-YTGRXD23.js';
|
|
16
|
+
import '../chunk-BY4UQH2Y.js';
|
|
15
17
|
import '../chunk-6N43WDVG.js';
|
|
16
|
-
import '../chunk-
|
|
18
|
+
import '../chunk-YRNEOBXA.js';
|
|
17
19
|
//# sourceMappingURL=ActivityPreview.js.map
|
|
18
20
|
//# sourceMappingURL=ActivityPreview.js.map
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-
|
|
6
|
-
require('../chunk-
|
|
7
|
-
require('../chunk-
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
12
|
-
require('../chunk-
|
|
4
|
+
var chunkXEGBGKHV_cjs = require('../chunk-XEGBGKHV.cjs');
|
|
5
|
+
require('../chunk-3FBBP5QR.cjs');
|
|
6
|
+
require('../chunk-H63O5HPW.cjs');
|
|
7
|
+
require('../chunk-JKMBFHER.cjs');
|
|
8
|
+
require('../chunk-TI23GIFM.cjs');
|
|
9
|
+
require('../chunk-QA42VDTA.cjs');
|
|
10
|
+
require('../chunk-RZ52SEYV.cjs');
|
|
11
|
+
require('../chunk-5F4Q6JT7.cjs');
|
|
12
|
+
require('../chunk-ZDYNAWDZ.cjs');
|
|
13
|
+
require('../chunk-6RRFH7C4.cjs');
|
|
14
|
+
require('../chunk-UQIRDE52.cjs');
|
|
13
15
|
require('../chunk-UDCQTOVU.cjs');
|
|
14
16
|
require('../chunk-OD65OZIW.cjs');
|
|
15
17
|
require('../chunk-BRPEB43C.cjs');
|
|
16
|
-
require('../chunk-
|
|
17
|
-
require('../chunk-
|
|
18
|
+
require('../chunk-BAKLJKFZ.cjs');
|
|
19
|
+
require('../chunk-L7WY5YFQ.cjs');
|
|
18
20
|
require('../chunk-XOR4MPEN.cjs');
|
|
19
|
-
require('../chunk-
|
|
21
|
+
require('../chunk-AHGB5HH6.cjs');
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
Object.defineProperty(exports, "ActivitySequence", {
|
|
24
26
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
27
|
+
get: function () { return chunkXEGBGKHV_cjs.ActivitySequence; }
|
|
26
28
|
});
|
|
27
29
|
//# sourceMappingURL=ActivitySequence.cjs.map
|
|
28
30
|
//# sourceMappingURL=ActivitySequence.cjs.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
|
|
2
2
|
import { ComponentType } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { a as
|
|
3
|
+
import { LearnerAi } from '../ai/LkAiProvider.cjs';
|
|
4
|
+
import { A as ActivityProps, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../strings-BOPKhnS-.cjs';
|
|
5
|
+
import { a as WrittenResponseSubmission } from '../WrittenResponse-Dl3zah22.cjs';
|
|
5
6
|
import '../machine-CuwKqWXC.cjs';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -240,6 +241,14 @@ interface ActivitySequenceProps {
|
|
|
240
241
|
workletUrl?: string;
|
|
241
242
|
/** Overrides the SDK's chrome text for this sequence. See {@link LkIntlProvider}. */
|
|
242
243
|
strings?: LkStringsOverride;
|
|
244
|
+
/**
|
|
245
|
+
* The host's AI ports, for every question this renders: explanations after
|
|
246
|
+
* grading, hints before submit. The same as `LkAiProvider`, for this one
|
|
247
|
+
* sequence, and a `renderers` override receives them as its own `ai` prop —
|
|
248
|
+
* except in `exam`, where nothing AI appears and no question is given them.
|
|
249
|
+
* See {@link LearnerAi}.
|
|
250
|
+
*/
|
|
251
|
+
ai?: LearnerAi;
|
|
243
252
|
/**
|
|
244
253
|
* `entries` shuffles the top-level entries; a group moves as one block, and
|
|
245
254
|
* the order INSIDE a group follows the group's own `shuffle` setting.
|
|
@@ -324,6 +333,6 @@ interface ActivitySequenceProps {
|
|
|
324
333
|
locale?: string;
|
|
325
334
|
disabled?: boolean;
|
|
326
335
|
}
|
|
327
|
-
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, workletUrl, strings, }: ActivitySequenceProps): React.JSX.Element;
|
|
336
|
+
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, workletUrl, strings, ai, }: ActivitySequenceProps): React.JSX.Element;
|
|
328
337
|
|
|
329
338
|
export { type ActivityRenderer, ActivitySequence, type ActivitySequenceProps, type SequenceItemOutcome };
|