@intellectif/lk-react 19.0.0 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +1 -0
  3. package/dist/{WrittenResponse-CeHY5u3W.d.ts → WrittenResponse-D2YI8xOK.d.ts} +8 -2
  4. package/dist/{WrittenResponse-DT_Yqbq1.d.cts → WrittenResponse-obIDDYDH.d.cts} +8 -2
  5. package/dist/ai/useAiHelp.cjs +4 -4
  6. package/dist/ai/useAiHelp.d.cts +8 -2
  7. package/dist/ai/useAiHelp.d.ts +8 -2
  8. package/dist/ai/useAiHelp.js +2 -2
  9. package/dist/{chunk-SEQTGOOU.js → chunk-3XP6VO4G.js} +22 -15
  10. package/dist/chunk-3XP6VO4G.js.map +1 -0
  11. package/dist/{chunk-5QCZZBOX.js → chunk-5GI53C6T.js} +22 -13
  12. package/dist/chunk-5GI53C6T.js.map +1 -0
  13. package/dist/{chunk-XUQ4KRTT.cjs → chunk-6S2CKZ4H.cjs} +24 -17
  14. package/dist/chunk-6S2CKZ4H.cjs.map +1 -0
  15. package/dist/{chunk-XHF376ES.js → chunk-AG7MWZYZ.js} +25 -11
  16. package/dist/chunk-AG7MWZYZ.js.map +1 -0
  17. package/dist/{chunk-YIYMBCPV.js → chunk-AQIAQHJC.js} +18 -9
  18. package/dist/chunk-AQIAQHJC.js.map +1 -0
  19. package/dist/{chunk-4NERCBOW.js → chunk-BGA2IVQY.js} +7 -5
  20. package/dist/chunk-BGA2IVQY.js.map +1 -0
  21. package/dist/{chunk-JVWLXVYG.cjs → chunk-BJLQKJZX.cjs} +2 -2
  22. package/dist/chunk-BJLQKJZX.cjs.map +1 -0
  23. package/dist/{chunk-XAIJNGTU.cjs → chunk-CEUEXISZ.cjs} +18 -13
  24. package/dist/chunk-CEUEXISZ.cjs.map +1 -0
  25. package/dist/{chunk-WKA6FUR4.cjs → chunk-DZVF3IGB.cjs} +24 -18
  26. package/dist/chunk-DZVF3IGB.cjs.map +1 -0
  27. package/dist/{chunk-KOFA54C7.js → chunk-HI6BUUIJ.js} +18 -12
  28. package/dist/chunk-HI6BUUIJ.js.map +1 -0
  29. package/dist/{chunk-NGFTSRKO.cjs → chunk-HREA5SMB.cjs} +23 -14
  30. package/dist/chunk-HREA5SMB.cjs.map +1 -0
  31. package/dist/{chunk-NLTU5JFD.js → chunk-IQ55QNBI.js} +16 -11
  32. package/dist/chunk-IQ55QNBI.js.map +1 -0
  33. package/dist/chunk-IXMT7X3E.cjs +44 -0
  34. package/dist/chunk-IXMT7X3E.cjs.map +1 -0
  35. package/dist/{chunk-ZME5FMED.cjs → chunk-JLDSCHY5.cjs} +27 -13
  36. package/dist/chunk-JLDSCHY5.cjs.map +1 -0
  37. package/dist/{chunk-55W2472T.cjs → chunk-LK5VXNMR.cjs} +14 -14
  38. package/dist/{chunk-55W2472T.cjs.map → chunk-LK5VXNMR.cjs.map} +1 -1
  39. package/dist/{chunk-KGDGYRBL.cjs → chunk-NOC2M6LU.cjs} +7 -6
  40. package/dist/chunk-NOC2M6LU.cjs.map +1 -0
  41. package/dist/{chunk-UXV3V5NH.js → chunk-NWNQ2PHT.js} +23 -11
  42. package/dist/chunk-NWNQ2PHT.js.map +1 -0
  43. package/dist/chunk-ORBU3XKH.js +40 -0
  44. package/dist/chunk-ORBU3XKH.js.map +1 -0
  45. package/dist/{chunk-2X2NZF46.cjs → chunk-PWLJDP3X.cjs} +29 -20
  46. package/dist/chunk-PWLJDP3X.cjs.map +1 -0
  47. package/dist/{chunk-OWV7VRMQ.js → chunk-QKW2GGTV.js} +20 -11
  48. package/dist/chunk-QKW2GGTV.js.map +1 -0
  49. package/dist/{chunk-NZM3M5IR.cjs → chunk-RT2PP4SO.cjs} +27 -15
  50. package/dist/chunk-RT2PP4SO.cjs.map +1 -0
  51. package/dist/{chunk-QRT2W5N5.js → chunk-RUS42NMN.js} +5 -4
  52. package/dist/chunk-RUS42NMN.js.map +1 -0
  53. package/dist/{chunk-SXU26SFO.cjs → chunk-TRMWBJWT.cjs} +17 -8
  54. package/dist/chunk-TRMWBJWT.cjs.map +1 -0
  55. package/dist/{chunk-CQNKZ435.cjs → chunk-UHIOVOFK.cjs} +7 -5
  56. package/dist/chunk-UHIOVOFK.cjs.map +1 -0
  57. package/dist/{chunk-7NNMDZUU.js → chunk-W6DMHN33.js} +8 -8
  58. package/dist/{chunk-7NNMDZUU.js.map → chunk-W6DMHN33.js.map} +1 -1
  59. package/dist/{chunk-TEAVPUMX.js → chunk-WBLYD5QA.js} +2 -2
  60. package/dist/chunk-WBLYD5QA.js.map +1 -0
  61. package/dist/components/ActivityPreview.cjs +12 -12
  62. package/dist/components/ActivityPreview.d.cts +2 -2
  63. package/dist/components/ActivityPreview.d.ts +2 -2
  64. package/dist/components/ActivityPreview.js +11 -11
  65. package/dist/components/ActivitySequence.cjs +12 -12
  66. package/dist/components/ActivitySequence.d.cts +16 -4
  67. package/dist/components/ActivitySequence.d.ts +16 -4
  68. package/dist/components/ActivitySequence.js +11 -11
  69. package/dist/components/Dictation.cjs +6 -6
  70. package/dist/components/Dictation.d.cts +1 -1
  71. package/dist/components/Dictation.d.ts +1 -1
  72. package/dist/components/Dictation.js +5 -5
  73. package/dist/components/FillInTheBlanks.cjs +6 -6
  74. package/dist/components/FillInTheBlanks.d.cts +1 -1
  75. package/dist/components/FillInTheBlanks.d.ts +1 -1
  76. package/dist/components/FillInTheBlanks.js +5 -5
  77. package/dist/components/GapSelect.cjs +6 -6
  78. package/dist/components/GapSelect.d.cts +1 -1
  79. package/dist/components/GapSelect.d.ts +1 -1
  80. package/dist/components/GapSelect.js +5 -5
  81. package/dist/components/InteractiveVideo.cjs +12 -12
  82. package/dist/components/InteractiveVideo.d.cts +16 -3
  83. package/dist/components/InteractiveVideo.d.ts +16 -3
  84. package/dist/components/InteractiveVideo.js +10 -10
  85. package/dist/components/MultipleChoice.cjs +6 -6
  86. package/dist/components/MultipleChoice.d.cts +1 -1
  87. package/dist/components/MultipleChoice.d.ts +1 -1
  88. package/dist/components/MultipleChoice.js +5 -5
  89. package/dist/components/PronunciationFeedback.d.cts +1 -1
  90. package/dist/components/PronunciationFeedback.d.ts +1 -1
  91. package/dist/components/ReadAloud.cjs +4 -4
  92. package/dist/components/ReadAloud.d.cts +2 -2
  93. package/dist/components/ReadAloud.d.ts +2 -2
  94. package/dist/components/ReadAloud.js +3 -3
  95. package/dist/components/StimulusPanel.d.cts +1 -1
  96. package/dist/components/StimulusPanel.d.ts +1 -1
  97. package/dist/components/WrittenResponse.cjs +4 -3
  98. package/dist/components/WrittenResponse.d.cts +3 -3
  99. package/dist/components/WrittenResponse.d.ts +3 -3
  100. package/dist/components/WrittenResponse.js +3 -2
  101. package/dist/i18n/LkIntlProvider.d.cts +2 -2
  102. package/dist/i18n/LkIntlProvider.d.ts +2 -2
  103. package/dist/index.cjs +25 -25
  104. package/dist/index.cjs.map +1 -1
  105. package/dist/index.d.cts +2 -2
  106. package/dist/index.d.ts +2 -2
  107. package/dist/index.js +13 -13
  108. package/dist/index.js.map +1 -1
  109. package/dist/{types-DtPYG1hh.d.cts → types-B_PCcqO-.d.cts} +9 -1
  110. package/dist/{types-BY-4S5Rd.d.ts → types-C-GMCJ0g.d.ts} +9 -1
  111. package/package.json +3 -3
  112. package/dist/chunk-2X2NZF46.cjs.map +0 -1
  113. package/dist/chunk-4NERCBOW.js.map +0 -1
  114. package/dist/chunk-5QCZZBOX.js.map +0 -1
  115. package/dist/chunk-BRPEB43C.cjs +0 -13
  116. package/dist/chunk-BRPEB43C.cjs.map +0 -1
  117. package/dist/chunk-CQNKZ435.cjs.map +0 -1
  118. package/dist/chunk-JVWLXVYG.cjs.map +0 -1
  119. package/dist/chunk-KGDGYRBL.cjs.map +0 -1
  120. package/dist/chunk-KOFA54C7.js.map +0 -1
  121. package/dist/chunk-NGFTSRKO.cjs.map +0 -1
  122. package/dist/chunk-NLTU5JFD.js.map +0 -1
  123. package/dist/chunk-NZM3M5IR.cjs.map +0 -1
  124. package/dist/chunk-OWV7VRMQ.js.map +0 -1
  125. package/dist/chunk-QRT2W5N5.js.map +0 -1
  126. package/dist/chunk-RCMYEWBE.js +0 -11
  127. package/dist/chunk-RCMYEWBE.js.map +0 -1
  128. package/dist/chunk-SEQTGOOU.js.map +0 -1
  129. package/dist/chunk-SXU26SFO.cjs.map +0 -1
  130. package/dist/chunk-TEAVPUMX.js.map +0 -1
  131. package/dist/chunk-UXV3V5NH.js.map +0 -1
  132. package/dist/chunk-WKA6FUR4.cjs.map +0 -1
  133. package/dist/chunk-XAIJNGTU.cjs.map +0 -1
  134. package/dist/chunk-XHF376ES.js.map +0 -1
  135. package/dist/chunk-XUQ4KRTT.cjs.map +0 -1
  136. package/dist/chunk-YIYMBCPV.js.map +0 -1
  137. package/dist/chunk-ZME5FMED.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/WrittenResponse/WrittenResponse.tsx","../src/components/WrittenResponse/index.tsx"],"names":["jsxs","Fragment","jsx","useLkStrings","useDeliveryPolicy","useMemo","isDevelopment","validateActivity","ActivitySchemaError","useActivityState","useState","useRef","useEffect","countWords","evaluate","xAPIBuilder","ANONYMOUS_ACTOR","objectIdFor","ActivityMedia","FeedbackRegion","outcomeShowsMarks","WrittenResponse","ActivityErrorBoundary"],"mappings":"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","file":"chunk-UHIOVOFK.cjs","sourcesContent":["'use client';\n\nimport {\n ActivitySchemaError,\n type CriterionScore,\n countWords,\n type DeliveryPolicy,\n evaluate,\n type GradeRecord,\n type InlineCorrection,\n type InteractionEvent,\n type ItemOutcome,\n type LearnerResponse,\n type ThemeTokens,\n validateActivity,\n type WrittenResponseData,\n type XAPIStatement,\n xAPIBuilder,\n} from '@intellectif/lk-core';\nimport { type CSSProperties, useEffect, useMemo, useRef, useState } from 'react';\nimport { useActivityState } from '../../hooks/useActivityState.js';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport type { LkStrings, LkStringsOverride } from '../../i18n/strings.js';\nimport { ANONYMOUS_ACTOR, isDevelopment, objectIdFor } from '../_internal.js';\nimport { ActivityMedia } from '../shared/ActivityMedia.js';\nimport { outcomeShowsMarks, useDeliveryPolicy } from '../shared/delivery.js';\nimport { FeedbackRegion } from '../shared/FeedbackRegion.js';\nimport type {\n HtmlSanitizer,\n MediaBudgetBinding,\n MediaTransportStrings,\n Renderable,\n RenderMode,\n} from '../types.js';\n\n/**\n * Payload delivered when the learner submits a written response. Grading is\n * DEFERRED (asynchronous AI/human grading), so there is no score here — and\n * deliberately no fake one: an ungraded submission must never be shown or\n * stored as a 0. The consumer persists `text` and grades it out-of-band.\n */\nexport interface WrittenResponseSubmission {\n /** The submitted text, verbatim. */\n text: string;\n /** Word count of `text`, recomputed with the canonical `countWords()`. */\n wordCount: number;\n /** Whether `wordCount` falls within the activity's `[minWords, maxWords]`. */\n withinWordBounds: boolean;\n /** Time in milliseconds from first interaction to submission. */\n timeSpent: number;\n /** The SUBMITTED-verb xAPI statement built for this submission (no score fields). */\n xapiStatement: XAPIStatement;\n}\n\n/**\n * Props for {@link WrittenResponse}. Mirrors `ActivityProps` except for the\n * completion callback: a deferred-grading activity completes with a\n * {@link WrittenResponseSubmission} (`onSubmitted`), not a scored\n * `ActivityResult` (`onComplete`) — deviation from Req 22.8 recorded in the\n * roadmap (§3.1): fabricating a score of 0 for ungraded work is the exact\n * bug this type exists to fix. Everything else — controlled value, render\n * mode, server outcome, rich text — follows the shared `ActivityProps`\n * contract verbatim.\n */\nexport interface WrittenResponseProps {\n /** Activity content. Accepts a `redact()` projection in `exam` mode. */\n data: Renderable<WrittenResponseData>;\n /**\n * Called on submit with the ungraded submission (text, recomputed word\n * count, bounds flag, timing, xAPI statement). Fires in `practice` and\n * `exam` mode, after `onSubmit`; never in `review`.\n *\n * Optional since lk-react 2.1.0 so a `review`-mode render (which has no submit\n * control) and an exam runner that only wants the raw response through\n * `onSubmit` do not have to pass a no-op. Supply it in `practice`/`exam`\n * unless `onSubmit` already captures everything you persist.\n */\n onSubmitted?: (submission: WrittenResponseSubmission) => void;\n /**\n * Called on submit with the raw learner response and no grade, BEFORE\n * `onSubmitted`. This is the only submit callback an exam runner needs:\n * the server grades the text and returns an {@link ItemOutcome} later.\n */\n onSubmit?: (response: LearnerResponse) => void;\n /**\n * Controlled value: the learner's current response. When present the\n * textarea renders from it (never from internal state) and every keystroke\n * goes out through `onChange` — restore an in-progress attempt, autosave a\n * delta, or drive a review render with it.\n */\n value?: LearnerResponse;\n /** Initial response for an uncontrolled component (ignored when `value` is set). */\n defaultValue?: LearnerResponse;\n /**\n * Mount as already submitted — read at mount only. Without it a resumed\n * attempt reopens an essay the learner had already submitted as editable\n * and re-submittable.\n */\n defaultSubmitted?: boolean;\n /** Fires on every change to the learner's response. Required for a controlled component. */\n onChange?: (response: LearnerResponse) => void;\n /**\n * Presentation mode, default `practice`. `practice` and `exam` are nearly\n * identical here — a written response is never graded client-side, so\n * there is no local score to withhold; `exam` additionally never calls\n * `evaluate()` and renders happily from a `redact()` projection.\n * `review` is read-only and shows the server's `outcome`.\n */\n renderMode?: RenderMode;\n /**\n * Server-computed outcome, rendered by `review` mode: `deferred` shows a\n * \"not graded yet\" affordance, `scored` shows the returned grade and\n * feedback. Ignored in other modes — this component never manufactures an\n * outcome of its own.\n */\n outcome?: ItemOutcome;\n /** Renders `data.promptHtml` when provided. See `HtmlSanitizer`. */\n sanitizeHtml?: HtmlSanitizer;\n /** Binds this activity's own `data.media` to a play budget. See {@link MediaBudgetBinding}. */\n mediaBudget?: MediaBudgetBinding;\n /** Translations for the audio transport chrome. See {@link MediaTransportStrings}. */\n mediaStrings?: Partial<MediaTransportStrings>;\n /** Overrides the SDK's chrome text for this activity. See {@link LkIntlProvider}. */\n strings?: LkStringsOverride;\n onInteraction?: (event: InteractionEvent) => void;\n /** Per-instance token overrides, applied as inline CSS vars on the root. */\n theme?: Partial<ThemeTokens>;\n locale?: string;\n disabled?: boolean;\n /**\n * The delivery policy. An essay is graded later, so only `feedback` reaches\n * it: `false` reads a returned grade back as nothing in `review`. See\n * `DeliveryPolicy` in lk-core.\n */\n delivery?: DeliveryPolicy | null;\n}\n\n/**\n * Reads the text out of a learner response. Another activity type's response\n * shape (the `value`/`defaultValue` props take the `LearnerResponse` union,\n * so a generic runner can hand any of them over) reads as empty rather than\n * throwing mid-exam.\n */\nfunction textOf(response: LearnerResponse | undefined): string {\n return response !== undefined && response.type === 'written-response' ? response.text : '';\n}\n\n/**\n * One criterion's score as a percentage of its OWN maximum.\n *\n * `CriterionScore.maxScore` defaults to 1 — the SDK's scaled convention — but\n * a grader may work out of 100, or out of 9 for a CEFR band, and\n * `gradeFromRubric` deliberately stores those judgements verbatim so a grade\n * stays auditable in the units the grader actually used. It normalises when it\n * computes the total; anything DISPLAYING a criterion has to normalise too, or\n * a perfectly ordinary 82/100 renders as \"8200%\". This is the same guard the\n * overall score already applies against `outcome.maxScore`.\n */\nfunction criterionPercent(criterion: CriterionScore): string {\n const max = criterion.maxScore !== undefined && criterion.maxScore > 0 ? criterion.maxScore : 1;\n return `${Math.round(((criterion.score as number) / max) * 100)}%`;\n}\n\n/**\n * Pairs each correction with a list key that is unique by construction. The\n * same mistake made twice carries the same `original`/`corrected` pair, so\n * the grader's `range` is what tells the occurrences apart. `range` is\n * optional and nothing validates it, so a correction without one — or one\n * whose range the grader already used — is keyed by its position instead.\n * Only position keys start with `#`, so the two kinds never collide.\n */\nfunction keyedCorrections(\n corrections: readonly InlineCorrection[],\n): { key: string; correction: InlineCorrection }[] {\n const used = new Set<string>();\n return corrections.map((correction, index) => {\n const anchored = correction.range\n ? `${correction.range.start}-${correction.range.end}:${correction.corrected}`\n : undefined;\n const key = anchored !== undefined && !used.has(anchored) ? anchored : `#${index}`;\n used.add(key);\n return { key, correction };\n });\n}\n\n/**\n * Renders the server-computed outcome in `review` mode. The grade shown here\n * always came back from the asynchronous grader — nothing on this path scores,\n * infers, or defaults a grade. A `written-response` outcome carries no\n * per-item `details` (there are no options or blanks to mark), so the render\n * is the scaled score, the pass state, and the grader's feedback.\n */\nfunction GradeBody({ grade, s }: { grade: GradeRecord; s: LkStrings }) {\n return (\n <>\n {grade.feedback ? <p className=\"lk-wr-grade-feedback\">{grade.feedback}</p> : null}\n {grade.criteria && grade.criteria.length > 0 ? (\n <ul className=\"lk-wr-criteria\">\n {grade.criteria.map((criterion) => (\n <li\n className=\"lk-wr-criterion\"\n key={criterion.name}\n data-na={String(criterion.notApplicable === true)}\n >\n <span className=\"lk-wr-criterion-name\">{criterion.name}</span>\n {criterion.notApplicable === true ? (\n <span className=\"lk-wr-criterion-score\">{s.notApplicable}</span>\n ) : (\n <span className=\"lk-wr-criterion-score\">\n {criterion.band ??\n (typeof criterion.score === 'number' ? criterionPercent(criterion) : '')}\n </span>\n )}\n {criterion.comment ? (\n <span className=\"lk-wr-criterion-comment\">{criterion.comment}</span>\n ) : null}\n </li>\n ))}\n </ul>\n ) : null}\n {grade.corrections && grade.corrections.length > 0 ? (\n <ul className=\"lk-wr-corrections\">\n {keyedCorrections(grade.corrections).map(({ key, correction }) => (\n <li className=\"lk-wr-correction\" key={key}>\n <del className=\"lk-wr-correction-original\">{correction.original}</del>{' '}\n <ins className=\"lk-wr-correction-corrected\">{correction.corrected}</ins>\n {correction.explanation ? (\n <span className=\"lk-wr-correction-explanation\">{correction.explanation}</span>\n ) : null}\n </li>\n ))}\n </ul>\n ) : null}\n {grade.requiresHumanReview === true ? (\n <p className=\"lk-wr-review-flag\">{s.awaitingHumanReview}</p>\n ) : null}\n </>\n );\n}\n\n/**\n * Renders the server-computed outcome in `review` mode. The grade shown here\n * always came back from the grader — nothing on this path scores, infers, or\n * defaults a grade.\n */\nfunction OutcomeSummary({ outcome, s }: { outcome: ItemOutcome; s: LkStrings }) {\n if (outcome.status === 'scored' || outcome.status === 'graded') {\n // `score` is scaled [0–1] against `maxScore`; normalising by `maxScore`\n // is a no-op for the canonical maxScore of 1 and keeps an unscaled\n // grader payload (8.5 / 10) from rendering as 850%.\n const percent =\n outcome.maxScore > 0\n ? Math.round((outcome.score / outcome.maxScore) * 100)\n : Math.round(outcome.score * 100);\n return (\n <div\n className=\"lk-wr-outcome\"\n data-status={outcome.status}\n data-passed={String(outcome.passed)}\n >\n <p className=\"lk-wr-grade\">{s.scoreAnnouncement(percent, outcome.passed)}</p>\n {outcome.status === 'graded' ? (\n <GradeBody grade={outcome.grade} s={s} />\n ) : outcome.feedback ? (\n <p className=\"lk-wr-grade-feedback\">{outcome.feedback}</p>\n ) : null}\n </div>\n );\n }\n if (outcome.status === 'deferred') {\n return (\n <div className=\"lk-wr-outcome\" data-status=\"deferred\">\n <p className=\"lk-wr-grade\">{s.awaitingGrade}</p>\n </div>\n );\n }\n // `unscorable` reasons are developer-facing strings; surface the state, not\n // the reason, and leave it on the element for diagnostics.\n return (\n <div className=\"lk-wr-outcome\" data-status=\"unscorable\" data-reason={outcome.reason}>\n <p className=\"lk-wr-grade\">{s.couldNotBeGraded}</p>\n </div>\n );\n}\n\nexport function WrittenResponse({\n data,\n onSubmitted,\n onSubmit,\n value,\n defaultValue,\n defaultSubmitted,\n onChange,\n renderMode = 'practice',\n outcome,\n sanitizeHtml,\n mediaBudget,\n mediaStrings,\n strings,\n onInteraction,\n theme,\n locale,\n disabled,\n delivery,\n}: WrittenResponseProps) {\n // Dev-only boundary validation (Req 2.3), same convention as MC/FIB. The\n // content schema is loose, so a `redact()` projection validates too.\n const s = useLkStrings(strings);\n // An essay is graded later, so `feedback` is the one setting that reaches\n // it: whether a returned grade — the score, each criterion, the corrections\n // — is read back in review.\n const policy = useDeliveryPolicy(delivery);\n\n const devError = useMemo(() => {\n if (!isDevelopment()) {\n return null;\n }\n const result = validateActivity('written-response', data);\n return result.success ? null : new ActivitySchemaError('written-response', result.errors);\n }, [data]);\n\n const { state, start, complete, getTimeSpent, reset } = useActivityState(\n defaultSubmitted === true ? 'completed' : 'idle',\n );\n const isControlled = value !== undefined;\n const [innerText, setInnerText] = useState<string>(() => textOf(defaultValue));\n const [summary, setSummary] = useState<string | null>(null);\n\n /**\n * Rich text is rendered ONLY through a caller-supplied sanitiser, and only\n * when the author actually shipped the HTML sidecar. Without both, the\n * plain-text prompt is rendered as an escaped React child.\n */\n const promptHtml = useMemo(() => {\n if (sanitizeHtml === undefined || typeof data.promptHtml !== 'string') {\n return null;\n }\n return sanitizeHtml(data.promptHtml);\n }, [data.promptHtml, sanitizeHtml]);\n\n // Latest seed text, kept in a ref so `defaultValue` is NOT a reset trigger:\n // callers pass an object literal, whose identity changes every render.\n const defaultTextRef = useRef<string>(textOf(defaultValue));\n useEffect(() => {\n defaultTextRef.current = textOf(defaultValue);\n }, [defaultValue]);\n\n // Reset on data-prop change (Req 3.7): back to the seed (empty when there\n // is none — the v1 behaviour), never the previous activity's draft.\n // Mirror `defaultSubmitted` so the reset below returns to the SEEDED state.\n // Resetting unconditionally to idle unlocked an item the learner had already\n // committed — which made `defaultSubmitted` a no-op here, since this effect\n // runs right after the first paint.\n const defaultSubmittedRef = useRef(defaultSubmitted);\n useEffect(() => {\n defaultSubmittedRef.current = defaultSubmitted;\n }, [defaultSubmitted]);\n\n // Identity guard so the MOUNT run is a no-op. Without it this effect fires\n // after the first paint and undoes every seed it was just given; with it,\n // only a real `data` change resets. A parent that rebuilds structurally\n // identical entries in render (`activities={raw.map(redact)}`) must not\n // unlock or revert a restored answer — the pager already remounts a slot\n // whose activity actually changed, via its key.\n const lastDataRef = useRef(data);\n useEffect(() => {\n if (lastDataRef.current === data) {\n return;\n }\n lastDataRef.current = data;\n setInnerText(defaultTextRef.current);\n setSummary(null);\n reset(defaultSubmittedRef.current === true ? 'completed' : 'idle');\n }, [data, reset]);\n\n if (devError) {\n throw devError;\n }\n\n const isExam = renderMode === 'exam';\n const isReview = renderMode === 'review';\n\n const text = isControlled ? textOf(value) : innerText;\n const submitted = state === 'completed';\n const inactive = disabled === true || submitted || isReview;\n const wordCount = countWords(text);\n const withinBounds = wordCount >= data.minWords && wordCount <= data.maxWords;\n\n const handleChange = (next: string): void => {\n if (inactive) {\n return;\n }\n if (state === 'idle') {\n start();\n }\n // A controlled component renders from `props.value` only; the caller's\n // state is the single source of truth for the text.\n if (!isControlled) {\n setInnerText(next);\n }\n const nextWordCount = countWords(next);\n onChange?.({ type: 'written-response', text: next, wordCount: nextWordCount });\n onInteraction?.({\n type: 'text-changed',\n activityId: data.id,\n timestamp: Date.now(),\n payload: { wordCount: nextWordCount },\n });\n };\n\n // Practice reveals nothing an essay could leak, but it DOES run the local\n // submit path and emit a practice xAPI statement for work the server is\n // supposed to grade. MultipleChoice and FillInTheBlanks have refused\n // redacted data in `practice` since 0.5.0; this component silently accepted\n // it, so an all-essay redacted paper mounted without `renderMode` looked\n // entirely healthy end to end. Fail at render, like its siblings.\n if (data.redacted === true && renderMode === 'practice') {\n throw new Error(\n `Written Response \"${data.id}\" received redacted activity data in renderMode \"practice\". ` +\n 'Practice runs the local submit path and emits a practice-mode xAPI statement, so an ' +\n 'exam item wired this way is graded nowhere and looks fine while it happens. ' +\n 'Render redacted data with renderMode=\"exam\" (server grades) or \"review\" (pass `outcome`).',\n );\n }\n\n const handleSubmit = (event: React.FormEvent): void => {\n event.preventDefault();\n if (inactive || text.trim().length === 0) {\n return;\n }\n let finalWordCount = wordCount;\n let finalWithinBounds = withinBounds;\n // `exam` mode must not call evaluate(): the component does not grade, and\n // a redacted projection carries no scoring input anyway. The two facts\n // evaluate() returns for a deferred type (recomputed word count, bounds)\n // are exactly what is computed above, so the payload is identical either\n // way; practice keeps going through core so the numbers stay canonical.\n if (!isExam) {\n const itemOutcome = evaluate(data, { type: 'written-response', text, wordCount });\n const partial = itemOutcome.status === 'deferred' ? itemOutcome.partial : undefined;\n if (typeof partial?.wordCount === 'number') {\n finalWordCount = partial.wordCount;\n }\n if (typeof partial?.withinWordBounds === 'boolean') {\n finalWithinBounds = partial.withinWordBounds;\n }\n }\n complete();\n const timeSpent = getTimeSpent();\n const xapiStatement = xAPIBuilder.buildSubmittedStatement({\n actor: ANONYMOUS_ACTOR,\n object: {\n id: objectIdFor(data.id),\n name: { [data.locale ?? 'en-US']: data.title },\n type: 'http://adlnet.gov/expapi/activities/cmi.interaction',\n interactionType: 'long-fill-in',\n },\n timeSpentMs: timeSpent,\n response: text,\n resultExtensions: {\n 'urn:learning-kit:extension:word-count': finalWordCount,\n 'urn:learning-kit:extension:within-word-bounds': finalWithinBounds,\n },\n });\n // Raw response first (an exam runner persists this), then the fuller\n // ungraded submission — mirroring `onSubmit` before `onComplete`.\n onSubmit?.({ type: 'written-response', text, wordCount: finalWordCount });\n onSubmitted?.({\n text,\n wordCount: finalWordCount,\n withinWordBounds: finalWithinBounds,\n timeSpent,\n xapiStatement,\n });\n setSummary(s.responseSubmitted);\n onInteraction?.({\n type: 'submitted',\n activityId: data.id,\n timestamp: Date.now(),\n payload: { wordCount: finalWordCount, withinWordBounds: finalWithinBounds },\n });\n };\n\n const promptId = `${data.id}-prompt`;\n const counterId = `${data.id}-counter`;\n const boundsLabel = s.wordBounds(data.minWords, data.maxWords);\n\n return (\n <form\n className=\"lk-wr\"\n aria-label={data.title}\n lang={locale}\n data-render-mode={renderMode}\n style={theme as CSSProperties | undefined}\n onSubmit={handleSubmit}\n >\n {data.media ? (\n <ActivityMedia\n media={data.media}\n renderMode={renderMode}\n {...(mediaBudget !== undefined ? { mediaBudget } : {})}\n {...(mediaStrings !== undefined ? { mediaStrings } : {})}\n {...(strings !== undefined ? { strings } : {})}\n {...(onInteraction !== undefined ? { onInteraction } : {})}\n {...(locale !== undefined ? { locale } : {})}\n />\n ) : null}\n {promptHtml === null ? (\n <p className=\"lk-wr-prompt\" id={promptId}>\n {data.prompt}\n </p>\n ) : (\n // A div, not a p: sanitised author HTML may contain block content.\n <div\n className=\"lk-wr-prompt\"\n id={promptId}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: rendered only through the caller-supplied HtmlSanitizer — the SDK never injects unsanitised markup\n dangerouslySetInnerHTML={{ __html: promptHtml }}\n />\n )}\n <textarea\n className=\"lk-wr-textarea\"\n aria-labelledby={promptId}\n aria-describedby={counterId}\n value={text}\n onChange={(event) => handleChange(event.target.value)}\n // `review` uses readOnly rather than disabled: the submitted essay\n // must stay focusable, selectable and scrollable for a screen reader\n // and a keyboard, while remaining uneditable.\n disabled={!isReview && inactive}\n readOnly={isReview}\n rows={8}\n />\n <div\n className=\"lk-wr-counter\"\n id={counterId}\n aria-live=\"polite\"\n data-within-bounds={withinBounds}\n >\n {s.wordCount(wordCount)} ({boundsLabel})\n </div>\n {isReview ? null : (\n <button\n type=\"submit\"\n className=\"lk-wr-submit\"\n disabled={inactive || text.trim().length === 0}\n >\n {s.submit}\n </button>\n )}\n <FeedbackRegion id={`${data.id}-feedback`}>\n {isReview ? (\n outcome && (policy.feedback || !outcomeShowsMarks(outcome)) ? (\n <OutcomeSummary outcome={outcome} s={s} />\n ) : null\n ) : (\n summary\n )}\n </FeedbackRegion>\n </form>\n );\n}\n","'use client';\n\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport { ActivityErrorBoundary } from '../ActivityErrorBoundary.js';\nimport {\n WrittenResponse as WrittenResponseCore,\n type WrittenResponseProps,\n} from './WrittenResponse.js';\n\nexport type { HtmlSanitizer, Renderable, RenderMode } from '../types.js';\nexport type { WrittenResponseProps, WrittenResponseSubmission } from './WrittenResponse.js';\n\n/**\n * Public Written Response activity: a labelled textarea with a live word\n * counter for free-text writing graded asynchronously (AI or human). The core\n * is wrapped in `ActivityErrorBoundary` so a render failure (incl. the dev\n * schema-validation throw) degrades to an accessible fallback.\n */\nexport function WrittenResponse(props: WrittenResponseProps) {\n // Read here rather than in the boundary: a class component cannot call a\n // hook, and the fallback it renders is learner-facing text like any other.\n const strings = useLkStrings(props.strings);\n return (\n <ActivityErrorBoundary activityTitle={props.data?.title} strings={strings}>\n <WrittenResponseCore {...props} />\n </ActivityErrorBoundary>\n );\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  'use client';
2
- import { WrittenResponse } from './chunk-4NERCBOW.js';
3
- import { MultipleChoice } from './chunk-XHF376ES.js';
4
- import { FillInTheBlanks } from './chunk-SEQTGOOU.js';
5
- import { GapSelect } from './chunk-NLTU5JFD.js';
6
- import { Dictation } from './chunk-5QCZZBOX.js';
7
- import { ReadAloud } from './chunk-UXV3V5NH.js';
2
+ import { WrittenResponse } from './chunk-BGA2IVQY.js';
3
+ import { MultipleChoice } from './chunk-AG7MWZYZ.js';
4
+ import { FillInTheBlanks } from './chunk-3XP6VO4G.js';
5
+ import { GapSelect } from './chunk-IQ55QNBI.js';
6
+ import { Dictation } from './chunk-5GI53C6T.js';
7
+ import { ReadAloud } from './chunk-NWNQ2PHT.js';
8
8
  import { ActivityErrorBoundary } from './chunk-FEOFX4QW.js';
9
9
  import { useLkStrings } from './chunk-YRNEOBXA.js';
10
10
  import { validateDraft, evaluate, slotMediaKey } from '@intellectif/lk-core';
@@ -230,5 +230,5 @@ function contentKeyOf(value, enclosing = /* @__PURE__ */ new Set()) {
230
230
  }
231
231
 
232
232
  export { ActivityPreview };
233
- //# sourceMappingURL=chunk-7NNMDZUU.js.map
234
- //# sourceMappingURL=chunk-7NNMDZUU.js.map
233
+ //# sourceMappingURL=chunk-W6DMHN33.js.map
234
+ //# sourceMappingURL=chunk-W6DMHN33.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ActivityPreview/ActivityPreview.tsx"],"names":[],"mappings":"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","file":"chunk-7NNMDZUU.js","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. Nor does the\n * `question` a sequence hands a renderer: a preview is one question with no\n * set around it, so there is no slot to report to and nothing to page away\n * from. A renderer that uses it must treat it as optional, which its type\n * already says.\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":[],"mappings":"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","file":"chunk-W6DMHN33.js","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. Nor does the\n * `question` a sequence hands a renderer: a preview is one question with no\n * set around it, so there is no slot to report to and nothing to page away\n * from. A renderer that uses it must treat it as optional, which its type\n * already says.\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"]}
@@ -18,5 +18,5 @@ function takeOf(value) {
18
18
  }
19
19
 
20
20
  export { SequenceSlotContext, mintTake, stampTake, takeOf };
21
- //# sourceMappingURL=chunk-TEAVPUMX.js.map
22
- //# sourceMappingURL=chunk-TEAVPUMX.js.map
21
+ //# sourceMappingURL=chunk-WBLYD5QA.js.map
22
+ //# sourceMappingURL=chunk-WBLYD5QA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/shared/sequence-slot.ts"],"names":[],"mappings":";;;AAwDO,IAAM,mBAAA,GAAsB,cAA0C,IAAI;AASjF,IAAI,QAAA,GAAW,CAAA;AAGR,SAAS,QAAA,GAAmB;AACjC,EAAA,QAAA,IAAY,CAAA;AACZ,EAAA,OAAO,QAAA;AACT;AAOA,IAAM,KAAA,uBAAY,OAAA,EAAwB;AAGnC,SAAS,SAAA,CAA4B,OAAU,IAAA,EAAiB;AACrE,EAAA,KAAA,CAAM,GAAA,CAAI,OAAO,IAAI,CAAA;AACrB,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,OAAO,KAAA,EAAoC;AACzD,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,OAAO,KAAA,CAAM,GAAA,CAAI,KAAK,CAAA,GAAI,MAAA;AAC1E","file":"chunk-WBLYD5QA.js","sourcesContent":["'use client';\n\nimport type { ResolvedDeliveryPolicy } from '@intellectif/lk-core';\nimport { createContext } from 'react';\nimport type { RenderMode } from '../types.js';\n\n/**\n * How far a take that was handed in has got, as a pager deciding whether its\n * set is finished needs to know it.\n *\n * - `in-flight` — being stored or being judged. The set waits for it.\n * - `retryable` — it failed, and the learner is being offered another try at\n * the SAME take. The set waits for it while the learner is on that question.\n * - `settled` — nothing more will come of it: a grade, a take with no grade, a\n * failure nobody can retry, or a take the learner walked away from.\n */\nexport type TakeState = 'in-flight' | 'retryable' | 'settled';\n\n/**\n * What a pager hands the one slot it renders, and only through\n * {@link SequenceSlotContext} — never as a prop, so none of it can appear on a\n * public component's signature. A consumer string in any of it could stop\n * another component's microphone or finish another paper's set.\n */\nexport interface SequenceSlotChannel {\n /**\n * The capture-registry group whose captures stop when the slot's pane is\n * hidden. Minted per pager and per slot, so no two pagers share one.\n */\n readonly captureGroup: string;\n /**\n * The mode the PAPER around this question is being delivered in, read live.\n *\n * It is how the AI hooks know an exam they were not told about. A host that\n * draws its own question passes `renderMode` on to them, but nothing makes\n * it: the hooks would then default to `practice` and, under an\n * `LkAiProvider` somewhere above, offer hints on a paper of record. The set\n * around the question decides, and an `exam` here wins over anything the\n * caller passes or forgets to pass.\n */\n readonly renderMode: RenderMode;\n /**\n * The delivery policy of the PAPER around this question, read live, for the\n * same reason as the mode: whatever a host's own question was handed, the\n * paper's restrictions hold in it. See `useDeliveryPolicy`.\n */\n readonly delivery: ResolvedDeliveryPolicy;\n /**\n * Reports the state of the take numbered `take`, a number from\n * {@link mintTake}. A take numbered below the slot's latest is a take the\n * learner has since replaced, and the pager ignores it.\n */\n takeState(take: number, state: TakeState): void;\n}\n\n/** `null` outside a pager: a standalone component belongs to no slot. */\nexport const SequenceSlotContext = createContext<SequenceSlotChannel | null>(null);\n\n/**\n * The last take number handed out. Module-level and never reset, so a number\n * is unique for the life of the page: across mounts, across papers, and across\n * two pagers side by side. A result can therefore only ever match the take that\n * produced it, whatever slot and activity ids a later paper reuses — ids a host\n * chooses, and can repeat, never decide it.\n */\nlet lastTake = 0;\n\n/** A take number no other take on this page has had, or will have. */\nexport function mintTake(): number {\n lastTake += 1;\n return lastTake;\n}\n\n/**\n * The take each reported value belongs to. A `WeakMap` rather than a field, so\n * a response or a result a host receives carries no extra key it would persist\n * or compare, and the number never outlives the object.\n */\nconst takes = new WeakMap<object, number>();\n\n/** Marks `value` as produced by take `take`, and returns it. */\nexport function stampTake<T extends object>(value: T, take: number): T {\n takes.set(value, take);\n return value;\n}\n\n/** The take `value` was produced by, or `undefined` when nothing stamped it. */\nexport function takeOf(value: unknown): number | undefined {\n return typeof value === 'object' && value !== null ? takes.get(value) : undefined;\n}\n"]}
@@ -1,21 +1,21 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunk55W2472T_cjs = require('../chunk-55W2472T.cjs');
5
- require('../chunk-CQNKZ435.cjs');
6
- require('../chunk-ZME5FMED.cjs');
7
- require('../chunk-XUQ4KRTT.cjs');
8
- require('../chunk-XAIJNGTU.cjs');
9
- require('../chunk-NGFTSRKO.cjs');
10
- require('../chunk-KGDGYRBL.cjs');
11
- require('../chunk-SXU26SFO.cjs');
4
+ var chunkLK5VXNMR_cjs = require('../chunk-LK5VXNMR.cjs');
5
+ require('../chunk-UHIOVOFK.cjs');
6
+ require('../chunk-JLDSCHY5.cjs');
7
+ require('../chunk-6S2CKZ4H.cjs');
8
+ require('../chunk-CEUEXISZ.cjs');
9
+ require('../chunk-HREA5SMB.cjs');
10
+ require('../chunk-NOC2M6LU.cjs');
11
+ require('../chunk-TRMWBJWT.cjs');
12
12
  require('../chunk-ZDYNAWDZ.cjs');
13
- require('../chunk-NZM3M5IR.cjs');
13
+ require('../chunk-RT2PP4SO.cjs');
14
14
  require('../chunk-LX2X4KC7.cjs');
15
15
  require('../chunk-UDCQTOVU.cjs');
16
16
  require('../chunk-OD65OZIW.cjs');
17
- require('../chunk-JVWLXVYG.cjs');
18
- require('../chunk-BRPEB43C.cjs');
17
+ require('../chunk-IXMT7X3E.cjs');
18
+ require('../chunk-BJLQKJZX.cjs');
19
19
  require('../chunk-APZ6JFN6.cjs');
20
20
  require('../chunk-EANGKAKG.cjs');
21
21
  require('../chunk-L7WY5YFQ.cjs');
@@ -26,7 +26,7 @@ require('../chunk-AHGB5HH6.cjs');
26
26
 
27
27
  Object.defineProperty(exports, "ActivityPreview", {
28
28
  enumerable: true,
29
- get: function () { return chunk55W2472T_cjs.ActivityPreview; }
29
+ get: function () { return chunkLK5VXNMR_cjs.ActivityPreview; }
30
30
  });
31
31
  //# sourceMappingURL=ActivityPreview.cjs.map
32
32
  //# sourceMappingURL=ActivityPreview.cjs.map
@@ -1,11 +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 '../types-DtPYG1hh.cjs';
4
+ import { e as RenderMode, H as HtmlSanitizer, a as LkStringsOverride } from '../types-B_PCcqO-.cjs';
5
5
  import { ActivityRenderer } from './ActivitySequence.cjs';
6
6
  import '../ai/LkAiProvider.cjs';
7
7
  import '../machine-CuwKqWXC.cjs';
8
- import '../WrittenResponse-DT_Yqbq1.cjs';
8
+ import '../WrittenResponse-obIDDYDH.cjs';
9
9
 
10
10
  interface ActivityPreviewProps {
11
11
  /**
@@ -1,11 +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 '../types-BY-4S5Rd.js';
4
+ import { e as RenderMode, H as HtmlSanitizer, a as LkStringsOverride } from '../types-C-GMCJ0g.js';
5
5
  import { ActivityRenderer } from './ActivitySequence.js';
6
6
  import '../ai/LkAiProvider.js';
7
7
  import '../machine-CuwKqWXC.js';
8
- import '../WrittenResponse-CeHY5u3W.js';
8
+ import '../WrittenResponse-D2YI8xOK.js';
9
9
 
10
10
  interface ActivityPreviewProps {
11
11
  /**
@@ -1,19 +1,19 @@
1
1
  'use client';
2
- export { ActivityPreview } from '../chunk-7NNMDZUU.js';
3
- import '../chunk-4NERCBOW.js';
4
- import '../chunk-XHF376ES.js';
5
- import '../chunk-SEQTGOOU.js';
6
- import '../chunk-NLTU5JFD.js';
7
- import '../chunk-5QCZZBOX.js';
8
- import '../chunk-QRT2W5N5.js';
9
- import '../chunk-YIYMBCPV.js';
2
+ export { ActivityPreview } from '../chunk-W6DMHN33.js';
3
+ import '../chunk-BGA2IVQY.js';
4
+ import '../chunk-AG7MWZYZ.js';
5
+ import '../chunk-3XP6VO4G.js';
6
+ import '../chunk-IQ55QNBI.js';
7
+ import '../chunk-5GI53C6T.js';
8
+ import '../chunk-RUS42NMN.js';
9
+ import '../chunk-AQIAQHJC.js';
10
10
  import '../chunk-YNDKAYW3.js';
11
- import '../chunk-UXV3V5NH.js';
11
+ import '../chunk-NWNQ2PHT.js';
12
12
  import '../chunk-G7AGM2Y7.js';
13
13
  import '../chunk-MCO52PV5.js';
14
14
  import '../chunk-YORQQXGO.js';
15
- import '../chunk-TEAVPUMX.js';
16
- import '../chunk-RCMYEWBE.js';
15
+ import '../chunk-ORBU3XKH.js';
16
+ import '../chunk-WBLYD5QA.js';
17
17
  import '../chunk-FEOFX4QW.js';
18
18
  import '../chunk-PPFVTXGJ.js';
19
19
  import '../chunk-BY4UQH2Y.js';
@@ -1,22 +1,22 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunk2X2NZF46_cjs = require('../chunk-2X2NZF46.cjs');
4
+ var chunkPWLJDP3X_cjs = require('../chunk-PWLJDP3X.cjs');
5
5
  require('../chunk-3FBBP5QR.cjs');
6
- require('../chunk-CQNKZ435.cjs');
7
- require('../chunk-ZME5FMED.cjs');
8
- require('../chunk-XUQ4KRTT.cjs');
9
- require('../chunk-XAIJNGTU.cjs');
10
- require('../chunk-NGFTSRKO.cjs');
11
- require('../chunk-KGDGYRBL.cjs');
12
- require('../chunk-SXU26SFO.cjs');
6
+ require('../chunk-UHIOVOFK.cjs');
7
+ require('../chunk-JLDSCHY5.cjs');
8
+ require('../chunk-6S2CKZ4H.cjs');
9
+ require('../chunk-CEUEXISZ.cjs');
10
+ require('../chunk-HREA5SMB.cjs');
11
+ require('../chunk-NOC2M6LU.cjs');
12
+ require('../chunk-TRMWBJWT.cjs');
13
13
  require('../chunk-ZDYNAWDZ.cjs');
14
- require('../chunk-NZM3M5IR.cjs');
14
+ require('../chunk-RT2PP4SO.cjs');
15
15
  require('../chunk-LX2X4KC7.cjs');
16
16
  require('../chunk-UDCQTOVU.cjs');
17
17
  require('../chunk-OD65OZIW.cjs');
18
- require('../chunk-JVWLXVYG.cjs');
19
- require('../chunk-BRPEB43C.cjs');
18
+ require('../chunk-IXMT7X3E.cjs');
19
+ require('../chunk-BJLQKJZX.cjs');
20
20
  require('../chunk-APZ6JFN6.cjs');
21
21
  require('../chunk-EANGKAKG.cjs');
22
22
  require('../chunk-L7WY5YFQ.cjs');
@@ -27,7 +27,7 @@ require('../chunk-AHGB5HH6.cjs');
27
27
 
28
28
  Object.defineProperty(exports, "ActivitySequence", {
29
29
  enumerable: true,
30
- get: function () { return chunk2X2NZF46_cjs.ActivitySequence; }
30
+ get: function () { return chunkPWLJDP3X_cjs.ActivitySequence; }
31
31
  });
32
32
  //# sourceMappingURL=ActivitySequence.cjs.map
33
33
  //# sourceMappingURL=ActivitySequence.cjs.map
@@ -1,8 +1,8 @@
1
- import { InteractionKind, SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
1
+ import { InteractionKind, SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, DeliveryPolicy, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
2
2
  import { ComponentType } from 'react';
3
3
  import { LearnerAi } from '../ai/LkAiProvider.cjs';
4
- import { A as ActivityProps, i as SequenceRecordingSlot, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../types-DtPYG1hh.cjs';
5
- import { a as WrittenResponseSubmission } from '../WrittenResponse-DT_Yqbq1.cjs';
4
+ import { A as ActivityProps, i as SequenceRecordingSlot, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../types-B_PCcqO-.cjs';
5
+ import { a as WrittenResponseSubmission } from '../WrittenResponse-obIDDYDH.cjs';
6
6
  import '../machine-CuwKqWXC.cjs';
7
7
 
8
8
  /**
@@ -313,6 +313,18 @@ interface ActivitySequenceProps {
313
313
  * See {@link LearnerAi}.
314
314
  */
315
315
  ai?: LearnerAi;
316
+ /**
317
+ * What the school running this paper lets a learner see — feedback,
318
+ * solutions, hints, AI help — for every question in it. Each setting only
319
+ * takes away from what `renderMode` shows; an absent policy takes nothing.
320
+ *
321
+ * It holds in every question however it is drawn: the SDK's own components
322
+ * and a `renderers` override are handed it as `delivery`, and a question
323
+ * that ignores what it was handed still cannot show AI help the paper
324
+ * forbids. Record the same policy in the attempt with
325
+ * `planAttempt(entries, { delivery })`. See `DeliveryPolicy` in lk-core.
326
+ */
327
+ delivery?: DeliveryPolicy | null;
316
328
  /**
317
329
  * `entries` shuffles the top-level entries; a group moves as one block, and
318
330
  * the order INSIDE a group follows the group's own `shuffle` setting.
@@ -397,6 +409,6 @@ interface ActivitySequenceProps {
397
409
  locale?: string;
398
410
  disabled?: boolean;
399
411
  }
400
- 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;
412
+ 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, delivery, }: ActivitySequenceProps): React.JSX.Element;
401
413
 
402
414
  export { type ActivityRenderer, ActivitySequence, type ActivitySequenceProps, type SequenceItemOutcome, type SequenceQuestion };
@@ -1,8 +1,8 @@
1
- import { InteractionKind, SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
1
+ import { InteractionKind, SequenceEntry, ActivityResult, LearnerResponse, InteractionEvent, SpeechAssessment, DeliveryPolicy, ItemOutcome, ThemeTokens } from '@intellectif/lk-core';
2
2
  import { ComponentType } from 'react';
3
3
  import { LearnerAi } from '../ai/LkAiProvider.js';
4
- import { A as ActivityProps, i as SequenceRecordingSlot, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../types-BY-4S5Rd.js';
5
- import { a as WrittenResponseSubmission } from '../WrittenResponse-CeHY5u3W.js';
4
+ import { A as ActivityProps, i as SequenceRecordingSlot, g as RenderableActivity, e as RenderMode, S as SequenceMediaBudget, h as SequenceRecordingBinding, a as LkStringsOverride, H as HtmlSanitizer } from '../types-C-GMCJ0g.js';
5
+ import { a as WrittenResponseSubmission } from '../WrittenResponse-D2YI8xOK.js';
6
6
  import '../machine-CuwKqWXC.js';
7
7
 
8
8
  /**
@@ -313,6 +313,18 @@ interface ActivitySequenceProps {
313
313
  * See {@link LearnerAi}.
314
314
  */
315
315
  ai?: LearnerAi;
316
+ /**
317
+ * What the school running this paper lets a learner see — feedback,
318
+ * solutions, hints, AI help — for every question in it. Each setting only
319
+ * takes away from what `renderMode` shows; an absent policy takes nothing.
320
+ *
321
+ * It holds in every question however it is drawn: the SDK's own components
322
+ * and a `renderers` override are handed it as `delivery`, and a question
323
+ * that ignores what it was handed still cannot show AI help the paper
324
+ * forbids. Record the same policy in the attempt with
325
+ * `planAttempt(entries, { delivery })`. See `DeliveryPolicy` in lk-core.
326
+ */
327
+ delivery?: DeliveryPolicy | null;
316
328
  /**
317
329
  * `entries` shuffles the top-level entries; a group moves as one block, and
318
330
  * the order INSIDE a group follows the group's own `shuffle` setting.
@@ -397,6 +409,6 @@ interface ActivitySequenceProps {
397
409
  locale?: string;
398
410
  disabled?: boolean;
399
411
  }
400
- 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;
412
+ 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, delivery, }: ActivitySequenceProps): React.JSX.Element;
401
413
 
402
414
  export { type ActivityRenderer, ActivitySequence, type ActivitySequenceProps, type SequenceItemOutcome, type SequenceQuestion };
@@ -1,20 +1,20 @@
1
1
  'use client';
2
- export { ActivitySequence } from '../chunk-OWV7VRMQ.js';
2
+ export { ActivitySequence } from '../chunk-QKW2GGTV.js';
3
3
  import '../chunk-7K4B2EMU.js';
4
- import '../chunk-4NERCBOW.js';
5
- import '../chunk-XHF376ES.js';
6
- import '../chunk-SEQTGOOU.js';
7
- import '../chunk-NLTU5JFD.js';
8
- import '../chunk-5QCZZBOX.js';
9
- import '../chunk-QRT2W5N5.js';
10
- import '../chunk-YIYMBCPV.js';
4
+ import '../chunk-BGA2IVQY.js';
5
+ import '../chunk-AG7MWZYZ.js';
6
+ import '../chunk-3XP6VO4G.js';
7
+ import '../chunk-IQ55QNBI.js';
8
+ import '../chunk-5GI53C6T.js';
9
+ import '../chunk-RUS42NMN.js';
10
+ import '../chunk-AQIAQHJC.js';
11
11
  import '../chunk-YNDKAYW3.js';
12
- import '../chunk-UXV3V5NH.js';
12
+ import '../chunk-NWNQ2PHT.js';
13
13
  import '../chunk-G7AGM2Y7.js';
14
14
  import '../chunk-MCO52PV5.js';
15
15
  import '../chunk-YORQQXGO.js';
16
- import '../chunk-TEAVPUMX.js';
17
- import '../chunk-RCMYEWBE.js';
16
+ import '../chunk-ORBU3XKH.js';
17
+ import '../chunk-WBLYD5QA.js';
18
18
  import '../chunk-FEOFX4QW.js';
19
19
  import '../chunk-PPFVTXGJ.js';
20
20
  import '../chunk-BY4UQH2Y.js';
@@ -1,13 +1,13 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkNGFTSRKO_cjs = require('../chunk-NGFTSRKO.cjs');
5
- require('../chunk-KGDGYRBL.cjs');
6
- require('../chunk-SXU26SFO.cjs');
4
+ var chunkHREA5SMB_cjs = require('../chunk-HREA5SMB.cjs');
5
+ require('../chunk-NOC2M6LU.cjs');
6
+ require('../chunk-TRMWBJWT.cjs');
7
7
  require('../chunk-ZDYNAWDZ.cjs');
8
8
  require('../chunk-OD65OZIW.cjs');
9
- require('../chunk-JVWLXVYG.cjs');
10
- require('../chunk-BRPEB43C.cjs');
9
+ require('../chunk-IXMT7X3E.cjs');
10
+ require('../chunk-BJLQKJZX.cjs');
11
11
  require('../chunk-APZ6JFN6.cjs');
12
12
  require('../chunk-EANGKAKG.cjs');
13
13
  require('../chunk-L7WY5YFQ.cjs');
@@ -18,7 +18,7 @@ require('../chunk-AHGB5HH6.cjs');
18
18
 
19
19
  Object.defineProperty(exports, "Dictation", {
20
20
  enumerable: true,
21
- get: function () { return chunkNGFTSRKO_cjs.Dictation; }
21
+ get: function () { return chunkHREA5SMB_cjs.Dictation; }
22
22
  });
23
23
  //# sourceMappingURL=Dictation.cjs.map
24
24
  //# sourceMappingURL=Dictation.cjs.map
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { DictationData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../types-DtPYG1hh.cjs';
3
+ import { A as ActivityProps } from '../types-B_PCcqO-.cjs';
4
4
  import '../ai/LkAiProvider.cjs';
5
5
  import 'react';
6
6
  import '../machine-CuwKqWXC.cjs';
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { DictationData } from '@intellectif/lk-core';
3
- import { A as ActivityProps } from '../types-BY-4S5Rd.js';
3
+ import { A as ActivityProps } from '../types-C-GMCJ0g.js';
4
4
  import '../ai/LkAiProvider.js';
5
5
  import 'react';
6
6
  import '../machine-CuwKqWXC.js';
@@ -1,11 +1,11 @@
1
1
  'use client';
2
- export { Dictation } from '../chunk-5QCZZBOX.js';
3
- import '../chunk-QRT2W5N5.js';
4
- import '../chunk-YIYMBCPV.js';
2
+ export { Dictation } from '../chunk-5GI53C6T.js';
3
+ import '../chunk-RUS42NMN.js';
4
+ import '../chunk-AQIAQHJC.js';
5
5
  import '../chunk-YNDKAYW3.js';
6
6
  import '../chunk-YORQQXGO.js';
7
- import '../chunk-TEAVPUMX.js';
8
- import '../chunk-RCMYEWBE.js';
7
+ import '../chunk-ORBU3XKH.js';
8
+ import '../chunk-WBLYD5QA.js';
9
9
  import '../chunk-FEOFX4QW.js';
10
10
  import '../chunk-PPFVTXGJ.js';
11
11
  import '../chunk-BY4UQH2Y.js';
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkXUQ4KRTT_cjs = require('../chunk-XUQ4KRTT.cjs');
5
- require('../chunk-KGDGYRBL.cjs');
6
- require('../chunk-SXU26SFO.cjs');
4
+ var chunk6S2CKZ4H_cjs = require('../chunk-6S2CKZ4H.cjs');
5
+ require('../chunk-NOC2M6LU.cjs');
6
+ require('../chunk-TRMWBJWT.cjs');
7
7
  require('../chunk-ZDYNAWDZ.cjs');
8
- require('../chunk-JVWLXVYG.cjs');
9
- require('../chunk-BRPEB43C.cjs');
8
+ require('../chunk-IXMT7X3E.cjs');
9
+ require('../chunk-BJLQKJZX.cjs');
10
10
  require('../chunk-APZ6JFN6.cjs');
11
11
  require('../chunk-EANGKAKG.cjs');
12
12
  require('../chunk-L7WY5YFQ.cjs');
@@ -17,7 +17,7 @@ require('../chunk-AHGB5HH6.cjs');
17
17
 
18
18
  Object.defineProperty(exports, "FillInTheBlanks", {
19
19
  enumerable: true,
20
- get: function () { return chunkXUQ4KRTT_cjs.FillInTheBlanks; }
20
+ get: function () { return chunk6S2CKZ4H_cjs.FillInTheBlanks; }
21
21
  });
22
22
  //# sourceMappingURL=FillInTheBlanks.cjs.map
23
23
  //# sourceMappingURL=FillInTheBlanks.cjs.map