@citolab/qti-components 7.28.1 → 8.0.1
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/cdn/index.global.js +1 -1
- package/cdn/index.js +6316 -2710
- package/dist/base.d.ts +100 -15
- package/dist/base.js +27 -6
- package/dist/chunk-3AJOQCDU.js +11 -0
- package/dist/chunk-3AJOQCDU.js.map +1 -0
- package/dist/chunk-64XSIBGO.js +241 -0
- package/dist/chunk-64XSIBGO.js.map +1 -0
- package/dist/chunk-7HC5SMCU.js +102 -0
- package/dist/chunk-7HC5SMCU.js.map +1 -0
- package/dist/{chunk-SP6S2WMG.js → chunk-7V4HJFHW.js} +3 -3
- package/dist/{chunk-SP6S2WMG.js.map → chunk-7V4HJFHW.js.map} +1 -1
- package/dist/chunk-CAO4JRLY.js +11 -0
- package/dist/chunk-CAO4JRLY.js.map +1 -0
- package/dist/{chunk-MPC7LIPC.js → chunk-F4BNJWYN.js} +4264 -3647
- package/dist/chunk-F4BNJWYN.js.map +1 -0
- package/dist/{chunk-3XV26R5M.js → chunk-H3J7LFRO.js} +829 -1005
- package/dist/chunk-H3J7LFRO.js.map +1 -0
- package/dist/{chunk-3WBG257S.js → chunk-IJD53WY6.js} +96 -74
- package/dist/chunk-IJD53WY6.js.map +1 -0
- package/dist/chunk-LVBIQDPM.js +1374 -0
- package/dist/chunk-LVBIQDPM.js.map +1 -0
- package/dist/{chunk-REI3AMCZ.js → chunk-NA2N2WSG.js} +1303 -1193
- package/dist/chunk-NA2N2WSG.js.map +1 -0
- package/dist/chunk-QECOPVPO.js +294 -0
- package/dist/chunk-QECOPVPO.js.map +1 -0
- package/dist/{chunk-HFCZFWSH.js → chunk-RXGDQDOV.js} +1993 -1764
- package/dist/chunk-RXGDQDOV.js.map +1 -0
- package/dist/chunk-V5G7X53Y.js +11 -0
- package/dist/chunk-V5G7X53Y.js.map +1 -0
- package/dist/{chunk-WDO2TRFM.js → chunk-WVVMNF74.js} +851 -925
- package/dist/chunk-WVVMNF74.js.map +1 -0
- package/dist/{chunk-FLJAKWXL.js → chunk-X3E5HXG2.js} +2 -2
- package/dist/chunk-XU7HNT4F.js +1608 -0
- package/dist/chunk-XU7HNT4F.js.map +1 -0
- package/dist/{computed-item.context-DfsW_96S.d.ts → computed-item.types.d-BKZdSLLJ.d.ts} +2 -5
- package/dist/{computed.context-DHbxad0N.d.ts → computed.types.d-rKLSPvVG.d.ts} +2 -5
- package/dist/config.context.d-BvU9r-Mg.d.ts +91 -0
- package/dist/corrections.d.ts +432 -0
- package/dist/corrections.js +84 -0
- package/dist/elements.d.ts +8 -14
- package/dist/elements.js +6 -5
- package/dist/index.d.ts +51 -16
- package/dist/index.js +193 -76
- package/dist/interaction.d-D4MstYRz.d.ts +115 -0
- package/dist/interaction.interface.d-CvjHM2bi.d.ts +46 -0
- package/dist/interactions.d.ts +1206 -552
- package/dist/interactions.js +19 -15
- package/dist/item.css +4228 -1656
- package/dist/item.d.ts +13 -55
- package/dist/item.js +6 -11
- package/dist/{variables-CMYcDbyW.d.ts → item.types.d-QU7LljEK.d.ts} +13 -1
- package/dist/loader.d.ts +4 -4
- package/dist/loader.js +2 -3
- package/dist/processing.d.ts +6 -7
- package/dist/processing.js +2 -3
- package/dist/qti-components-jsx.d.ts +5348 -2709
- package/dist/qti-components-jsx.js +1 -0
- package/dist/qti-condition-expression.d-aMvBvpc6.d.ts +8 -0
- package/dist/{qti-condition-expression-Dam-RER6.d.ts → qti-expression.d-BietT_8b.d.ts} +14 -9
- package/dist/{qti-feedback-ChmXhZuf.d.ts → qti-feedback.d-DZbad0RN.d.ts} +1 -1
- package/dist/{qti-transform-test-DoZaWItm.d.ts → qti-transform-test.d-BL7GGFJj.d.ts} +2 -2
- package/dist/response.d-_8y4kjGP.d.ts +106 -0
- package/dist/test.d.ts +199 -39
- package/dist/test.js +34 -11
- package/dist/transformers.d.ts +1 -1
- package/dist/transformers.js +1 -2
- package/package.json +24 -17
- package/custom-elements.json +0 -43251
- package/dist/chunk-3WBG257S.js.map +0 -1
- package/dist/chunk-3XV26R5M.js.map +0 -1
- package/dist/chunk-AQ5RJFM6.js +0 -3673
- package/dist/chunk-AQ5RJFM6.js.map +0 -1
- package/dist/chunk-HFCZFWSH.js.map +0 -1
- package/dist/chunk-MPC7LIPC.js.map +0 -1
- package/dist/chunk-QXBXORM3.js +0 -27
- package/dist/chunk-REI3AMCZ.js.map +0 -1
- package/dist/chunk-RLTYVS2I.js +0 -530
- package/dist/chunk-RLTYVS2I.js.map +0 -1
- package/dist/chunk-WDO2TRFM.js.map +0 -1
- package/dist/config.context-BjZ2bZSY.d.ts +0 -42
- package/dist/interaction-Bgzlw7Iu.d.ts +0 -110
- package/dist/item.context-CkUeDcaO.d.ts +0 -15
- package/dist/test.context-CByZZjkR.d.ts +0 -15
- /package/dist/{chunk-FLJAKWXL.js.map → chunk-X3E5HXG2.js.map} +0 -0
- /package/dist/{chunk-QXBXORM3.js.map → corrections.js.map} +0 -0
- /package/dist/{qti-rule-base-ajOnfGXY.d.ts → qti-rule-base.d-ajOnfGXY.d.ts} +0 -0
- /package/dist/{qti.context-CejJMlfZ.d.ts → qti.context.d-CejJMlfZ.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../qti-corrections/src/mixins/correct-response.mixin.ts","../../qti-corrections/src/styles/correction.styles.ts","../../qti-corrections/src/mixins/candidate-correction.mixin.ts","../../qti-corrections/src/mixins/choice-correction.mixin.ts","../../qti-corrections/src/mixins/active-element-correction.mixin.ts","../../qti-corrections/src/elements/qti-gap-text-correction.ts","../../qti-corrections/src/elements/qti-hotspot-choice-correction.ts","../../qti-corrections/src/elements/qti-hottext-correction.ts","../../qti-corrections/src/elements/qti-simple-associable-choice-correction.ts","../../qti-corrections/src/elements/qti-simple-choice-correction.ts","../../qti-corrections/src/components/qti-assessment-item-correction.ts","../../qti-corrections/src/components/qti-item-correction.ts","../../qti-corrections/src/components/test-correction-elements.ts","../../qti-corrections/src/components/item-correct-response-mode/item-correct-response-mode.ts","../../qti-corrections/src/components/styles.ts","../../qti-corrections/src/components/item-show-candidate-correction/item-show-candidate-correction.ts","../../qti-corrections/src/components/item-show-correct-response/item-show-correct-response.ts","../../qti-corrections/src/components/test-show-correct-response/test-show-correct-response.ts","../../qti-corrections/src/mixins/drag-drop-correction.mixin.ts","../../qti-corrections/src/interactions/qti-associate-interaction-correction.ts","../../qti-corrections/src/interactions/qti-choice-interaction-correction.ts","../../qti-corrections/src/interactions/qti-extended-text-interaction-correction.ts","../../qti-corrections/src/interactions/shared.ts","../../qti-corrections/src/interactions/qti-gap-match-interaction-correction.ts","../../qti-corrections/src/interactions/qti-graphic-associate-interaction-correction.ts","../../qti-corrections/src/interactions/qti-graphic-gap-match-interaction-correction.ts","../../qti-corrections/src/interactions/qti-graphic-order-interaction-correction.ts","../../qti-corrections/src/interactions/qti-hotspot-interaction-correction.ts","../../qti-corrections/src/interactions/qti-hottext-interaction-correction.ts","../../qti-corrections/src/interactions/qti-inline-choice-interaction-correction.ts","../../qti-corrections/src/interactions/qti-match-interaction-correction.ts","../../qti-corrections/src/utils/longest-increasing-subsequence.ts","../../qti-corrections/src/interactions/qti-order-interaction-correction.ts","../../qti-corrections/src/interactions/qti-portable-custom-interaction-correction.ts","../../qti-corrections/src/interactions/qti-select-point-interaction-correction.ts","../../qti-corrections/src/interactions/qti-slider-interaction-correction.ts","../../qti-corrections/src/interactions/qti-text-entry-interaction-correction.ts"],"sourcesContent":["import { property, state } from 'lit/decorators.js';\n\nimport { watch } from '@qti-components/utilities';\nimport { responseAttributeConverter, type Interaction, type ResponseValue } from '@qti-components/base';\n\nimport type { CorrectionConfig } from '../context/correction-config';\n\ntype AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;\n\nexport enum Correctness {\n Correct = 'correct',\n PartiallyCorrect = 'partially-correct',\n Incorrect = 'incorrect'\n}\n\n/**\n * Adds correct-response and full-correct-response behaviour\n * on top of any `Interaction` subclass.\n *\n * Usage:\n * ```ts\n * export abstract class CorrectableInteraction extends CorrectResponseMixin(Interaction) {}\n * ```\n *\n * Interactions that genuinely have no correct-response concept\n * (extended-text, upload, media) should extend `Interaction` directly\n * and omit this mixin.\n */\nexport const CorrectResponseMixin = <T extends AbstractConstructor<Interaction>>(superClass: T) => {\n abstract class CorrectResponseMixinClass extends superClass {\n // ─── Correct-response attribute ──────────────────────────────────────────\n\n /**\n * The correct response for this interaction. Can be set as a comma-separated\n * string via attribute or as string/string[] via property.\n *\n * @example\n * ```html\n * <qti-choice-interaction correct-response=\"A,B\">\n * ```\n */\n @property({\n attribute: 'correct-response',\n reflect: true,\n converter: responseAttributeConverter({ emptyAs: null })\n })\n set correctResponseAttr(val: ResponseValue) {\n this._correctResponse = val;\n }\n\n get correctResponseAttr(): ResponseValue {\n return this._correctResponse;\n }\n\n // ─── Show-correct-response ────────────────────────────────────────────────\n\n @property({ type: Boolean, attribute: 'show-correct-response', reflect: true })\n showCorrectResponse = false;\n\n @watch('showCorrectResponse', { waitUntilFirstUpdate: true })\n protected _handleShowCorrectResponseChange = (_: boolean, show: boolean) => {\n this.toggleInternalCorrectResponse(show);\n };\n\n // ─── Show-full-correct-response ───────────────────────────────────────────\n\n @property({ type: Boolean, attribute: 'show-full-correct-response', reflect: true })\n showFullCorrectResponse = false;\n\n @watch('showFullCorrectResponse', { waitUntilFirstUpdate: true })\n protected _handleShowFullCorrectResponseChange = (_: boolean, show: boolean) => {\n this.toggleFullCorrectResponse(show);\n };\n\n // ─── Show-candidate-correction ────────────────────────────────────────────\n\n @property({ type: Boolean, attribute: 'show-candidate-correction', reflect: true })\n showCandidateCorrection = false;\n\n @watch('showCandidateCorrection', { waitUntilFirstUpdate: true })\n protected _handleShowCandidateCorrectionChange = (_: boolean, show: boolean) => {\n this.toggleCandidateCorrection(show);\n };\n\n // ─── isFullCorrectResponse ────────────────────────────────────────────────\n\n @state()\n protected _isFullCorrectResponse: boolean;\n\n get isFullCorrectResponse(): boolean {\n return this._isFullCorrectResponse;\n }\n\n protected override get registersWithItem(): boolean {\n return !this.isFullCorrectResponse && super.registersWithItem;\n }\n\n set isFullCorrectResponse(val: boolean) {\n this._isFullCorrectResponse = val;\n if (val) {\n // `inert` already makes the answer-key clone non-interactive. Do NOT also set `disabled`:\n // it would mark every choice `:state(disabled)`, which the theme dims (opacity), fading the\n // answer key that is meant to be crisp. inert is enough.\n this.setAttribute('inert', '');\n this.setAttribute('response-identifier', this.responseIdentifier + '_cr');\n // An answer key shows the answer, not the means of giving one, so every drag-drop\n // interaction hides its chip bank here. Each one does that in its own stylesheet, keyed on\n // this attribute — hiding removes a box from the flow, which makes it layout, and layout is\n // not the theme's to declare (CONTRACT.md §7).\n //\n // The class the theme used instead, `.full-correct-response`, is on the wrapper *around*\n // this element, so only a document selector could see it. This attribute is on the clone\n // itself, which is what a shadow root can reach.\n this.setAttribute('answer-key', '');\n }\n }\n\n // ─── correctResponse property ─────────────────────────────────────────────\n\n @state()\n protected _correctResponse: string | string[] | null = null;\n\n get correctResponse(): Readonly<string | string[] | null> {\n const responseVariable = this.responseVariable;\n if (responseVariable?.correctResponse) {\n return responseVariable.correctResponse;\n }\n return this._correctResponse;\n }\n\n set correctResponse(val: Readonly<string | string[] | null>) {\n const oldVal = this._correctResponse;\n this._correctResponse = val as string | string[] | null;\n if (val === null || val === undefined) {\n this.removeAttribute('correct-response');\n } else {\n this.setAttribute('correct-response', Array.isArray(val) ? val.join(',') : (val as string));\n }\n this.requestUpdate('_correctResponse', oldVal);\n }\n\n // ─── correctness getter ───────────────────────────────────────────────────\n\n get correctness(): Readonly<Correctness | null> {\n const correctResponse = this.correctResponse;\n if (!correctResponse) return null;\n\n const currentResponse = this.response;\n if (\n currentResponse === null ||\n currentResponse === undefined ||\n currentResponse === '' ||\n (Array.isArray(currentResponse) && currentResponse.length === 0)\n ) {\n return null;\n }\n\n const correctArr = Array.isArray(correctResponse) ? correctResponse : [correctResponse];\n const responseArr = Array.isArray(currentResponse) ? currentResponse : [currentResponse];\n const filteredResponseArr = responseArr.filter(r => r !== '');\n if (filteredResponseArr.length === 0) return null;\n\n const correctCount = filteredResponseArr.filter(r => correctArr.includes(r)).length;\n const incorrectCount = filteredResponseArr.filter(r => !correctArr.includes(r)).length;\n\n if (\n correctCount === correctArr.length &&\n incorrectCount === 0 &&\n filteredResponseArr.length === correctArr.length\n ) {\n return Correctness.Correct;\n }\n\n if (correctCount > 0 && (correctCount < correctArr.length || incorrectCount > 0)) {\n return Correctness.PartiallyCorrect;\n }\n\n return Correctness.Incorrect;\n }\n\n // ─── correctionPart ───────────────────────────────────────────────────────\n\n public get correctionPart(): string {\n return 'correction';\n }\n\n // ─── toggle methods ───────────────────────────────────────────────────────\n\n public toggleCorrectResponse(show: boolean): void {\n const correctionConfig = this.configContext as CorrectionConfig | undefined;\n const correctResponseMode = correctionConfig?.correctResponseMode || 'internal';\n\n if (correctResponseMode === 'full') {\n this.toggleFullCorrectResponse(show);\n } else {\n this.toggleInternalCorrectResponse(show);\n }\n }\n\n /**\n * Whether the full correct response is withheld from a candidate who is already correct.\n *\n * Withheld by default, unless the item configures `fullCorrectResponseOnlyWhenIncorrect: false`\n * — the behaviour `show-full-correct-response` has always had, on the reasoning that a correct\n * answer already *is* the key.\n *\n * An interaction that routes its internal mode here overrides this to false: there, the caller\n * asked to show the correct response, and silently showing nothing is worse than showing the\n * candidate the answer they already gave.\n */\n protected get withholdsFullCorrectResponseWhenCorrect(): boolean {\n return (this.configContext as CorrectionConfig | undefined)?.fullCorrectResponseOnlyWhenIncorrect !== false;\n }\n\n protected async toggleFullCorrectResponse(show: boolean): Promise<void> {\n const nextSibling = this.nextSibling;\n const nextSiblingIsFullCorrectResponse =\n nextSibling instanceof HTMLDivElement && nextSibling?.classList.contains('full-correct-response');\n\n const correctResponse = this.correctResponse;\n\n if (!correctResponse) {\n return;\n }\n\n const showFullCorrectResponse =\n show && (!this.withholdsFullCorrectResponseWhenCorrect || this.correctness !== Correctness.Correct);\n\n if (!showFullCorrectResponse) {\n if (!nextSiblingIsFullCorrectResponse) {\n return;\n }\n this.parentElement?.removeChild(nextSibling);\n return;\n }\n\n if (nextSiblingIsFullCorrectResponse) {\n return;\n }\n\n const clone = this.cloneNode(true) as Interaction & CorrectResponseMixinClass;\n\n clone.removeAttribute('show-full-correct-response');\n clone.removeAttribute('show-correct-response');\n clone.removeAttribute('show-candidate-correction');\n\n const containerDiv = document.createElement('div');\n containerDiv.classList.add('full-correct-response');\n if (this.isInline) {\n containerDiv.classList.add('full-correct-response-inline');\n } else {\n containerDiv.classList.add('full-correct-response-block');\n }\n containerDiv.role = 'full-correct-response';\n containerDiv.appendChild(clone);\n\n clone.isFullCorrectResponse = true;\n\n this.parentElement?.insertBefore(containerDiv, this.nextSibling);\n await clone.updateComplete;\n\n clone.response = Array.isArray(correctResponse)\n ? ([...correctResponse] as string[])\n : (correctResponse as string);\n }\n\n public toggleInternalCorrectResponse(show: boolean): void {\n this._internals.states.delete('show-correct-response');\n if (show && this.correctResponse) {\n this._internals.states.add('show-correct-response');\n }\n }\n\n public toggleCandidateCorrection(show: boolean): void {\n if (!show) {\n return;\n }\n }\n\n // ─── Lifecycle ────────────────────────────────────────────────────────────\n\n protected override firstUpdated(): void {\n super.firstUpdated();\n\n if (this.isFullCorrectResponse) {\n return;\n }\n\n if (this.showCorrectResponse) {\n this.toggleInternalCorrectResponse(true);\n }\n if (this.showFullCorrectResponse) {\n this.toggleFullCorrectResponse(true);\n }\n }\n }\n\n // Cast strips the anonymous class type so TypeScript can generate clean .d.ts\n // for any named class that extends this mixin (avoids TS4094).\n return CorrectResponseMixinClass as unknown as AbstractConstructor<CorrectResponseInterface> & T;\n};\n\n/** Public type surface exposed by `CorrectResponseMixin`. */\nexport interface CorrectResponseInterface {\n correctResponseAttr: ResponseValue;\n showCorrectResponse: boolean;\n showFullCorrectResponse: boolean;\n showCandidateCorrection: boolean;\n isFullCorrectResponse: boolean;\n correctResponse: Readonly<string | string[] | null>;\n readonly correctness: Readonly<Correctness | null>;\n readonly correctionPart: string;\n toggleCorrectResponse(show: boolean): void;\n toggleCandidateCorrection(show: boolean): void;\n /** Protected at runtime; exposed here so subclasses can call `super.toggleInternalCorrectResponse()`. */\n toggleInternalCorrectResponse(show: boolean): void;\n /** Protected at runtime. */\n toggleFullCorrectResponse(show: boolean): Promise<void>;\n /** Protected at runtime; declared here so a subclass can `override` it. */\n readonly withholdsFullCorrectResponseWhenCorrect: boolean;\n}\n","import { css } from 'lit';\n\n/**\n * The candidate-correction badge shared by correction-package elements.\n *\n * The component decides where the badge sits in the markup — last, after the label — and how big\n * its box is. It decides nothing about how it looks. The disc, the tick, the cross, and whether it\n * is lifted out of flow at all are the theme's, keyed on ::part(correction-correct) /\n * ::part(correction-incorrect).\n *\n * It replaces six implementations of one idea: four ::after glyph blocks in kennisnet, an\n * ::before/::after pair in order-interaction, and a .correct-option span that gap-match and match\n * built in JavaScript with inline styles. Several of those set margin-left and width inside a\n * :state(candidate-*) rule — a transient state doing layout, which is the bug this contract exists\n * to prevent.\n *\n * Reachable everywhere. A chip has three homes, and inside a drop target's shadow root the document\n * cannot see its badge: parts do not chain, so ::part(drag)::part(correction) is inert. A part\n * token survives exportparts, so one bare ::part(correction-correct) reaches the badge in the drag\n * bank, on the floating clone, and inside a gap. Verified in Chromium.\n *\n * Deliberately not anchored, and not absolutely positioned. Both were tried; both left\n * qti-choice-interaction unable to reach layout stability, and the VRT stability detector spent 20\n * seconds waiting before capturing a half-settled frame. A theme that wants a corner badge can\n * position ::part(correction-correct) itself — it is a part, that is the point.\n */\nexport const correctionPart = css`\n /* Nothing at all until the item judges this element. */\n [part~='correction'] {\n display: none;\n }\n\n [part~='correction-correct'],\n [part~='correction-incorrect'],\n [part~='correction-partially-correct'] {\n display: inline-flex;\n flex: 0 0 auto;\n\n /*\n * The badge aligns ITSELF, and that is the whole of the vertical story.\n *\n * It is a flex item with a definite height, so left alone its cross-axis position is decided by\n * whatever its host says — and the hosts disagree: qti-simple-associable-choice defaults to\n * align-items: normal, and qti-gap-text gates center behind :not([part~='drag']), so the\n * same chip centred its badge in the bank and top-aligned it once placed. align-self settles it\n * from the badge's side, in one line, without touching a single container.\n *\n * This replaces an align-items/justify-content: center pair that had never done anything: the\n * badge is empty — a mask painted over a background — so centring its CONTENTS centres nothing.\n */\n align-self: center;\n\n box-sizing: border-box;\n width: var(--qti-correction-size, 1em);\n height: var(--qti-correction-size, 1em);\n margin-left: var(--qti-glyph-gap, 0.5em);\n\n pointer-events: none;\n }\n`;\n","import { state } from 'lit/decorators.js';\n\nimport { CorrectResponseMixin, Correctness, type CorrectResponseInterface } from './correct-response.mixin';\n\nimport type { Interaction } from '@qti-components/base';\n\ntype AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;\n\nexport const CandidateCorrectionMixin = <T extends AbstractConstructor<Interaction>>(superClass: T) => {\n abstract class CandidateCorrectionMixinClass extends CorrectResponseMixin(superClass) {\n @state() private _candidateCorrection: 'correct' | 'incorrect' | 'partially-correct' | null = null;\n\n public override get correctionPart(): string {\n return this._candidateCorrection ? `correction correction-${this._candidateCorrection}` : 'correction';\n }\n\n public override toggleCandidateCorrection(show: boolean): void {\n if (this.showCandidateCorrection !== show) {\n this.showCandidateCorrection = show;\n }\n\n super.toggleCandidateCorrection(show);\n\n const internals = (this as unknown as { _internals: ElementInternals })._internals;\n\n internals.states.delete('candidate-correct');\n internals.states.delete('candidate-partially-correct');\n internals.states.delete('candidate-incorrect');\n\n let verdict: 'correct' | 'incorrect' | 'partially-correct' | null = null;\n\n if (show) {\n if (this.correctness === Correctness.Correct) {\n internals.states.add('candidate-correct');\n verdict = 'correct';\n }\n if (this.correctness === Correctness.PartiallyCorrect) {\n internals.states.add('candidate-partially-correct');\n verdict = 'partially-correct';\n }\n if (this.correctness === Correctness.Incorrect) {\n internals.states.add('candidate-incorrect');\n verdict = 'incorrect';\n }\n }\n\n if (this._candidateCorrection !== verdict) {\n this._candidateCorrection = verdict;\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback?.();\n\n queueMicrotask(() => {\n if (!this.isConnected || this.isFullCorrectResponse) {\n return;\n }\n if (this.showCandidateCorrection) {\n this.toggleCandidateCorrection(true);\n }\n });\n }\n }\n\n return CandidateCorrectionMixinClass as unknown as AbstractConstructor<CorrectResponseInterface> & T;\n};\n","import { CandidateCorrectionMixin } from './candidate-correction.mixin';\n\nimport type { Interaction } from '@qti-components/base';\nimport type { CorrectResponseInterface } from './correct-response.mixin';\n\ntype AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;\n\ntype CorrectableChoice = HTMLElement & {\n identifier: string;\n internals: ElementInternals;\n candidateCorrection: 'correct' | 'incorrect' | 'partially-correct' | null;\n};\n\ntype ChoicesCorrectionBase = Interaction & {\n readonly response: string | string[] | null;\n readonly internals: ElementInternals;\n};\n\n/** Adds per-choice candidate marking to interactions built on `ChoicesMixin`. */\nexport const ChoiceCorrectionMixin = <T extends AbstractConstructor<ChoicesCorrectionBase>>(superClass: T) => {\n abstract class ChoiceCorrectionMixinClass extends CandidateCorrectionMixin(superClass) {\n declare protected _choiceElements: CorrectableChoice[];\n\n public override toggleInternalCorrectResponse(show: boolean): void {\n super.toggleInternalCorrectResponse(show);\n\n const correctResponse = this.correctResponse;\n const correctResponses = correctResponse\n ? Array.isArray(correctResponse)\n ? correctResponse\n : [correctResponse]\n : [];\n\n for (const choice of this._choiceElements) {\n choice.internals.states.delete('correct-response');\n choice.internals.states.delete('incorrect-response');\n if (show && correctResponses.length > 0) {\n choice.internals.states.add(\n correctResponses.includes(choice.identifier) ? 'correct-response' : 'incorrect-response'\n );\n }\n }\n }\n\n public override toggleCandidateCorrection(show: boolean): void {\n super.toggleCandidateCorrection(show);\n\n for (const choice of this._choiceElements) {\n choice.candidateCorrection = null;\n }\n\n if (!show || !this.correctResponse) {\n return;\n }\n\n const correctResponses = Array.isArray(this.correctResponse) ? this.correctResponse : [this.correctResponse];\n const candidateResponses = Array.isArray(this.response) ? this.response : this.response ? [this.response] : [];\n\n for (const choice of this._choiceElements) {\n if (!candidateResponses.includes(choice.identifier)) {\n continue;\n }\n choice.candidateCorrection = correctResponses.includes(choice.identifier) ? 'correct' : 'incorrect';\n }\n }\n }\n\n return ChoiceCorrectionMixinClass as unknown as AbstractConstructor<CorrectResponseInterface> & T;\n};\n","type AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;\n\nexport type CandidateCorrection = 'correct' | 'incorrect' | 'partially-correct' | null;\n\nexport interface ActiveElementCorrectionInterface {\n candidateCorrection: CandidateCorrection;\n readonly correctionPart: string;\n}\n\ntype ActiveElement = HTMLElement & {\n readonly internals: ElementInternals;\n requestUpdate(name?: PropertyKey, oldValue?: unknown): unknown;\n};\n\n/** Adds candidate-verdict state to a lean choice/chip element. */\nexport const ActiveElementCorrectionMixin = <T extends AbstractConstructor<ActiveElement>>(superClass: T) => {\n abstract class ActiveElementCorrectionMixinClass extends superClass {\n #candidateCorrection: CandidateCorrection = null;\n\n public get candidateCorrection(): CandidateCorrection {\n return this.#candidateCorrection;\n }\n\n public set candidateCorrection(value: CandidateCorrection) {\n if (this.#candidateCorrection === value) return;\n const previous = this.#candidateCorrection;\n this.#candidateCorrection = value;\n\n const states = this.internals.states;\n states.delete('candidate-correct');\n states.delete('candidate-incorrect');\n states.delete('candidate-partially-correct');\n if (value) states.add(`candidate-${value}`);\n this.requestUpdate('candidateCorrection', previous);\n }\n\n public get correctionPart(): string {\n return this.#candidateCorrection ? `correction correction-${this.#candidateCorrection}` : 'correction';\n }\n }\n\n return ActiveElementCorrectionMixinClass as unknown as AbstractConstructor<ActiveElementCorrectionInterface> & T;\n};\n","import { html } from 'lit';\n\nimport { QtiGapText } from '@qti-components/interactions-core/elements/qti-gap-text';\n\nimport { ActiveElementCorrectionMixin } from '../mixins/active-element-correction.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nexport class QtiGapTextCorrection extends ActiveElementCorrectionMixin(QtiGapText) {\n static override styles = [QtiGapText.styles, correctionPart];\n\n override render() {\n return html`<div part=\"control\"></div>\n <slot part=\"label\"></slot>\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>`;\n }\n}\n","import { property } from 'lit/decorators.js';\n\nimport { QtiHotspotChoice } from '@qti-components/interactions-core/elements/qti-hotspot-choice';\n\nimport { ActiveElementCorrectionMixin } from '../mixins/active-element-correction.mixin';\n\nexport class QtiHotspotChoiceCorrection extends ActiveElementCorrectionMixin(QtiHotspotChoice) {\n @property({ attribute: 'aria-ordercorrectvalue', type: Number, reflect: true })\n orderCorrect: number | null = null;\n}\n","import { html } from 'lit';\n\nimport { QtiHottext } from '@qti-components/interactions-core/elements/qti-hottext';\n\nimport { ActiveElementCorrectionMixin } from '../mixins/active-element-correction.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nexport class QtiHottextCorrection extends ActiveElementCorrectionMixin(QtiHottext) {\n static override styles = [QtiHottext.styles, correctionPart];\n\n override render() {\n return html`<div part=\"control\"><div part=\"control-mark\"></div></div>\n <slot part=\"label\"></slot>\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>`;\n }\n}\n","import { html } from 'lit';\nimport { repeat } from 'lit/directives/repeat.js';\n\nimport { QtiSimpleAssociableChoice } from '@qti-components/interactions-core/elements/qti-simple-associable-choice';\n\nimport { ActiveElementCorrectionMixin } from '../mixins/active-element-correction.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nexport class QtiSimpleAssociableChoiceCorrection extends ActiveElementCorrectionMixin(QtiSimpleAssociableChoice) {\n static override styles = [QtiSimpleAssociableChoice.styles, correctionPart];\n\n override render() {\n return html`\n <div part=\"control\"></div>\n <slot part=\"label\"></slot>\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>\n <div part=\"drop\">\n ${repeat(\n this.drags,\n node => node.getAttribute('identifier'),\n node => node\n )}\n </div>\n `;\n }\n}\n","import { html, nothing } from 'lit';\n\nimport { QtiSimpleChoice } from '@qti-components/interactions-core/elements/qti-simple-choice';\n\nimport { ActiveElementCorrectionMixin } from '../mixins/active-element-correction.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nexport class QtiSimpleChoiceCorrection extends ActiveElementCorrectionMixin(QtiSimpleChoice) {\n static override styles = [QtiSimpleChoice.styles, correctionPart];\n\n override render() {\n return html`<div part=\"control\" tabindex=\"0\"><div part=\"control-mark\"></div></div>\n ${this.marker ? html`<div id=\"label\" part=\"marker\">${this.marker}</div>` : nothing}\n <slot part=\"label\"></slot>\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>`;\n }\n}\n","import { QtiAssessmentItem } from '@qti-components/elements/elements';\n\ntype CorrectionInteraction = {\n toggleCorrectResponse(show: boolean): void;\n toggleCandidateCorrection(show: boolean): void;\n};\n\n/** Assessment-item extension that coordinates correction-capable interactions. */\nexport class QtiAssessmentItemCorrection extends QtiAssessmentItem {\n public showCorrectResponse(show: boolean): void {\n for (const interaction of this.interactionElements) {\n (interaction as unknown as Partial<CorrectionInteraction>).toggleCorrectResponse?.(show);\n }\n\n this.updateControlState('item-show-correct-response', show);\n }\n\n public showCandidateCorrection(show: boolean): void {\n for (const interaction of this.interactionElements) {\n (interaction as unknown as Partial<CorrectionInteraction>).toggleCandidateCorrection?.(show);\n }\n\n this.updateControlState('item-show-candidate-correction', show);\n }\n\n protected override afterResponseVariableUpdated(): void {\n this.showCandidateCorrection(false);\n }\n\n private updateControlState(selector: string, shown: boolean): void {\n let root = this.getRootNode();\n while (true) {\n (root as ParentNode)\n .querySelectorAll<HTMLElement & { shown: boolean }>(selector)\n .forEach(control => (control.shown = shown));\n\n if (!(root instanceof ShadowRoot)) return;\n root = root.host.getRootNode();\n }\n }\n}\n","import { QtiItem } from '@qti-components/item/elements';\n\nimport type { CorrectResponseMode } from '../context/correction-config';\n\ntype CorrectionAssessmentItem = {\n showCorrectResponse(show: boolean): void;\n showCandidateCorrection(show: boolean): void;\n};\n\n/** Item host extension that handles correction controls and mode changes. */\nexport class QtiItemCorrection extends QtiItem {\n readonly #onShowCorrectResponse = (event: Event) => {\n const show = (event as CustomEvent<boolean>).detail;\n (this.assessmentItem as unknown as Partial<CorrectionAssessmentItem>)?.showCorrectResponse?.(show);\n this.updateControlState('item-show-correct-response', show);\n };\n\n readonly #onShowCandidateCorrection = (event: Event) => {\n const show = (event as CustomEvent<boolean>).detail;\n (this.assessmentItem as unknown as Partial<CorrectionAssessmentItem>)?.showCandidateCorrection?.(show);\n this.updateControlState('item-show-candidate-correction', show);\n };\n\n readonly #onSwitchCorrectResponseMode = (event: Event) => {\n (this.assessmentItem as unknown as Partial<CorrectionAssessmentItem>)?.showCorrectResponse?.(false);\n this.configContext = {\n ...this.configContext,\n correctResponseMode: (event as CustomEvent<CorrectResponseMode>).detail\n } as typeof this.configContext;\n };\n\n constructor() {\n super();\n this.addEventListener('item-show-correct-response', this.#onShowCorrectResponse);\n this.addEventListener('item-show-candidate-correction', this.#onShowCandidateCorrection);\n this.addEventListener('item-switch-correct-response-mode', this.#onSwitchCorrectResponseMode);\n }\n\n private updateControlState(selector: string, shown: boolean): void {\n this.querySelectorAll<HTMLElement & { shown: boolean }>(selector).forEach(control => (control.shown = shown));\n }\n\n override disconnectedCallback(): void {\n this.removeEventListener('item-show-correct-response', this.#onShowCorrectResponse);\n this.removeEventListener('item-show-candidate-correction', this.#onShowCandidateCorrection);\n this.removeEventListener('item-switch-correct-response-mode', this.#onSwitchCorrectResponseMode);\n super.disconnectedCallback();\n }\n}\n","import { QtiTest, TestCheckItem, TestNavigation } from '@qti-components/test/elements';\n\nimport type { View } from '@qti-components/base';\nimport type { QtiAssessmentItem } from '@qti-components/elements';\n\ntype CorrectionAssessmentItem = QtiAssessmentItem & {\n showCorrectResponse(show: boolean): void;\n showCandidateCorrection(show: boolean): void;\n};\n\n/** Test navigation extension that routes correction controls to the active item. */\nexport class TestNavigationCorrection extends TestNavigation {\n readonly #onShowCorrectResponse = (event: Event) => {\n (this.activeAssessmentItem as Partial<CorrectionAssessmentItem> | undefined)?.showCorrectResponse?.(\n (event as CustomEvent<boolean>).detail\n );\n };\n\n readonly #onShowCandidateCorrection = (event: Event) => {\n (this.activeAssessmentItem as Partial<CorrectionAssessmentItem> | undefined)?.showCandidateCorrection?.(\n (event as CustomEvent<boolean>).detail\n );\n };\n\n constructor() {\n super();\n this.addEventListener('test-show-correct-response', this.#onShowCorrectResponse);\n this.addEventListener('test-show-candidate-correction', this.#onShowCandidateCorrection);\n }\n\n override disconnectedCallback(): void {\n this.removeEventListener('test-show-correct-response', this.#onShowCorrectResponse);\n this.removeEventListener('test-show-candidate-correction', this.#onShowCandidateCorrection);\n super.disconnectedCallback();\n }\n}\n\n/** Test host extension that shows correct responses in scorer view. */\nexport class QtiTestCorrection extends QtiTest {\n public override updateAssessmentItemView(assessmentItem: QtiAssessmentItem, view: View): void {\n (assessmentItem as Partial<CorrectionAssessmentItem>).showCorrectResponse?.(view === 'scorer');\n }\n}\n\n/** Check-item extension that reveals the correct response after scoring. */\nexport class TestCheckItemCorrection extends TestCheckItem {\n constructor() {\n super();\n this.addEventListener('click', () => {\n this.dispatchEvent(new CustomEvent('test-show-correct-response', { detail: true, bubbles: true }));\n });\n }\n}\n","import { html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\n\nimport { configContext } from '@qti-components/base';\n\nimport type { ConfigContext } from '@qti-components/base';\nimport type { CorrectionConfig, CorrectResponseMode } from '../../context/correction-config';\n\nexport class ItemCorrectResponseMode extends LitElement {\n @consume({ context: configContext, subscribe: true })\n private itemContext: ConfigContext & CorrectionConfig;\n\n @property({ type: String })\n label = 'Correct response mode';\n\n @state()\n private _options = {\n internal: 'Internal',\n full: 'Full (copy)'\n };\n\n #switchMode(view: CorrectResponseMode) {\n this.dispatchEvent(\n new CustomEvent('item-switch-correct-response-mode', {\n detail: view,\n bubbles: true\n })\n );\n }\n\n override render() {\n return html`\n <label part=\"label\" for=\"modeSelect\">${this.label}</label>\n <select\n part=\"select\"\n id=\"modeSelect\"\n @change=${(e: Event) => {\n const el = e.target as HTMLSelectElement;\n this.#switchMode(el.value as CorrectResponseMode);\n }}\n >\n ${Object.keys(this._options).map(\n value =>\n html`<option value=\"${value}\" ?selected=${value === this.itemContext?.correctResponseMode}>\n ${this._options[value as keyof typeof this._options]}\n </option>`\n )}\n </select>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'item-correct-response-mode': ItemCorrectResponseMode;\n }\n}\n","import { css } from 'lit';\n\nexport const form = css`\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n padding: 0.5rem 1rem;\n border-radius: 0.25rem;\n user-select: none;\n`;\n\nexport const btn = css`\n background-color: lightgray;\n ${form};\n`;\n\nexport const dis = css`\n cursor: not-allowed;\n opacity: 0.8;\n`;\n\nexport const ind = css`\n ${form};\n border: 1px solid gray;\n`;\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\n\nimport { computedItemContext } from '@qti-components/base';\n\nimport * as styles from '../styles';\n\nimport type { ComputedItemContext } from '@qti-components/base';\n\nexport class ItemShowCandidateCorrection extends LitElement {\n @consume({ context: computedItemContext, subscribe: true })\n public computedContext?: ComputedItemContext;\n\n static override styles = css`\n :host {\n ${styles.btn};\n }\n :host([disabled]) {\n ${styles.dis};\n }\n `;\n\n @property({ type: Boolean, reflect: true }) shown = false;\n @property({ type: Boolean, reflect: true }) disabled = false; // Reflects to `disabled` attribute\n @property({ type: String }) showCandidateCorrectionText = 'Show candidate correction';\n @property({ type: String }) hideCandidateCorrectionText = 'Hide candidate correction';\n @property({ type: String }) noCorrectResponseText = 'No correct response specified';\n\n #hasCorrectResponse = false; // correct response is removed on certain point\n #previousActiveItem = ''; // Store previous active item reference\n\n constructor() {\n super();\n }\n\n override updated() {\n if (!this.#hasCorrectResponse || this.#previousActiveItem !== this.computedContext?.identifier) {\n this.#previousActiveItem = this.computedContext?.identifier;\n const containsCorrectResponse = !!this.computedContext?.variables.some(v => (v as any)['correctResponse']);\n const containsMapping = !!this.computedContext?.variables.some(v => {\n return (v as any)['mapping']?.mapEntries?.length > 0 || (v as any)['areaMapping']?.areaMapEntries?.length > 0;\n });\n this.#hasCorrectResponse = containsCorrectResponse || containsMapping;\n }\n this.disabled = !this.#hasCorrectResponse;\n }\n\n #toggleState() {\n if (this.disabled) return; // Prevent toggle if disabled\n\n this.dispatchEvent(\n new CustomEvent('item-show-candidate-correction', {\n detail: !this.shown,\n bubbles: true\n })\n );\n }\n\n #getDisplayedText(): string {\n return this.disabled\n ? this.noCorrectResponseText\n : this.shown\n ? this.hideCandidateCorrectionText\n : this.showCandidateCorrectionText;\n }\n\n override render() {\n return html` <div @click=\"${this.#toggleState}\">${this.#getDisplayedText()}</div> `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'item-show-candidate-correction': ItemShowCandidateCorrection;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\n\nimport { computedItemContext } from '@qti-components/base';\n\nimport * as styles from '../styles';\n\nimport type { ComputedItemContext } from '@qti-components/base';\n\nexport class ItemShowCorrectResponse extends LitElement {\n @consume({ context: computedItemContext, subscribe: true })\n public computedContext?: ComputedItemContext;\n\n static override styles = css`\n :host {\n ${styles.btn};\n }\n :host([disabled]) {\n ${styles.dis};\n }\n `;\n\n @property({ type: Boolean, reflect: true }) shown = false;\n @property({ type: Boolean, reflect: true }) disabled = false; // Reflects to `disabled` attribute\n @property({ type: String }) showCorrectText = 'Show correct response';\n @property({ type: String }) hideCorrectText = 'Hide correct response';\n @property({ type: String }) noCorrectResponseText = 'No correct response specified';\n\n #hasCorrectResponse = false; // correct response is removed on certain point\n #previousActiveItem = ''; // Store previous active item reference\n\n override updated() {\n if (!this.#hasCorrectResponse || this.#previousActiveItem !== this.computedContext?.identifier) {\n this.#previousActiveItem = this.computedContext?.identifier;\n const containsCorrectResponse = !!this.computedContext?.variables.some(v => (v as any)['correctResponse']);\n const containsMapping = !!this.computedContext?.variables.some(v => {\n return (v as any)['mapping']?.mapEntries?.length > 0 || (v as any)['areaMapping']?.areaMapEntries?.length > 0;\n });\n this.#hasCorrectResponse = containsCorrectResponse || containsMapping;\n }\n this.disabled = !this.#hasCorrectResponse;\n }\n\n #toggleState() {\n if (this.disabled) return; // Prevent toggle if disabled\n\n this.dispatchEvent(\n new CustomEvent('item-show-correct-response', {\n detail: !this.shown,\n bubbles: true\n })\n );\n }\n\n #getDisplayedText(): string {\n return this.disabled ? this.noCorrectResponseText : this.shown ? this.hideCorrectText : this.showCorrectText;\n }\n\n override render() {\n return html` <div @click=\"${this.#toggleState}\">${this.#getDisplayedText()}</div> `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'item-show-correct-response': ItemShowCorrectResponse;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\n\nimport { computedContext } from '@qti-components/base';\n\nimport * as styles from '../styles';\n\nimport type { ComputedContext } from '@qti-components/base';\n\n/**\n * @deprecated test-show-correct-response is deprecated and will be removed in the future.\n */\n\nexport class TestShowCorrectResponse extends LitElement {\n @consume({ context: computedContext, subscribe: true })\n public computedContext?: ComputedContext;\n\n static override styles = css`\n :host {\n ${styles.btn};\n }\n :host([disabled]) {\n ${styles.dis};\n }\n `;\n\n @property({ type: Boolean, reflect: true }) shown = false;\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: String }) showCorrectText = 'Show correct response';\n @property({ type: String }) hideCorrectText = 'Hide correct response';\n @property({ type: String }) noCorrectResponseText = 'No correct response specified';\n\n #previousActiveItem?: unknown; // Store previous active item reference\n\n override willUpdate(_changedProperties: Map<string | number | symbol, unknown>) {\n const activeItem = this.computedContext?.testParts\n .flatMap(testPart => testPart.sections.flatMap(section => section.items))\n .find(item => item.active);\n\n // If active item changed, reset shown before the update\n if (this.#previousActiveItem !== activeItem) {\n this.shown = false;\n this.#previousActiveItem = activeItem; // Update previous active item\n }\n\n if (activeItem) {\n const containsCorrectResponse = !!activeItem?.variables?.some(v => (v as any)['correctResponse']);\n const containsMapping = !!activeItem?.variables?.some(v => {\n return (v as any)['mapping']?.mapEntries?.length > 0 || (v as any)['areaMapping']?.areaMapEntries?.length > 0;\n });\n this.disabled = !containsCorrectResponse && !containsMapping;\n } else {\n this.disabled = true;\n }\n }\n #toggleState() {\n if (this.disabled) return;\n this.shown = !this.shown;\n\n this.dispatchEvent(\n new CustomEvent('test-show-correct-response', {\n detail: this.shown,\n bubbles: true\n })\n );\n }\n\n #getDisplayedText(): string {\n return this.disabled ? this.noCorrectResponseText : this.shown ? this.hideCorrectText : this.showCorrectText;\n }\n\n override render() {\n return html` <div @click=\"${this.#toggleState}\">${this.#getDisplayedText()}</div> `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'test-show-correct-response': TestShowCorrectResponse;\n }\n}\n","import { CandidateCorrectionMixin } from './candidate-correction.mixin';\n\nimport type { Interaction } from '@qti-components/base';\nimport type { CorrectResponseInterface } from './correct-response.mixin';\n\ntype AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;\n\ntype DragDropInteraction = Interaction & {\n afterCache(): void;\n};\n\n/** Adds correction lifecycle behavior shared by drag-and-drop interactions. */\nexport const DragDropCorrectionMixin = <T extends AbstractConstructor<DragDropInteraction>>(superClass: T) => {\n abstract class DragDropCorrectionMixinClass extends CandidateCorrectionMixin(superClass) {\n public override toggleInternalCorrectResponse(show: boolean): void {\n if (!this.showFullCorrectResponse) {\n this.toggleFullCorrectResponse(show);\n }\n }\n\n public override afterCache(): void {\n super.afterCache();\n if (this.showCorrectResponse) this.toggleInternalCorrectResponse(true);\n if (this.showCandidateCorrection) this.toggleCandidateCorrection(true);\n if (this.showFullCorrectResponse) this.toggleFullCorrectResponse(true);\n }\n }\n\n return DragDropCorrectionMixinClass as unknown as AbstractConstructor<CorrectResponseInterface> & T;\n};\n","import { QtiAssociateInteraction } from '@qti-components/associate-interaction/elements';\n\nimport { DragDropCorrectionMixin } from '../mixins/drag-drop-correction.mixin';\n\nexport class QtiAssociateInteractionCorrection extends DragDropCorrectionMixin(QtiAssociateInteraction) {}\n","import { QtiChoiceInteraction } from '@qti-components/choice-interaction/elements';\n\nimport { ChoiceCorrectionMixin } from '../mixins/choice-correction.mixin';\n\n/**\n * Correction-capable `qti-choice-interaction` implementation.\n *\n * It is registered under the standard tag only inside a correction registry;\n * the standard package constructor remains correction-free.\n */\nexport class QtiChoiceInteractionCorrection extends ChoiceCorrectionMixin(QtiChoiceInteraction) {}\n","import { css, html } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { QtiExtendedTextInteraction } from '@qti-components/extended-text-interaction/elements';\n\nimport { ActiveElementCorrectionMixin } from '../mixins/active-element-correction.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nimport type { CandidateCorrection } from '../mixins/active-element-correction.mixin';\n\n/**\n * Extended-text, judged from OUTSIDE.\n *\n * Every other correction class in this folder derives its verdict: it is handed a `correct-response`\n * and compares. Extended-text cannot — the response is free prose, there is nothing to compare it\n * to, and that is exactly why the base component extends `Interaction` directly and carries no\n * correction machinery (correct-response.mixin.ts says so for extended-text, upload and media).\n *\n * But an extended-text answer is still judged; just not here. A teacher, a marking service, or an app\n * that already knows the score decides, and then has to tell the component. This class is that\n * channel and nothing more: it computes no correctness, it only accepts one.\n *\n * Hence `ActiveElementCorrectionMixin` rather than `CandidateCorrectionMixin`. The two are otherwise\n * the same bookkeeping — clear the three `candidate-*` states, add one, expose `correctionPart` — but\n * `CandidateCorrectionMixin` sits on top of `CorrectResponseMixin` and drives everything off a\n * computed `correctness` getter with no setter. `ActiveElementCorrectionMixin` is the settable one,\n * written for chips whose parent interaction pushes a verdict into them. An externally-graded essay\n * is the same shape: something else knows the answer.\n *\n * Two consequences worth knowing:\n *\n * - The `item-show-candidate-correction` button will not drive this. It disables itself unless a\n * response variable declares a correctResponse / mapping / areaMapping, which a prose item never\n * does. Correct: the verdict comes from the host application, which sets the attribute.\n * - The verdict survives typing. It is a property, not the `showCandidateCorrection` toggle, so\n * `afterResponseVariableUpdated()` does not clear it. If a stale grade should be dropped when the\n * candidate edits their answer, that is an explicit decision for the host app to make.\n */\nexport class QtiExtendedTextInteractionCorrection extends ActiveElementCorrectionMixin(QtiExtendedTextInteraction) {\n static override styles = [\n QtiExtendedTextInteraction.styles,\n correctionPart,\n css`\n /*\n * Placement only — the glyph itself is the theme's, keyed on ::part(correction-*). That split\n * is the contract in correction.styles.ts, which deliberately leaves the shared badge in flow\n * and invites a component to lift it out if it wants a corner badge.\n *\n * A textarea is a box the candidate writes in, so the badge goes over its top-left corner\n * rather than trailing the text the way a chip's does, and the theme reserves the gutter for it\n * (padding-left on ::part(textarea)).\n *\n * Anchored to the TEXTAREA, not to the host. The badge's containing block is :host, and the\n * host also contains the prompt slot — so a plain top: 0.85rem measured from the host lands on\n * the prompt and the badge floats above the field, which is exactly what it did. Only the\n * vertical offset needs anchoring: the textarea spans the host's full width, so the left\n * offset is the same measured from either.\n */\n [part~='textarea'] {\n anchor-name: --qti-extended-text-field;\n }\n\n [part~='correction'] {\n position: absolute;\n position-anchor: --qti-extended-text-field;\n margin: 0;\n width: var(--qti-correction-size);\n\n /*\n * One FIELD line tall, not square — this is what puts the glyph on the text rather than near\n * it. The mask is drawn center / contain, so in a box exactly one line high it centres itself\n * on that line while the width still governs the glyph's size.\n *\n * Not 1lh: that unit resolves against the BADGE's own inherited line-height (measured 18.4px),\n * not the textarea's (24px), so it landed a third of a line low. --qti-field-line-height is\n * the same number @mixin field-typography gives the field, so the two cannot drift.\n */\n height: calc(var(--qti-correction-size) * var(--qti-field-line-height));\n\n /* Inset exactly as the text is: the same trailing token the two field-shaped interactions\n use, read here as a LEADING inset because this badge lives in a left gutter. */\n left: var(--qti-correction-inset);\n\n /* Anchored to the field's first line: its top edge plus the field's own padding-top. */\n top: calc(anchor(top) + var(--qti-spacing));\n }\n\n /*\n * Fallback for engines without anchor positioning, where the top above does not parse and the\n * badge would fall to its static position below the field. The bottom of the gutter needs no\n * knowledge of where the field starts, and the gutter runs the full height, so the badge still\n * clears the text.\n *\n * Scoped by @supports rather than declared alongside. Both were set at first, on the assumption\n * that top + height over-constrains the box and bottom is ignored — it is not: measured, the\n * bottom won and put the badge on the third line.\n */\n @supports not (anchor-name: --probe) {\n [part~='correction'] {\n top: auto;\n bottom: var(--qti-correction-inset);\n }\n }\n `\n ];\n\n /**\n * The verdict, pushed in from outside: `correct`, `partially-correct`, `incorrect`, or absent.\n *\n * `noAccessor` because the mixin already owns the accessor — its setter is what writes the\n * `:state(candidate-*)` custom states — and Lit would otherwise replace it with a generated one and\n * silently drop that bookkeeping. Same pattern as the `response` attribute on\n * qti-inline-choice-interaction and qti-slider-interaction.\n */\n @property({ attribute: 'candidate-correction', reflect: true, noAccessor: true })\n declare candidateCorrection: CandidateCorrection;\n\n /** The badge goes between the field and the validation message; everything else is the base's. */\n override render() {\n return html`${this.renderPrompt()}${this.renderTextarea()}\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>\n ${this.renderValidationMessage()}`;\n }\n}\n","/** Helpers shared by more than one correction interaction. */\n\n/** A choice element that can carry a per-candidate correction verdict. */\nexport type CorrectableChoice = HTMLElement & {\n identifier: string;\n candidateCorrection: 'correct' | 'incorrect' | 'partially-correct' | null;\n};\n\n/** Splits a `\"source target\"` correct-response into its pairs. */\nexport const parsePairs = (response: Readonly<string | string[] | null>): Array<{ source: string; target: string }> => {\n if (!response) return [];\n const entries = Array.isArray(response) ? response : [response];\n return entries.map(entry => {\n const [source, target] = entry.split(' ');\n return { source, target };\n });\n};\n","import { QtiGapMatchInteraction } from '@qti-components/gap-match-interaction/elements';\n\nimport { DragDropCorrectionMixin } from '../mixins/drag-drop-correction.mixin';\nimport { parsePairs, type CorrectableChoice } from './shared';\n\nexport class QtiGapMatchInteractionCorrection extends DragDropCorrectionMixin(QtiGapMatchInteraction) {\n public override toggleCandidateCorrection(show: boolean): void {\n super.toggleCandidateCorrection(show);\n const matches = parsePairs(this.correctResponse);\n\n for (const target of this.querySelectorAll('qti-gap')) {\n const targetId = target.getAttribute('identifier');\n const selectedChoices = (target as unknown as HTMLElement & { drags: readonly CorrectableChoice[] }).drags;\n for (const choice of selectedChoices) {\n choice.candidateCorrection = null;\n if (show && matches.some(match => match.source === choice.identifier && match.target === targetId)) {\n choice.candidateCorrection = 'correct';\n } else if (show) {\n choice.candidateCorrection = 'incorrect';\n }\n }\n }\n }\n}\n","import { svg } from 'lit';\nimport { repeat } from 'lit/directives/repeat.js';\n\nimport { QtiGraphicAssociateInteraction } from '@qti-components/graphic-associate-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\n\nexport class QtiGraphicAssociateInteractionCorrection extends CandidateCorrectionMixin(QtiGraphicAssociateInteraction) {\n #correctLines: string[] = [];\n\n public override toggleInternalCorrectResponse(show: boolean): void {\n super.toggleInternalCorrectResponse(show);\n const response = this.correctResponse;\n const previous = this.#correctLines;\n this.#correctLines = show && response ? (Array.isArray(response) ? [...response] : [response]) : [];\n this.requestUpdate('correctLines', previous);\n }\n\n protected override renderSupplementalLines(): unknown {\n return repeat(\n this.#correctLines,\n line => line,\n line => svg`\n <line\n part=\"correct-line\"\n x1=${parseInt(this.querySelector<SVGLineElement>(`[identifier=${line.split(' ')[0]}]`)!.style.left)}\n y1=${parseInt(this.querySelector<SVGLineElement>(`[identifier=${line.split(' ')[0]}]`)!.style.top)}\n x2=${parseInt(this.querySelector<SVGLineElement>(`[identifier=${line.split(' ')[1]}]`)!.style.left)}\n y2=${parseInt(this.querySelector<SVGLineElement>(`[identifier=${line.split(' ')[1]}]`)!.style.top)}\n stroke=\"var(--qti-correct)\"\n stroke-width=\"3\"\n stroke-dasharray=\"5,5\"\n />\n `\n );\n }\n}\n","import { QtiGraphicGapMatchInteraction } from '@qti-components/graphic-gap-match-interaction/elements';\n\nimport { DragDropCorrectionMixin } from '../mixins/drag-drop-correction.mixin';\n\nexport class QtiGraphicGapMatchInteractionCorrection extends DragDropCorrectionMixin(QtiGraphicGapMatchInteraction) {}\n","import { QtiGraphicOrderInteraction } from '@qti-components/graphic-order-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\n\nimport type { Choice } from '@qti-components/interactions-core/mixins/choices/choices.mixin';\n\ntype OrderedHotspot = Choice & { order: number | null };\n\ntype CorrectableOrderedHotspot = OrderedHotspot & {\n candidateCorrection: 'correct' | 'incorrect' | 'partially-correct' | null;\n orderCorrect: number | null;\n};\n\nexport class QtiGraphicOrderInteractionCorrection extends CandidateCorrectionMixin(QtiGraphicOrderInteraction) {\n protected override resolvePinColor(choice: OrderedHotspot): string {\n const correctableChoice = choice as CorrectableOrderedHotspot;\n if (correctableChoice.matches(':state(candidate-incorrect)')) return 'var(--qti-incorrect)';\n if (correctableChoice.matches(':state(candidate-correct)')) return 'var(--qti-correct)';\n if (correctableChoice.matches(':state(correct-response)')) return 'var(--qti-answer-border)';\n return super.resolvePinColor(choice);\n }\n\n public override toggleInternalCorrectResponse(show: boolean): void {\n super.toggleInternalCorrectResponse(show);\n const response = this.correctResponse;\n const correctOrder = response ? (Array.isArray(response) ? response : [response]) : [];\n for (const hotspot of this._choiceElements as CorrectableOrderedHotspot[]) {\n const index = correctOrder.indexOf(hotspot.identifier);\n hotspot.orderCorrect = show && index >= 0 ? index + 1 : null;\n }\n this.refreshLocatorPins();\n }\n\n public override toggleCandidateCorrection(show: boolean): void {\n super.toggleCandidateCorrection(show);\n const response = this.correctResponse;\n const correctOrder = response ? (Array.isArray(response) ? response : [response]) : [];\n for (const hotspot of this._choiceElements as CorrectableOrderedHotspot[]) {\n hotspot.candidateCorrection = null;\n if (show && hotspot.order != null) {\n hotspot.candidateCorrection = correctOrder[hotspot.order - 1] === hotspot.identifier ? 'correct' : 'incorrect';\n }\n }\n this.refreshLocatorPins();\n }\n}\n","import { QtiHotspotInteraction } from '@qti-components/hotspot-interaction/elements';\n\nimport { ChoiceCorrectionMixin } from '../mixins/choice-correction.mixin';\n\nexport class QtiHotspotInteractionCorrection extends ChoiceCorrectionMixin(QtiHotspotInteraction) {}\n","import { QtiHottextInteraction } from '@qti-components/hottext-interaction/elements';\n\nimport { ChoiceCorrectionMixin } from '../mixins/choice-correction.mixin';\n\nexport class QtiHottextInteractionCorrection extends ChoiceCorrectionMixin(QtiHottextInteraction) {}\n","import { css, html } from 'lit';\n\nimport { QtiInlineChoiceInteraction } from '@qti-components/inline-choice-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nexport class QtiInlineChoiceInteractionCorrection extends CandidateCorrectionMixin(QtiInlineChoiceInteraction) {\n static override get styles() {\n return [\n QtiInlineChoiceInteraction.styles,\n correctionPart,\n css`\n /*\n * Only the TRAILING inset — the leading gap is the shared --qti-glyph-gap, like every other\n * badge. This used to set both margins to --qti-gap (1rem), twice everyone else's 0.5em, on\n * the one token qti-variables.css calls \"the page's rhythm … an order of magnitude too wide\n * for a glyph sitting inside a line\".\n *\n * The trailing inset is needed here, and in text-entry, because these two put the field's box\n * on the HOST while its padding sits on an inner element (::part(trigger), ::part(input)) —\n * so a badge that is a child of the host falls outside that padding and lands on the border.\n * Chips, choices and hottext carry their padding on the host, so their badge is already inset\n * by it and needs nothing.\n */\n [part~='correction'] {\n margin-inline-end: var(--qti-correction-inset);\n }\n `\n ];\n }\n\n /**\n * Internal mode defers to the full correct response, exactly as text-entry does.\n *\n * There is no room beside a dropdown for an answer key: the interaction sits inside a line of\n * running text, so a marker next to the field competes with the sentence around it, and when the\n * candidate happened to pick the correct option it printed the same word twice. The full variant\n * puts the key in a `div.full-correct-response-inline` after the field instead — one already-themed\n * presentation for both inline interactions rather than a second one only these two use.\n *\n * `super` is deliberately not called: its `show-correct-response` host state paints the dashed\n * outline in qti-states.css, and this element is no longer the thing presenting the key — the\n * wrapper beside it is. Leaving the state off keeps internal mode looking identical to an item\n * authored with `show-full-correct-response`.\n *\n * The guard stops the two entry points rendering two wrappers: `showFullCorrectResponse` has its\n * own watcher, so with both flags set this would otherwise run a second time.\n */\n public override toggleInternalCorrectResponse(show: boolean): void {\n if (!this.showFullCorrectResponse) this.toggleFullCorrectResponse(show);\n }\n\n /**\n * The key is shown whether or not the candidate was right.\n *\n * The base withholds it from a correct candidate, on the reasoning that their answer already is\n * the key. That reasoning does not survive contact with this element: asking for the correct\n * response and being shown nothing is indistinguishable from the feature being broken, and it is\n * the only inline interaction where the answer and the key are the same short phrase, so there is\n * no visual clue either. Show it, and let the correctness badge say who was right.\n */\n public override get withholdsFullCorrectResponseWhenCorrect(): boolean {\n return false;\n }\n\n /** The badge trails the validation message; everything else is the base's. */\n override render() {\n return html`\n ${this.renderTrigger()} ${this.renderMenu()} ${this.renderValidationMessage()}\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>\n `;\n }\n}\n","import { QtiMatchInteraction } from '@qti-components/match-interaction/elements';\n\nimport { DragDropCorrectionMixin } from '../mixins/drag-drop-correction.mixin';\nimport { parsePairs, type CorrectableChoice } from './shared';\n\nexport class QtiMatchInteractionCorrection extends DragDropCorrectionMixin(QtiMatchInteraction) {\n #correctPairs = new Set<string>();\n\n public override toggleCandidateCorrection(show: boolean): void {\n super.toggleCandidateCorrection(show);\n const matches = parsePairs(this.correctResponse);\n this.#correctPairs = show ? new Set(matches.map(match => `${match.source} ${match.target}`)) : new Set();\n\n for (const target of this.targetChoices) {\n const targetId = target.getAttribute('identifier');\n const selectedChoices = (target as unknown as { drags: readonly CorrectableChoice[] }).drags;\n for (const choice of selectedChoices) {\n choice.candidateCorrection = null;\n if (show) {\n choice.candidateCorrection = this.#correctPairs.has(`${choice.identifier} ${targetId}`)\n ? 'correct'\n : 'incorrect';\n }\n }\n }\n this.requestUpdate();\n }\n\n protected override getCellStateVariant(value: string, checked: boolean): string {\n if (!this.showCandidateCorrection || !checked) return '';\n return this.#correctPairs.has(value) ? 'correct' : 'incorrect';\n }\n}\n","/**\n * Numeric core: indices of the chosen longest increasing subsequence within a\n * sequence of distinct numbers.\n *\n * Tiebreaker: strict `>` comparisons keep the smallest predecessor index when\n * lengths tie, and the smallest ending index is picked when multiple indices\n * achieve the maximum length. This is equivalent to \"the first LIS found when\n * iterating left-to-right\".\n */\nexport function findLongestIncreasingSubsequenceIndices(sequence: number[]): Set<number> {\n if (sequence.length === 0) {\n return new Set();\n }\n\n const lengthEndingAt: number[] = new Array(sequence.length).fill(1);\n const predecessorIndex: number[] = new Array(sequence.length).fill(-1);\n\n for (let currentIndex = 0; currentIndex < sequence.length; currentIndex++) {\n for (let previousIndex = 0; previousIndex < currentIndex; previousIndex++) {\n if (\n sequence[previousIndex] < sequence[currentIndex] &&\n lengthEndingAt[previousIndex] + 1 > lengthEndingAt[currentIndex]\n ) {\n lengthEndingAt[currentIndex] = lengthEndingAt[previousIndex] + 1;\n predecessorIndex[currentIndex] = previousIndex;\n }\n }\n }\n\n let bestEndIndex = 0;\n for (let index = 1; index < sequence.length; index++) {\n if (lengthEndingAt[index] > lengthEndingAt[bestEndIndex]) {\n bestEndIndex = index;\n }\n }\n\n const resultIndices = new Set<number>();\n for (let index = bestEndIndex; index !== -1; index = predecessorIndex[index]) {\n resultIndices.add(index);\n }\n\n return resultIndices;\n}\n\n/**\n * Domain wrapper: identifiers of candidate-placed choices counted as\n * correctly placed, i.e. the longest run of choices whose relative order\n * matches the correct order.\n *\n * Assumes identifiers are unique within both arrays (guaranteed by QTI).\n * Identifiers not present in `correctOrder` are foreign to the response and\n * are never included in the result.\n */\nexport function findCorrectlyPlacedIdentifiers(candidateOrder: string[], correctOrder: string[]): Set<string> {\n const rankByIdentifier = new Map<string, number>(correctOrder.map((identifier, position) => [identifier, position]));\n\n const knownIdentifiers = candidateOrder.filter(identifier => rankByIdentifier.has(identifier));\n const rankSequence = knownIdentifiers.map(identifier => rankByIdentifier.get(identifier));\n\n const winningIndices = findLongestIncreasingSubsequenceIndices(rankSequence);\n\n const result = new Set<string>();\n winningIndices.forEach(index => result.add(knownIdentifiers[index]));\n return result;\n}\n","import { QtiOrderInteraction } from '@qti-components/order-interaction/elements';\n\nimport { DragDropCorrectionMixin } from '../mixins/drag-drop-correction.mixin';\nimport { findCorrectlyPlacedIdentifiers } from '../utils/longest-increasing-subsequence';\nimport { type CorrectableChoice } from './shared';\n\nexport class QtiOrderInteractionCorrection extends DragDropCorrectionMixin(QtiOrderInteraction) {\n public override toggleCandidateCorrection(show: boolean): void {\n super.toggleCandidateCorrection(show);\n\n const dropTargets = Array.from(this.shadowRoot!.querySelectorAll<HTMLElement>(`[part~='drop']`));\n const placedChoices = dropTargets.flatMap(drop => this.chipsIn(drop) as CorrectableChoice[]);\n for (const choice of placedChoices) choice.candidateCorrection = null;\n if (!show) return;\n\n const response = this.correctResponse;\n const entries = response ? (Array.isArray(response) ? response : [response]) : [];\n const correctOrder = entries\n .map((entry, index) => {\n const [identifier, dropId] = entry.split(' ');\n const parsed = dropId?.startsWith('droplist') ? parseInt(dropId.slice('droplist'.length), 10) : index;\n return { identifier, dropIndex: Number.isNaN(parsed) ? index : parsed };\n })\n .filter(entry => entry.identifier)\n .sort((a, b) => a.dropIndex - b.dropIndex)\n .map(entry => entry.identifier);\n if (correctOrder.length === 0) return;\n\n const placedEntries = placedChoices\n .map(choice => ({ choice, identifier: choice.getAttribute('identifier') }))\n .filter((entry): entry is { choice: CorrectableChoice; identifier: string } => Boolean(entry.identifier));\n const correctlyPlaced = findCorrectlyPlacedIdentifiers(\n placedEntries.map(entry => entry.identifier),\n correctOrder\n );\n for (const { choice, identifier } of placedEntries) {\n choice.candidateCorrection = correctlyPlaced.has(identifier) ? 'correct' : 'incorrect';\n }\n }\n}\n","import { QtiPortableCustomInteraction } from '@qti-components/portable-custom-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\n\nimport type { BaseType, Cardinality } from '@qti-components/base';\n\nexport class QtiPortableCustomInteractionCorrection extends CandidateCorrectionMixin(QtiPortableCustomInteraction) {\n public override toggleInternalCorrectResponse(show: boolean): void {\n super.toggleInternalCorrectResponse(show);\n const responseVariable = this.responseVariable;\n const sourceResponse = responseVariable?.correctResponse ?? this.correctResponse;\n this.correctResponse = show ? sourceResponse : responseVariable?.cardinality === 'single' ? '' : [];\n\n const containerId = `correct-response-container-${this.responseIdentifier}`;\n this.parentElement?.querySelectorAll(`#${containerId}`).forEach(element => element.remove());\n\n if (!show) {\n this.enable();\n return;\n }\n this.disable();\n if (!this.correctResponse) return;\n\n const container = document.createElement('div');\n container.id = containerId;\n container.className = 'pci-correct-response-container';\n Object.assign(container.style, {\n position: 'relative',\n marginTop: '20px',\n border: '2px solid green',\n padding: '16px',\n borderRadius: '4px',\n backgroundColor: 'rgba(0, 128, 0, 0.05)'\n });\n\n const label = document.createElement('div');\n label.textContent = 'Correct Response:';\n Object.assign(label.style, { fontWeight: 'bold', marginBottom: '10px', color: 'green' });\n container.append(label);\n\n // `cloneNode(false)`, not `document.createElement`: a shallow clone is created in the same\n // custom element registry as this element, so the viewer is still upgraded when the item was\n // rendered into a scoped registry. It carries the attributes over and none of the children.\n const viewer = this.cloneNode(false) as QtiPortableCustomInteractionCorrection;\n // Two elements in one tree cannot share an id, and the flags would have the viewer show a\n // correction of its own.\n viewer.removeAttribute('id');\n viewer.removeAttribute('show-correct-response');\n viewer.removeAttribute('show-full-correct-response');\n viewer.removeAttribute('show-candidate-correction');\n viewer.isFullCorrectResponse = true;\n const originalResponseId = this.responseIdentifier;\n viewer.responseIdentifier = `${originalResponseId}-correct`;\n\n // Only the authored light DOM — modules, markup, properties, stylesheets. The runtime's own\n // children must not come along: the PCI appends its iframe to itself, and the `disable()` above\n // has just added the review overlay. A cloned iframe never loads, so the viewer would paint a\n // dead frame above the live one.\n for (const child of Array.from(this.children)) {\n if (child.tagName.startsWith('QTI-')) viewer.append(child.cloneNode(true));\n }\n\n const correctResponse = this.correctResponse as string | string[];\n const cardinality: Cardinality =\n responseVariable?.cardinality ?? (Array.isArray(correctResponse) ? 'multiple' : 'single');\n const baseType: BaseType = responseVariable?.baseType ?? 'string';\n\n // The standards-conformant handoff, for a PCI that implements the solution use case: it reads\n // the key out of its own `getInstance` configuration rather than having a response pushed at it.\n // Set explicitly because the viewer has no response declaration to derive one from — it is not a\n // registered interaction, so `responseVariable` is undefined and the derived getter returns null.\n // See https://github.com/1EdTech/qti-project-management/issues/210\n viewer.status = 'solution';\n viewer.responseDeclaration = {\n baseType,\n cardinality,\n correctResponse: { value: correctResponse }\n };\n\n // The push below stays for PCIs that do NOT implement the solution use case: those only know how\n // to render a response bound to them. It goes out once the viewer's own iframe has finished its\n // handshake — listened for rather than hooked into `connectedCallback`, since custom element\n // reactions are looked up on the prototype when the element is defined, so an instance-level\n // override of it is never read.\n viewer.addEventListener(\n 'qti-portable-custom-interaction-loaded',\n () => {\n const value = viewer.responseVariablesToQtiVariableJSON(correctResponse, cardinality, baseType);\n viewer.sendMessageToIframe('setBoundTo', { [originalResponseId]: value });\n viewer.sendMessageToIframe('setState', { state: 'review' });\n },\n { once: true }\n );\n viewer.style.pointerEvents = 'none';\n container.append(viewer);\n this.after(container);\n }\n}\n","import { css, html } from 'lit';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport { ScoringHelper } from '@qti-components/base';\nimport { QtiSelectPointInteraction } from '@qti-components/select-point-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\n\nimport type { QtiAreaMapEntry } from '@qti-components/base';\n\nexport class QtiSelectPointInteractionCorrection extends CandidateCorrectionMixin(QtiSelectPointInteraction) {\n #correctAreas: Array<{ shape: string; coords: string }> = [];\n\n #responseCorrection: boolean[] = [];\n\n static override styles = [\n QtiSelectPointInteraction.styles,\n css`\n [part~='correct'] {\n --qti-select-point-marker-color: var(--qti-correct);\n }\n [part~='incorrect'] {\n --qti-select-point-marker-color: var(--qti-incorrect);\n }\n `\n ];\n\n public override toggleCandidateCorrection(show: boolean): void {\n super.toggleCandidateCorrection(show);\n const previous = this.#responseCorrection;\n this.#responseCorrection = [];\n if (!show) {\n this.requestUpdate('responseCorrection', previous);\n return;\n }\n\n const areaEntries = this._effectiveAreaEntries;\n const baseType = this.responseVariable?.baseType;\n const response = this.correctResponse;\n for (const point of this.responsePoints) {\n let correct = areaEntries.some(area =>\n ScoringHelper.isPointInArea(`${point.x} ${point.y}`, `${area.shape},${area.coords}`, baseType)\n );\n if (!areaEntries.length && response) {\n const expected = Array.isArray(response) ? response : [response];\n correct = expected.some(entry => {\n const [x, y] = entry.split(' ').map(Number);\n return Number.isFinite(x) && Number.isFinite(y) && Math.hypot(point.x - x, point.y - y) <= 10;\n });\n }\n this.#responseCorrection.push(correct);\n }\n this.requestUpdate('responseCorrection', previous);\n }\n\n public override toggleInternalCorrectResponse(show: boolean): void {\n super.toggleInternalCorrectResponse(show);\n if (!show) {\n const previous = this.#correctAreas;\n this.#correctAreas = [];\n this.requestUpdate('correctAreas', previous);\n return;\n }\n\n let entries: QtiAreaMapEntry[] = this._effectiveAreaEntries;\n if (!entries.length) {\n const response = this.correctResponse;\n const values = response ? (Array.isArray(response) ? response : [response]) : [];\n if (values.some(value => value.split(' ').length < 2)) {\n console.error('No valid correct responses found.');\n return;\n }\n entries = values.map(value => ({\n shape: 'circle',\n coords: `${value.split(' ').join(',')},10`,\n defaultValue: 1,\n mappedValue: 1\n }));\n }\n const previous = this.#correctAreas;\n this.#correctAreas = entries.map(entry => ({ shape: entry.shape, coords: entry.coords }));\n this.requestUpdate('correctAreas', previous);\n }\n\n protected override pointPart(_point: string, index: number): string {\n const verdict = this.#responseCorrection[index];\n return verdict === undefined ? 'point' : `point ${verdict ? 'correct' : 'incorrect'}`;\n }\n\n protected override renderSupplementalLayer(): unknown {\n return repeat(\n this.#correctAreas,\n area => `${area.shape}:${area.coords}`,\n (area, index) =>\n html`<div\n style=${styleMap({\n position: 'absolute',\n pointerEvents: 'none',\n backgroundColor: 'var(--qti-correct)',\n opacity: '0.5'\n })}\n data-correction-area\n data-coord=${area.coords}\n data-shape=${area.shape}\n alt=${`correct-response-${index + 1}`}\n ></div>`\n );\n }\n\n protected override updated(changedProperties: Map<string | number | symbol, unknown>): void {\n super.updated(changedProperties);\n if (changedProperties.has('correctAreas' as never)) {\n this.positionOverlayElements(this.shadowRoot!.querySelectorAll<HTMLElement>('[data-correction-area]'));\n }\n }\n}\n","import { css, html, nothing } from 'lit';\n\nimport { QtiSliderInteraction } from '@qti-components/slider-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\n\nexport class QtiSliderInteractionCorrection extends CandidateCorrectionMixin(QtiSliderInteraction) {\n #correctResponseNumber: number | null = null;\n\n static override styles = [\n QtiSliderInteraction.styles,\n css`\n [part='knob-correct'] {\n background-color: var(--qti-correct-light);\n border: 2px solid var(--qti-correct);\n position: relative;\n height: 1rem;\n width: 1rem;\n transform-origin: center;\n transform: translateX(-50%);\n cursor: pointer;\n border-radius: 9999px;\n left: var(--value-percentage-correct);\n }\n `\n ];\n\n public override toggleInternalCorrectResponse(show: boolean): void {\n super.toggleInternalCorrectResponse(show);\n const response = this.correctResponse;\n const raw = Array.isArray(response) ? response[0] : response;\n const value = show && raw ? parseFloat(raw) : NaN;\n const previous = this.#correctResponseNumber;\n this.#correctResponseNumber = Number.isFinite(value) ? value : null;\n if (this.#correctResponseNumber !== null) {\n const percentage = ((this.#correctResponseNumber - this.min) / (this.max - this.min)) * 100;\n this.style.setProperty('--value-percentage-correct', `${percentage}%`);\n } else {\n this.style.removeProperty('--value-percentage-correct');\n }\n this.requestUpdate('correctResponseNumber', previous);\n }\n\n protected override renderRailSupplement(): unknown {\n return this.#correctResponseNumber === null\n ? nothing\n : html`<div id=\"knob-correct\" part=\"knob-correct\">\n <div id=\"value\" part=\"value\">${this.#correctResponseNumber}</div>\n </div>`;\n }\n}\n","import { css, html } from 'lit';\n\nimport { QtiTextEntryInteraction } from '@qti-components/text-entry-interaction/elements';\n\nimport { CandidateCorrectionMixin } from '../mixins/candidate-correction.mixin';\nimport { Correctness } from '../mixins/correct-response.mixin';\nimport { correctionPart } from '../styles/correction.styles';\n\nexport class QtiTextEntryInteractionCorrection extends CandidateCorrectionMixin(QtiTextEntryInteraction) {\n static override styles = [\n QtiTextEntryInteraction.styles,\n correctionPart,\n css`\n /*\n * The trailing inset only — size and leading gap come from the shared sheet.\n *\n * This block used to also set position: static; translate: none (dead: nothing positions this\n * badge) and size it with --qti-control-size, the radio/checkbox token — 1rem, absolute, where\n * every other badge is 1em and scales with the text it annotates. The two agreed only while the\n * item's font-size happened to equal the root's.\n *\n * The inset is needed because the field's box is the HOST while its padding is on ::part(input),\n * so the badge — a child of the host — falls outside that padding and lands flush on the border.\n * Measured at 0px from the border, against 16px for a choice and 12.8px for a chip.\n */\n [part~='correction'] {\n margin-inline-end: var(--qti-correction-inset);\n }\n :host {\n position: relative;\n anchor-name: --text-entry-host, --qti-correction-anchor;\n }\n [part='correct'] {\n position: absolute;\n position-anchor: --text-entry-host;\n position-area: top span-right;\n margin-bottom: 0.25rem;\n padding: var(--qti-padding-box);\n background-color: var(--qti-bg);\n white-space: nowrap;\n }\n `\n ];\n\n public override get correctness(): Readonly<Correctness | null> {\n const variable = this.responseVariable;\n if (!variable) return super.correctness;\n if (variable.value === null) return Correctness.Incorrect;\n\n if (variable.mapping) {\n const maxScore = variable.mapping.mapEntries.reduce((maximum, entry) => Math.max(entry.mappedValue, maximum), 0);\n for (const entry of variable.mapping.mapEntries) {\n let expected = entry.mapKey;\n let actual = variable.value as string;\n if (!entry.caseSensitive) {\n expected = expected.toLowerCase();\n actual = actual.toLowerCase();\n }\n if (expected !== actual) continue;\n if (entry.mappedValue === maxScore) return Correctness.Correct;\n if (entry.mappedValue <= (variable.mapping.defaultValue || 0)) return Correctness.Incorrect;\n return Correctness.PartiallyCorrect;\n }\n }\n\n return variable.correctResponse === variable.value ? Correctness.Correct : Correctness.Incorrect;\n }\n\n public override toggleInternalCorrectResponse(show: boolean): void {\n if (!this.showFullCorrectResponse) this.toggleFullCorrectResponse(show);\n }\n\n /** The badge goes between the field and the validation message; everything else is the base's. */\n override render() {\n return html`\n ${this.renderAnswer()} ${this.renderInput()}\n <span part=${this.correctionPart} aria-hidden=\"true\"></span>\n ${this.renderValidationMessage()}\n `;\n }\n}\n"],"mappings":"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","names":["Correctness","r","__decorate","__decorate","c","i","__decorate","i","__decorate","i","__decorate","i","__decorate","__decorate","c","b","previous","c"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { V as VariableDeclaration } from './
|
|
1
|
+
import { V as VariableDeclaration } from './item.types.d-QU7LljEK.js';
|
|
2
2
|
|
|
3
3
|
type ComputedItemContext = {
|
|
4
4
|
identifier: string;
|
|
@@ -15,8 +15,5 @@ type ComputedItemContext = {
|
|
|
15
15
|
completionStatus?: string;
|
|
16
16
|
variables: ReadonlyArray<VariableDeclaration<string | string[] | null>>;
|
|
17
17
|
};
|
|
18
|
-
declare const computedItemContext: {
|
|
19
|
-
__context__: Readonly<ComputedItemContext>;
|
|
20
|
-
};
|
|
21
18
|
|
|
22
|
-
export {
|
|
19
|
+
export type { ComputedItemContext as C };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ComputedItemContext } from './computed-item.
|
|
1
|
+
import { C as ComputedItemContext } from './computed-item.types.d-BKZdSLLJ.js';
|
|
2
2
|
|
|
3
3
|
type View = 'author' | 'candidate' | 'proctor' | 'scorer' | 'testConstructor' | 'tutor' | '';
|
|
4
4
|
interface SessionContext {
|
|
@@ -38,8 +38,5 @@ type ComputedContext = {
|
|
|
38
38
|
}[];
|
|
39
39
|
}[];
|
|
40
40
|
};
|
|
41
|
-
declare const computedContext: {
|
|
42
|
-
__context__: Readonly<ComputedContext>;
|
|
43
|
-
};
|
|
44
41
|
|
|
45
|
-
export { type ComputedContext as C, INITIAL_SESSION_CONTEXT as I, type SessionContext as S, type View as V, type ComputedItem as a,
|
|
42
|
+
export { type ComputedContext as C, INITIAL_SESSION_CONTEXT as I, type SessionContext as S, type View as V, type ComputedItem as a, sessionContext as s };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
type ValidationDisplayMode = 'inline' | 'native' | 'both' | 'none';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration context for QTI components. Provides runtime options for assessment item and
|
|
4
|
+
* interaction behavior.
|
|
5
|
+
*
|
|
6
|
+
* ── Three ways to set it, in the order you should reach for them ─────────────────────────────
|
|
7
|
+
*
|
|
8
|
+
* 1. **On a provider**, for real delivery. `qti-test` and `qti-item` both provide it, so setting
|
|
9
|
+
* `item.configContext = {…}` configures every interaction inside.
|
|
10
|
+
*
|
|
11
|
+
* 2. **On one interaction, directly** — the development-time route, and the reason
|
|
12
|
+
* `Interaction.configContext` is public:
|
|
13
|
+
*
|
|
14
|
+
* orderInteraction.configContext = { allowReorder: false };
|
|
15
|
+
*
|
|
16
|
+
* or, in a lit-html template, as a property binding — which lands before `connectedCallback`:
|
|
17
|
+
*
|
|
18
|
+
* html`<qti-order-interaction .configContext=${{ allowReorder: false }}>…`
|
|
19
|
+
*
|
|
20
|
+
* An interaction has to work standalone, so in a story or a spec there is usually no provider
|
|
21
|
+
* above it, and then nothing ever overwrites what you set. Where a provider DOES exist it wins on
|
|
22
|
+
* its next emit, because `@consume` writes that same field.
|
|
23
|
+
*
|
|
24
|
+
* A `qti-config-test-provider` element used to exist for scoping config to a subtree. It is gone:
|
|
25
|
+
* it was test-only yet registered itself into every consumer's element registry via an unguarded
|
|
26
|
+
* `@customElement`, which threw whenever two copies of this package ended up in one module graph.
|
|
27
|
+
* Bind the property on each interaction instead, or provide from `qti-item`.
|
|
28
|
+
*
|
|
29
|
+
* There is no merging at any level: @lit/context resolves to the nearest provider and that object
|
|
30
|
+
* replaces the ancestor's wholesale. A deeper provider therefore has to restate anything from above
|
|
31
|
+
* that it still wants.
|
|
32
|
+
*
|
|
33
|
+
* Note what is NOT here. Options an item author chooses per question are attributes on the
|
|
34
|
+
* interaction (`auto-size-dropzones`, `max-associations`, `disable-animations`); options only a
|
|
35
|
+
* developer chooses are mixin factory arguments or method overrides. This context is for what a
|
|
36
|
+
* delivery environment decides across items. `interactionContext` and `dragDropContext` are neither
|
|
37
|
+
* — they publish derived state (what a choice IS, what a drop HOLDS), never configuration.
|
|
38
|
+
*/
|
|
39
|
+
interface ConfigContext {
|
|
40
|
+
/**
|
|
41
|
+
* Optional category label for info items, used for reporting or display purposes.
|
|
42
|
+
* Example: "General Information", "Instructions".
|
|
43
|
+
*/
|
|
44
|
+
infoItemCategory?: string;
|
|
45
|
+
/**
|
|
46
|
+
* If true, calls reportValidity() on interactions after scoring to show validation feedback.
|
|
47
|
+
* Used to trigger UI validation after a scoring event.
|
|
48
|
+
*/
|
|
49
|
+
reportValidityAfterScoring?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Controls how validation feedback is displayed by interactions:
|
|
52
|
+
* - 'inline': render message in #validation-message (default behavior)
|
|
53
|
+
* - 'native': use browser-native reportValidity popup behavior
|
|
54
|
+
* - 'both': show both inline and native feedback
|
|
55
|
+
* - 'none': keep validity state only, without visual feedback
|
|
56
|
+
*/
|
|
57
|
+
validationDisplayMode?: ValidationDisplayMode;
|
|
58
|
+
/**
|
|
59
|
+
* If true, disables further user actions when an interaction reaches its configured maximum.
|
|
60
|
+
* Applies to both choice-based and drag/drop interactions.
|
|
61
|
+
*/
|
|
62
|
+
disableAfterMaxReached?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* If false, chips already placed in a drop target cannot be reordered or moved between targets in
|
|
65
|
+
* drag/drop sortable interactions (order, match, gap-match). Defaults to true. A per-interaction
|
|
66
|
+
* `allowReorder` property overrides this.
|
|
67
|
+
*/
|
|
68
|
+
allowReorder?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* If true, disables further selection in choice interactions after the maximum number of choices is reached.
|
|
71
|
+
* @deprecated Legacy alias for choice interactions. Prefer disableAfterMaxReached.
|
|
72
|
+
*/
|
|
73
|
+
disableAfterIfMaxChoicesReached?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Optional prompt text to display in inline choice interactions when no option is selected.
|
|
76
|
+
* Example: "Select an answer..."
|
|
77
|
+
*/
|
|
78
|
+
inlineChoicePrompt?: string;
|
|
79
|
+
/**
|
|
80
|
+
* If true, the inline choice interaction automatically measures the widest option and sizes the
|
|
81
|
+
* trigger button to match. Defaults to false.
|
|
82
|
+
* When a `qti-input-width-*` class is present on the interaction, that class width always takes
|
|
83
|
+
* precedence and autosizing is skipped regardless of this setting.
|
|
84
|
+
*/
|
|
85
|
+
inlineChoiceAutosize?: boolean;
|
|
86
|
+
}
|
|
87
|
+
declare const configContext: {
|
|
88
|
+
__context__: Readonly<ConfigContext>;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export { type ConfigContext as C, type ValidationDisplayMode as V, configContext as c };
|