@citolab/qti-components 8.2.0 → 9.1.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 (50) hide show
  1. package/cdn/index.global.js +1 -1
  2. package/cdn/index.js +190 -190
  3. package/dist/base.js +1 -1
  4. package/dist/{chunk-OVBG223G.js → chunk-3VQSUWCK.js} +173 -12
  5. package/dist/chunk-3VQSUWCK.js.map +1 -0
  6. package/dist/{chunk-Q6ZK4LRH.js → chunk-5BXJRO5O.js} +1792 -551
  7. package/dist/chunk-5BXJRO5O.js.map +1 -0
  8. package/dist/{chunk-OIUK5BFU.js → chunk-5SU3MP6Y.js} +811 -811
  9. package/dist/chunk-5SU3MP6Y.js.map +1 -0
  10. package/dist/{chunk-LMGJOBJA.js → chunk-DAUU2NJL.js} +5 -5
  11. package/dist/chunk-DAUU2NJL.js.map +1 -0
  12. package/dist/chunk-KCK27QBP.js +11 -0
  13. package/dist/chunk-KCK27QBP.js.map +1 -0
  14. package/dist/{chunk-M7K5C522.js → chunk-LDY4C2OT.js} +2 -2
  15. package/dist/chunk-MKZ374OJ.js +179 -0
  16. package/dist/chunk-MKZ374OJ.js.map +1 -0
  17. package/dist/{chunk-CRLXQZFA.js → chunk-QCPN7E6K.js} +14 -10
  18. package/dist/chunk-QCPN7E6K.js.map +1 -0
  19. package/dist/{chunk-U7YCXDYC.js → chunk-RT6WZ3P7.js} +2 -2
  20. package/dist/{chunk-7D3NKAGZ.js → chunk-WCWJPIUQ.js} +5 -4
  21. package/dist/chunk-WCWJPIUQ.js.map +1 -0
  22. package/dist/{chunk-YLRMOX6C.js → chunk-WKWCOV5P.js} +2 -2
  23. package/dist/chunk-XE7BALDO.js +7 -0
  24. package/dist/chunk-XE7BALDO.js.map +1 -0
  25. package/dist/{chunk-UC3T3NI3.js → chunk-XYQNTF5B.js} +2 -2
  26. package/dist/corrections.js +82 -7
  27. package/dist/corrections.js.map +1 -1
  28. package/dist/elements.js +3 -3
  29. package/dist/index.js +24 -24
  30. package/dist/interactions.js +14 -15
  31. package/dist/item.js +4 -4
  32. package/dist/processing.d.ts +26 -0
  33. package/dist/processing.js +3 -2
  34. package/dist/qti-components-jsx.d.ts +60 -4
  35. package/dist/test.js +5 -5
  36. package/package.json +7 -7
  37. package/dist/chunk-43XBJ47H.js +0 -1420
  38. package/dist/chunk-43XBJ47H.js.map +0 -1
  39. package/dist/chunk-7D3NKAGZ.js.map +0 -1
  40. package/dist/chunk-CRLXQZFA.js.map +0 -1
  41. package/dist/chunk-LMGJOBJA.js.map +0 -1
  42. package/dist/chunk-OIUK5BFU.js.map +0 -1
  43. package/dist/chunk-OVBG223G.js.map +0 -1
  44. package/dist/chunk-Q6ZK4LRH.js.map +0 -1
  45. package/dist/chunk-TLTYXWW7.js +0 -7
  46. package/dist/chunk-TLTYXWW7.js.map +0 -1
  47. /package/dist/{chunk-M7K5C522.js.map → chunk-LDY4C2OT.js.map} +0 -0
  48. /package/dist/{chunk-U7YCXDYC.js.map → chunk-RT6WZ3P7.js.map} +0 -0
  49. /package/dist/{chunk-YLRMOX6C.js.map → chunk-WKWCOV5P.js.map} +0 -0
  50. /package/dist/{chunk-UC3T3NI3.js.map → chunk-XYQNTF5B.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../interactions/core/src/elements/qti-associable-hotspot/qti-associable-hotspot.ts","../../interactions/core/src/elements/qti-associable-hotspot/qti-associable-hotspot.styles.ts","../../interactions/core/src/elements/qti-gap/qti-gap.ts","../../interactions/core/src/elements/qti-gap/qti-gap.styles.ts","../../interactions/core/src/elements/qti-gap-img/qti-gap-img.ts","../../interactions/core/src/elements/qti-gap-img/qti-gap-img.styles.ts","../../interactions/core/src/elements/qti-inline-choice/qti-inline-choice.ts","../../interactions/core/src/elements/qti-inline-choice/qti-inline-choice.styles.ts","../../interactions/core/src/elements/qti-prompt/qti-prompt.ts","../../interactions/core/src/elements/qti-prompt/qti-prompt.styles.ts","../../interactions/custom-interaction/src/qti-custom-interaction.ts","../../interactions/custom-interaction/src/qti-custom-interaction.styles.ts","../../interactions/end-attempt-interaction/src/qti-end-attempt-interaction.ts","../../interactions/end-attempt-interaction/src/qti-end-attempt-interaction.styles.ts","../../interactions/media-interaction/src/qti-media-interaction.ts","../../interactions/media-interaction/src/qti-media-interaction.styles.ts","../../interactions/position-object-interaction/src/qti-position-object-interaction.ts","../../interactions/position-object-interaction/src/qti-position-object-interaction.styles.ts","../../interactions/position-object-interaction/src/qti-position-object-stage.ts","../../interactions/position-object-interaction/src/qti-position-object-stage.styles.ts","../../interactions/upload-interaction/src/qti-upload-interaction.ts","../../interactions/upload-interaction/src/qti-upload-interaction.styles.ts","../../interactions/core/src/elements/qti-associable-hotspot/elements.ts","../../interactions/core/src/elements/qti-gap/elements.ts","../../interactions/core/src/elements/qti-gap-img/elements.ts","../../interactions/core/src/elements/qti-gap-text/elements.ts","../../interactions/core/src/elements/qti-hotspot-choice/elements.ts","../../interactions/core/src/elements/qti-hottext/elements.ts","../../interactions/core/src/elements/qti-inline-choice/elements.ts","../../interactions/core/src/elements/qti-prompt/elements.ts","../../interactions/core/src/elements/qti-simple-associable-choice/elements.ts","../../interactions/core/src/elements/qti-simple-choice/elements.ts","../../interactions/core/src/elements.ts","../../interactions/custom-interaction/src/elements.ts","../../interactions/end-attempt-interaction/src/elements.ts","../../interactions/media-interaction/src/elements.ts","../../interactions/position-object-interaction/src/elements.ts","../../interactions/upload-interaction/src/elements.ts","../../qti-interactions/src/elements.ts","../../qti-interactions/src/register-all.ts","../../interactions/associate-interaction/src/register.ts","../../interactions/choice-interaction/src/register.ts","../../interactions/custom-interaction/src/register.ts","../../interactions/end-attempt-interaction/src/register.ts","../../interactions/extended-text-interaction/src/register.ts","../../interactions/gap-match-interaction/src/register.ts","../../interactions/graphic-associate-interaction/src/register.ts","../../interactions/graphic-gap-match-interaction/src/register.ts","../../interactions/graphic-order-interaction/src/register.ts","../../interactions/hotspot-interaction/src/register.ts","../../interactions/hottext-interaction/src/register.ts","../../interactions/inline-choice-interaction/src/register.ts","../../interactions/match-interaction/src/register.ts","../../interactions/media-interaction/src/register.ts","../../interactions/order-interaction/src/register.ts","../../interactions/portable-custom-interaction/src/register.ts","../../interactions/position-object-interaction/src/register.ts","../../interactions/select-point-interaction/src/register.ts","../../interactions/slider-interaction/src/register.ts","../../interactions/text-entry-interaction/src/register.ts","../../interactions/upload-interaction/src/register.ts"],"sourcesContent":["import { LitElement, html } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { consume } from '@lit/context';\n\nimport { dragDropContext } from '../../context/drag-drop.context';\nimport styles from './qti-associable-hotspot.styles';\n\nimport type { DragDropState } from '../../context/drag-drop.context';\nimport type { CSSResultGroup } from 'lit';\n\n/**\n * A drop target positioned over an image. Like `qti-gap`, it renders the chips it holds from\n * `dragDropContext` rather than having them appended into it.\n *\n * @csspart drop - The region a chip lands in.\n */\nexport class QtiAssociableHotspot extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n /** Carries `:state(filled)` while the hotspot holds a chip. */\n public internals: ElementInternals = this.attachInternals();\n\n /** Opt-in marker read by `DragDropSlottedMixin`; see qti-gap. */\n public readonly acceptsDeclarativeDrops = true;\n\n @property({ type: String, reflect: true }) identifier: string;\n\n @consume({ context: dragDropContext, subscribe: true })\n @state()\n private _dragDrop?: Readonly<DragDropState>;\n\n /** The chips this hotspot holds. Stable node references, cloned once at drop time. */\n public get drags(): readonly HTMLElement[] {\n return this._dragDrop?.nodesByTarget?.[this.identifier] ?? [];\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this.dispatchEvent(\n new CustomEvent('qti-register-hotspot', {\n bubbles: true,\n composed: true,\n cancelable: false\n })\n );\n }\n\n override render() {\n return html`<div part=\"drop\">\n ${repeat(\n this.drags,\n node => node.getAttribute('identifier'),\n node => node\n )}\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-associable-hotspot': QtiAssociableHotspot;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing, dropRegion } from '@qti-components/base';\n\nexport default [\n boxSizing,\n dropRegion,\n css`\n /* A drop target — see qti-gap.styles.ts. The interaction publishes the chip measurements as\n custom properties on its host; the properties themselves live here. */\n :host {\n display: flex;\n align-items: center;\n justify-content: center;\n user-select: none;\n position: absolute;\n min-height: var(--qti-dropzone-min-height, 0);\n min-width: var(--qti-dropzone-min-width, 0);\n }\n\n /* The hotspot's own box comes from its authored coords; the drop region simply fills it. */\n [part~='drop'] {\n width: 100%;\n height: 100%;\n }\n `\n];\n","import { html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { consume } from '@lit/context';\n\nimport { dragDropContext } from '../../context/drag-drop.context';\nimport styles from './qti-gap.styles';\n\nimport type { DragDropState } from '../../context/drag-drop.context';\nimport type { CSSResultGroup } from 'lit';\n\n/**\n * A gap in the prose, and the first drop target to render its own chips.\n *\n * The interaction owns placement and publishes it on `dragDropContext`; this element subscribes and\n * renders what it holds. Nothing appends into it. That inverts the old flow, where `handleDrop` did\n * `cloneNode` + `appendChild` and the response was recovered afterwards by reading the DOM back\n * out — which is why placement and the response could ever disagree at all.\n *\n * The chips land in this shadow root rather than in the light DOM, so a theme reaches them as\n * `::part(drag)` — a bare `::part()` matches in any shadow root — instead of by tag. The gap's own\n * `:state(filled)` says whether it holds anything.\n *\n * @customElement qti-gap\n *\n * @attr {string} identifier - Required. Value recorded as the gap side of the response pair.\n * @attr {number} [match-max=1] - How many tokens this gap can hold; `0` means unlimited. Read\n * from the DOM by the drag-drop mixin.\n * @attr {number} [match-min=0] - Minimum tokens this gap must hold.\n * @attr {boolean} [required=false] - Not implemented. Whether this gap must be filled for the\n * response to be valid.\n * @attr {string} template-identifier - Not implemented. Identifier of a template variable\n * controlling this gap's visibility.\n * @attr {'show'|'hide'} [show-hide=show] - Not implemented. How `template-identifier` controls\n * visibility.\n *\n * @csspart drop - The region a chip lands in. Reserves the widest chip's box; see qti-gap.styles.\n */\nexport class QtiGap extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n /** Carries `:state(filled)` while the gap holds a chip. */\n public internals: ElementInternals = this.attachInternals();\n\n /**\n * Opt-in marker, read by `DragDropSlottedMixin`. While this is true the interaction keeps this\n * target's chips in its placement map and never touches this element's children.\n */\n public readonly acceptsDeclarativeDrops = true;\n\n @property({ type: Number, reflect: true }) tabindex: number | undefined = 0;\n @property({ type: String, reflect: true }) identifier: string;\n\n @consume({ context: dragDropContext, subscribe: true })\n @state()\n private _dragDrop?: Readonly<DragDropState>;\n\n /** The chips this gap holds. Stable node references, cloned once at drop time by the interaction. */\n public get drags(): readonly HTMLElement[] {\n return this._dragDrop?.nodesByTarget?.[this.identifier] ?? [];\n }\n\n override render() {\n // Lit renders a `Node` by reference, so a stable node is moved rather than recreated. Keyed by\n // identifier so `repeat` reorders instead of rebuilding.\n return html`<div part=\"drop\">\n ${repeat(\n this.drags,\n node => node.getAttribute('identifier'),\n node => node\n )}\n </div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-gap': QtiGap;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing, dropRegion } from '@qti-components/base';\n\nexport default [\n boxSizing,\n dropRegion,\n css`\n /*\n * A drop target. The interaction measures its chips and publishes the result as custom\n * properties on its own host; the actual CSS properties live here, not in a style attribute.\n *\n * An authored data-choices-container-width takes the width axis: autoSizeDropzoneWidth goes\n * false and the mixin never publishes --qti-dropzone-min-width at all, so the fallback below\n * applies and the authored inline width is free to win. That works only because the token is\n * never declared globally — min-width beats width, so a declared floor would silently outrank\n * the author. See DROP-SIZING.md §2 and tools/stylelint/no-declared-measured-token.js.\n */\n /*\n * A gap sits in a line of prose, so it is inline-flex and rides the text baseline. All four of\n * these were in the theme, set on this host from the document — which also meant the\n * 'display: flex' this file declared never took effect.\n */\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n vertical-align: middle;\n user-select: none;\n }\n\n /*\n * The chip's box is reserved on the slot, not on the host.\n *\n * --qti-dropzone-min-* is the border-box of the widest and tallest chip, so whatever carries\n * that minimum must have no border or padding of its own — otherwise the theme's dashed gap\n * border eats into the reservation, the gap comes up short, and it grows the instant a chip\n * lands in it. That reflows the sentence and drags the neighbouring gaps sideways while the\n * user is still on their way to one.\n *\n * It cannot live on :host. A theme's universal reset matches the host element from the\n * document, and document rules outrank :host — so the host is border-box no matter what this\n * file says. This div is inside the shadow tree, out of the document's reach, and inherits\n * border-box harmlessly since it has no border or padding of its own.\n */\n [part~='drop'] {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: var(--qti-dropzone-min-height, 0);\n min-width: var(--qti-dropzone-min-width, 0);\n }\n `\n];\n","import { LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport styles from './qti-gap-img.styles';\n\nimport type { CSSResultGroup } from 'lit';\n\nexport class QtiGapImg extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n @property({ type: Number, reflect: true }) tabindex: number | undefined = 0;\n\n /**\n * `qti-gap-img` is a draggable chip, so it needs ElementInternals to carry the drag states\n * (`dragging`, `placeholder`). It works without a shadow root.\n *\n * NOTE: this element never calls `super.connectedCallback()`, so Lit never enables updating\n * and it has no shadow root — which makes `qti-gap-img.styles.ts` dead code. Fixing that means\n * adding a `<slot>` to a `render()` first, otherwise the authored `<img>` child disappears.\n */\n public internals: ElementInternals = this.attachInternals();\n\n override connectedCallback() {\n this.setAttribute('slot', 'drags');\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-gap-img': QtiGapImg;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n /* Centred, because a gap-img is a picture inside a drop the same size as it. Was in the theme's\n graphic-gap-match rules, on the host from the document. */\n :host {\n display: flex;\n align-items: center;\n justify-content: center;\n user-select: none;\n }\n `\n];\n","import { html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { ActiveElementMixin } from '../../mixins/active-element/active-element.mixin.js';\nimport styles from './qti-inline-choice.styles.js';\n\nimport type { CSSResultGroup } from 'lit';\nimport type { PropertyValues } from 'lit';\n/**\n * An option in the dropdown of `qti-inline-choice-interaction`.\n *\n * @customElement qti-inline-choice\n *\n * @attr {string} identifier - Required. Value recorded in the response when this option is\n * selected.\n * @attr {boolean} [fixed=false] - Pins this option in place when the interaction is shuffled.\n * @attr {string} template-identifier - Not implemented. Identifier of a template variable\n * controlling this option's visibility.\n * @attr {'show'|'hide'} [show-hide=show] - Not implemented. How `template-identifier` controls\n * visibility.\n */\nexport class QtiInlineChoice extends ActiveElementMixin(LitElement, 'qti-inline-choice') {\n static override styles: CSSResultGroup = styles;\n\n @property({ type: String })\n identifier: string;\n\n override connectedCallback() {\n super.connectedCallback();\n\n this.addEventListener('click', this.#onSelectInlineChoice);\n\n this.dispatchEvent(\n new CustomEvent('qti-inline-choice-register', {\n bubbles: true,\n composed: true,\n cancelable: false\n })\n );\n }\n\n override disconnectedCallback() {\n this.removeEventListener('click', this.#onSelectInlineChoice);\n }\n\n override render() {\n return html` <slot></slot> `;\n }\n\n #onSelectInlineChoice() {\n // if (this.disabled || this.readonly) return;\n\n this.dispatchEvent(\n new CustomEvent('qti-inline-choice-select', {\n bubbles: true,\n cancelable: false,\n composed: true,\n detail: { identifier: this.identifier }\n })\n );\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-inline-choice': QtiInlineChoice;\n }\n}\n","import { css } from 'lit';\n\nimport type { CSSResultGroup } from 'lit';\n\nconst styles: CSSResultGroup = css`\n /*\n * An option row: one line, clipped, with its text centred against the row's min-height. All four\n * were in the theme, set on this host from the document — which is also why the 'display: block'\n * this file declared never took effect.\n */\n :host {\n display: inline-flex;\n align-items: center;\n white-space: nowrap;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n slot {\n display: inline;\n }\n`;\n\nexport default styles;\n","import { html, LitElement } from 'lit';\n\nimport styles from './qti-prompt.styles';\n\nimport type { CSSResultGroup } from 'lit';\n\nexport class QtiPrompt extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n override render() {\n return html`<slot></slot>`;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n // if prompts are in interactions they should have a slot, so the prompt has to go there\n // if prompt is in the body, then just display the prompt there.\n // A better check would be the latter, but not can't get through the shadowroot to find the slot\n const inInteraction = this.parentElement?.tagName.endsWith('INTERACTION');\n if (inInteraction) {\n this.setAttribute('slot', 'prompt');\n }\n // const promptSlot = this.parentElement.shadowRoot.querySelector(\"[name='prompt']\");\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-prompt': QtiPrompt;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n :host {\n display: block;\n margin: var(--qti-gap) 0;\n width: 100%;\n }\n `\n];\n","import { html } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { Interaction, removeDoubleSlashes } from '@qti-components/base';\n\nimport styles from './qti-custom-interaction.styles';\n\nimport type { CSSResultGroup } from 'lit';\n\n/**\n * CES (Custom Element Standard) Custom Interaction Support\n *\n * This component provides runtime support for legacy custom interactions that were built\n * for the CES player - the predecessor to what is now known as FACET and the Trifork QTI Player.\n *\n * These custom interactions use a specific API pattern:\n * - A manifest.json file that references script, style, and media files\n * - A bootstrap.js script that creates an iframe and loads the interaction's index.html\n * - A global CES object that provides: getMedia(), getResponse(), setResponse(), setStageHeight()\n *\n * The challenge is that when these interactions are embedded in iframes (especially those\n * created via document.write() which have about:blank origin), they cannot:\n * - Access the parent's global CES object (cross-origin restriction)\n * - Load external scripts via service workers (about:blank is not controlled)\n *\n * This implementation solves these problems by:\n * 1. Fetching the interaction's index.html from the main window (where service workers work)\n * 2. Injecting a CES proxy (registerCES) that uses postMessage to communicate with the parent\n * 3. Creating a blob URL for the modified HTML\n * 4. Using a simplified bootstrap (ciBootstrap) that loads the pre-created blob URL\n *\n * This approach is transparent - the original package files remain unchanged and the\n * transformation happens entirely at runtime within this web component.\n */\n\n// CES API proxy that gets injected into the index.html\n// This provides the CES object that the custom interaction expects,\n// but uses postMessage to communicate with the parent qti-custom-interaction component\nconst registerCES = `\nconst postToParentWindows = (type, data) => {\n window.top.postMessage(data ? { type, data } : { type }, '*');\n let w = window.parent;\n while (w) {\n if (w !== window.top) {\n w.postMessage({ type, data }, '*');\n }\n if (w !== w.parent) {\n w = w.parent;\n } else {\n w = null;\n }\n }\n};\n\nwindow.CES = {\n media: null,\n response: null,\n load: () => {\n let resolveCount = 0;\n\n const handleMessage = (event) => {\n if (event.data.type === \"mediaData\") {\n const media = event.data.data;\n CES.media = media;\n resolveCount++;\n } else if (event.data.type === \"responseData\") {\n const response = event.data.data;\n if (response && Array.isArray(response) && response.length > 0) {\n // state is stored in the first element of the array\n CES.response = response[0];\n // Wait a short moment to ensure CES.response is set\n setTimeout(() => {\n // Re-create the Controller instance if it exists\n if (typeof Controller === 'function') {\n console.log(\"Re-creating Controller instance\");\n ctrl = new Controller();\n }\n }, 50);\n } else { \n CES.response = response;\n }\n resolveCount++;\n }\n if (resolveCount === 2) {\n //window.removeEventListener(\"message\", handleMessage);\n }\n };\n window.addEventListener(\"message\", handleMessage);\n postToParentWindows(\"getMedia\");\n postToParentWindows(\"getResponse\");\n },\n setResponse: (data) => {\n postToParentWindows(\"setResponse\", data);\n },\n getResponse: () => {\n return CES.response;\n },\n getMedia: () => {\n return CES.media;\n },\n setStageHeight: () => {\n postToParentWindows(\"setStageHeight\");\n },\n};\nCES.load();\n`;\n\n// Simple bootstrap that just waits for the blob URL and creates the iframe\nconst ciBootstrap = `\n (function() {\n var blobUrlReceived = null;\n \n const createIframe = () => {\n if (!blobUrlReceived || !document.body) return;\n var n = document.createElement('iframe');\n n.frameBorder = '0';\n n.scrolling = 'no';\n n.src = blobUrlReceived;\n n.style.width = '100%';\n n.style.height = '100%';\n document.body.appendChild(n);\n };\n \n const handleMessage = (event) => {\n if (event.data.type === 'blobUrl') {\n blobUrlReceived = event.data.data;\n window.removeEventListener('message', handleMessage);\n createIframe();\n }\n };\n \n window.addEventListener('message', handleMessage);\n \n // Wait for document ready before requesting blobUrl\n const requestBlobUrl = () => {\n let w = window.parent;\n while (w) {\n w.postMessage({ type: 'getBlobUrl' }, '*');\n if (w !== w.parent) {\n w = w.parent;\n } else {\n w = null;\n }\n }\n };\n \n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', requestBlobUrl);\n } else {\n requestBlobUrl();\n }\n })();\n`;\n\n/**\n * QTI Custom Interaction component for legacy CES-based interactions.\n *\n * This component implements support for custom interactions originally built for the CES\n * (Custom Element Standard) player - the predecessor to FACET and the Trifork QTI Player.\n *\n * @remarks\n * The interaction workflow:\n * 1. Fetch the CI manifest (JSON file with script, style, media references)\n * 2. Check if bootstrap.js uses the CES API\n * 3. If CES is used:\n * - Fetch index.html from main window (where service worker/fetch works)\n * - Inject registerCES proxy script for postMessage-based communication\n * - Create blob URL and pass it to ciBootstrap\n * 4. Create pciContainer iframe with style and bootstrap script\n * 5. Handle postMessage events for getMedia, getResponse, setResponse, getBlobUrl\n *\n * The postMessage bridge is necessary because:\n * - Iframes created via document.write() have about:blank origin\n * - They cannot access the parent's global CES object (cross-origin)\n * - Service workers don't control about:blank documents\n *\n * Messages are sent to all parent windows to support embedding scenarios like Storybook\n * where window.top might not be the actual host application.\n */\n\nexport class QtiCustomInteraction extends Interaction {\n #rawResponse: string | string[] = '';\n #manifestUrl: string = null;\n #resourceBaseUrl: string = null;\n static override styles: CSSResultGroup = styles;\n\n constructor() {\n super();\n this.handlePostMessage = this.handlePostMessage.bind(this);\n }\n\n @property({ type: String, attribute: 'data' })\n data: string;\n\n @property({ type: String, attribute: 'data-base-item' })\n baseItemUrl: string;\n\n @property({ type: String, attribute: 'data-base-ref' })\n baseRefUrl: string;\n\n @property({ type: String, attribute: 'id' })\n override id: string;\n\n @state()\n private _errorMessage: string = null;\n manifest: {\n script: string[];\n style: string[];\n media: string[];\n };\n // Pre-created blob URL for the index.html with injected CES proxy\n #contentBlobUrl: string = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n // Support two QTI formats:\n // 1. data attribute directly on qti-custom-interaction: <qti-custom-interaction data=\"manifest.json\">\n // 2. object child element: <qti-custom-interaction><object data=\"manifest.json\"></qti-custom-interaction>\n let manifestPath = this.data;\n\n if (!manifestPath) {\n // Try to get from child <object> element\n const objectEl = this.querySelector('object[data]');\n if (objectEl) {\n manifestPath = objectEl.getAttribute('data');\n // Also get width/height from the object element if available\n const width = objectEl.getAttribute('width');\n const height = objectEl.getAttribute('height');\n if (width) this.setAttribute('width', width);\n if (height) this.setAttribute('height', height);\n }\n }\n\n if (!manifestPath) {\n this._errorMessage = 'No manifest path found (neither data attribute nor object child)';\n return;\n }\n\n const uriToManifest =\n manifestPath.startsWith('http') || manifestPath.startsWith('blob')\n ? manifestPath\n : removeDoubleSlashes((this.baseItemUrl || '') + '/' + manifestPath);\n this.#manifestUrl = new URL(uriToManifest, window.location.href).toString();\n // fetch the json file located at the data attribute\n fetch(uriToManifest)\n .then(response => {\n return response.json();\n })\n .then(data => {\n this.manifest = data;\n this.setupCES();\n })\n .catch(err => {\n this._errorMessage = err;\n });\n }\n\n /**\n * Sets up the CES custom interaction by creating the iframe structure and\n * handling the CES API communication via postMessage.\n *\n * For interactions that use CES, this method:\n * 1. Fetches the original bootstrap.js and checks if it uses CES\n * 2. If CES is used, fetches index.html and injects the registerCES proxy\n * 3. Creates a blob URL for the modified HTML (stored in _contentBlobUrl)\n * 4. Replaces bootstrap.js with ciBootstrap that loads the blob URL\n * 5. Sets up postMessage listeners for CES API calls\n */\n async setupCES() {\n // Ensure the iframe exists and has a document before writing into it.\n // In some environments (e.g. Storybook/Vitest browser mode) the iframe can exist but its\n // `contentDocument` is still null momentarily, which would otherwise cause an unhandled rejection.\n await this.updateComplete;\n const iframe = this.shadowRoot?.querySelector('#pciContainer') as HTMLIFrameElement | null;\n if (!iframe) {\n this._errorMessage = 'pciContainer iframe not found';\n return;\n }\n\n if (!iframe.getAttribute('src')) {\n // Make sure the iframe navigates so we get a document we can write to.\n iframe.setAttribute('src', 'about:blank');\n }\n\n let iframeDoc = iframe.contentDocument ?? iframe.contentWindow?.document ?? null;\n if (!iframeDoc) {\n await new Promise<void>(resolve => iframe.addEventListener('load', () => resolve(), { once: true }));\n iframeDoc = iframe.contentDocument ?? iframe.contentWindow?.document ?? null;\n }\n if (!iframeDoc) {\n this._errorMessage = 'pciContainer iframe document not available';\n return;\n }\n\n if (!this.manifest.script || this.manifest.script.length === 0) {\n this._errorMessage = 'No script found in manifest';\n return;\n }\n if (!this.manifest.style || this.manifest.style.length === 0) {\n this._errorMessage = 'No style found in manifest';\n return;\n }\n const cssRef = this.manifest.style[0];\n\n const baseCandidates = this.#getBaseCandidates();\n\n const cssResolved = await this.#resolveResourceWithFallback(cssRef, baseCandidates);\n const cssUrl = cssResolved.url;\n if (cssResolved.baseUrl && !this.#resourceBaseUrl) {\n this.#resourceBaseUrl = cssResolved.baseUrl;\n }\n\n // Always use the built-in ciBootstrap instead of the package's bootstrap.js.\n // The package's bootstrap.js is the original CES version which doesn't work\n // in the iframe/postMessage setup. Our ciBootstrap handles this correctly.\n const usesCES = true;\n\n // If the original bootstrap.js uses CES, we need to:\n // 1. Fetch the index.html from here (main window, where service worker works)\n // 2. Inject the registerCES proxy script\n // 3. Create a blob URL and store it\n // 4. Use ciBootstrap to request and load the blob URL\n if (usesCES) {\n // Try to get index.html path from manifest.media, or construct it from the manifest path\n let indexUrl = '';\n if (this.manifest.media && this.manifest.media.length > 0) {\n const mediaRef = this.manifest.media[0];\n const indexResolved = await this.#resolveResourceWithFallback(mediaRef, baseCandidates, {\n returnText: true\n });\n indexUrl = indexResolved.url;\n if (indexResolved.baseUrl && !this.#resourceBaseUrl) {\n this.#resourceBaseUrl = indexResolved.baseUrl;\n }\n if (indexResolved.text) {\n let html = indexResolved.text;\n\n // Check if the HTML was already modified (e.g., by backend import process)\n // If it already has postToParentWindows or CES proxy, skip injection\n const alreadyModified = html.includes('postToParentWindows') || html.includes('window.CES');\n\n if (!alreadyModified) {\n // Inject the CES proxy script after <head>\n const cesScript = '<script>' + registerCES + '</' + 'script>';\n const headIndex = html.indexOf('<head>');\n if (headIndex !== -1) {\n html = html.slice(0, headIndex + 6) + cesScript + html.slice(headIndex + 6);\n } else {\n // If no <head>, prepend to document\n html = cesScript + html;\n }\n }\n\n // Create a blob URL for the modified HTML\n const blob = new Blob([html], { type: 'text/html' });\n this.#contentBlobUrl = URL.createObjectURL(blob);\n }\n } else {\n // If no media array, try to construct index.html path from the manifest location\n // Assume index.html is in the same directory as the manifest\n const manifestPath = this.data || 'manifest.json';\n const basePath = manifestPath.includes('/') ? manifestPath.substring(0, manifestPath.lastIndexOf('/')) : '';\n const indexPath = basePath ? `${basePath}/index.html` : 'index.html';\n const indexResolved = await this.#resolveResourceWithFallback(indexPath, baseCandidates, {\n returnText: true\n });\n indexUrl = indexResolved.url;\n if (indexResolved.baseUrl && !this.#resourceBaseUrl) {\n this.#resourceBaseUrl = indexResolved.baseUrl;\n }\n if (indexResolved.text) {\n let html = indexResolved.text;\n\n // Check if the HTML was already modified (e.g., by backend import process)\n const alreadyModified = html.includes('postToParentWindows') || html.includes('window.CES');\n\n if (!alreadyModified) {\n // Inject the CES proxy script after <head>\n const cesScript = '<script>' + registerCES + '</' + 'script>';\n const headIndex = html.indexOf('<head>');\n if (headIndex !== -1) {\n html = html.slice(0, headIndex + 6) + cesScript + html.slice(headIndex + 6);\n } else {\n // If no <head>, prepend to document\n html = cesScript + html;\n }\n }\n\n // Create a blob URL for the modified HTML\n const blob = new Blob([html], { type: 'text/html' });\n this.#contentBlobUrl = URL.createObjectURL(blob);\n }\n }\n\n if (indexUrl && !this.#contentBlobUrl) {\n try {\n const indexResponse = await fetch(indexUrl);\n if (indexResponse.ok) {\n let html = await indexResponse.text();\n\n // Check if the HTML was already modified (e.g., by backend import process)\n const alreadyModified = html.includes('postToParentWindows') || html.includes('window.CES');\n\n if (!alreadyModified) {\n // Inject the CES proxy script after <head>\n const cesScript = '<script>' + registerCES + '</' + 'script>';\n const headIndex = html.indexOf('<head>');\n if (headIndex !== -1) {\n html = html.slice(0, headIndex + 6) + cesScript + html.slice(headIndex + 6);\n } else {\n // If no <head>, prepend to document\n html = cesScript + html;\n }\n }\n\n // Create a blob URL for the modified HTML\n const blob = new Blob([html], { type: 'text/html' });\n this.#contentBlobUrl = URL.createObjectURL(blob);\n } else {\n console.error(`Failed to fetch index.html: ${indexResponse.status}`);\n }\n } catch (e) {\n console.error(`Error fetching index.html: ${e}`);\n }\n }\n }\n\n const inlineScript = `<script>${ciBootstrap}</` + 'script>';\n\n window.addEventListener('message', this.handlePostMessage);\n\n const htmlContent = `\n <!DOCTYPE html>\n <html>\n <head>\n ${cssUrl ? `<link href='${cssUrl}' rel=\"stylesheet\" />` : ''}\n ${inlineScript}\n </head>\n <body></body>\n </html>\n `;\n\n // Use srcdoc instead of document.write for better script execution\n iframe.srcdoc = htmlContent;\n }\n\n #getIFrames() {\n const iframesInShadowRoot = this.shadowRoot.querySelectorAll('iframe');\n const iframe = this.querySelectorAll('iframe');\n\n const outerIFrames = [...iframesInShadowRoot, ...iframe];\n for (const iframe of outerIFrames) {\n const iframeSrc = iframe.src;\n const isSameOrigin = new URL(iframeSrc, window.location.href).origin === window.location.origin;\n if (isSameOrigin) {\n try {\n const outerDoc = iframe.contentDocument || iframe.contentWindow.document;\n if (outerDoc) {\n this.#getInnerIFrames(outerDoc, outerIFrames);\n }\n } catch (e) {\n console.error('Error accessing nested iframe:', e);\n }\n }\n }\n // get only unique iframes\n outerIFrames.forEach((iframe, index) => {\n if (outerIFrames.indexOf(iframe) !== index) {\n outerIFrames.splice(index, 1);\n }\n });\n return outerIFrames;\n }\n\n #getInnerIFrames(iframeDocument: Document, iframes: HTMLIFrameElement[] = []) {\n // Get all iframes in the current document\n const currentIframes = iframeDocument.querySelectorAll('iframe');\n\n currentIframes.forEach(iframe => {\n // Add the current iframe to the list\n iframes.push(iframe);\n\n // Recursively get iframes within the current iframe\n // Check if the iframe src is from the same origin\n const iframeSrc = iframe.src;\n const isSameOrigin = new URL(iframeSrc, window.location.href).origin === window.location.origin;\n\n if (isSameOrigin) {\n try {\n const nestedDoc = iframe.contentDocument || iframe.contentWindow.document;\n this.#getInnerIFrames(nestedDoc, iframes);\n } catch (e) {\n console.error('Error accessing nested iframe:', e);\n }\n } else {\n console.warn('Skipped cross-origin iframe:', iframeSrc);\n }\n });\n\n return iframes;\n }\n\n #postToWindowAndIframes(type: string, data: any) {\n window.postMessage({ type, data }, '*');\n const iframes = this.#getIFrames();\n for (const iframe of iframes) {\n if (iframe.contentWindow) {\n iframe.contentWindow.postMessage({ type, data }, '*');\n }\n }\n }\n\n handlePostMessage(event: MessageEvent) {\n const { type, data } = event.data;\n switch (type) {\n case 'setResponse':\n if (data === null || !(Array.isArray(data) && data.length === 1 && data[0] === '')) {\n this.#rawResponse = data;\n this.saveResponse(data);\n }\n break;\n case 'getResponse': {\n this.#postToWindowAndIframes('responseData', this.#rawResponse);\n break;\n }\n case 'getBlobUrl': {\n // Send the pre-created blob URL to the requesting iframe\n if (this.#contentBlobUrl) {\n this.#postToWindowAndIframes('blobUrl', this.#contentBlobUrl);\n // Also respond directly to the source window if possible\n if (event.source && event.source !== window) {\n (event.source as Window).postMessage({ type: 'blobUrl', data: this.#contentBlobUrl }, '*');\n }\n }\n break;\n }\n case 'getMedia': {\n const baseCandidates = this.#getBaseCandidates();\n const mediaData = this.manifest.media.map(media => {\n if (media.startsWith('http') || media.startsWith('blob')) {\n return media;\n }\n const baseUrl = this.#resourceBaseUrl || baseCandidates[0];\n if (!baseUrl) {\n return media;\n }\n return new URL(media, baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`).toString();\n });\n this.#postToWindowAndIframes('mediaData', mediaData);\n break;\n }\n case 'setStageHeight':\n console.log('setStageHeight not implemented');\n break;\n }\n }\n\n validate(): boolean {\n if (!this.#rawResponse) {\n return false;\n }\n if (Array.isArray(this.#rawResponse)) {\n if (this.#rawResponse.length === 0) {\n return false;\n }\n // check if one of the values has a value\n for (const value of this.#rawResponse) {\n if (value !== '' && value !== null) {\n return true;\n }\n }\n }\n return true;\n }\n\n get response(): string | string[] | null {\n return (this.#rawResponse as string | string[]) || null;\n }\n\n set response(val: string | string[] | null) {\n if (typeof val === 'string') {\n this.#rawResponse = val;\n this.saveResponse(val);\n } else if (Array.isArray(val)) {\n this.#rawResponse = val;\n } else if (!val) {\n // do nothing\n } else {\n throw new Error('Value must be a string or an array of strings');\n }\n }\n\n override disconnectedCallback(): void {\n window.removeEventListener('message', this.handlePostMessage);\n super.disconnectedCallback();\n }\n\n override render() {\n return html`<iframe\n width=${this.getAttribute('width')}\n height=${this.getAttribute('height')}\n frameborder=\"0\"\n title=\"pciContainer\"\n id=\"pciContainer\"\n >\n </iframe>\n ${this._errorMessage &&\n html`<div style=\"color:red\">\n <h1>Error</h1>\n ${this._errorMessage}\n </div>`}`;\n }\n\n #getBaseCandidates(): string[] {\n const candidates = [this.#resourceBaseUrl, this.baseRefUrl, this.baseItemUrl, this.#getManifestBaseUrl()];\n const resolved = candidates.filter(Boolean).map(base => new URL(base, window.location.href).toString());\n\n // Also add the manifest's parent directory (e.g. go up from .../json/ to .../)\n const manifestParent = this.#getManifestParentBaseUrl();\n if (manifestParent) {\n resolved.push(manifestParent);\n }\n\n // Deduplicate\n return [...new Set(resolved)];\n }\n\n #getManifestBaseUrl(): string | null {\n if (!this.#manifestUrl) {\n return null;\n }\n return new URL('.', this.#manifestUrl).toString();\n }\n\n #getManifestParentBaseUrl(): string | null {\n if (!this.#manifestUrl) {\n return null;\n }\n // Go up one more level from the manifest directory (e.g. from .../json/ to .../)\n // This helps when manifest.json is in a subdirectory but resources are at the parent level\n return new URL('..', this.#manifestUrl).toString();\n }\n\n async #resolveResourceWithFallback(\n ref: string,\n baseCandidates: string[],\n options: { returnText?: boolean } = {}\n ): Promise<{ url: string; baseUrl: string | null; text?: string }> {\n if (!ref) {\n return { url: '', baseUrl: null };\n }\n if (ref.startsWith('http') || ref.startsWith('blob')) {\n return { url: ref, baseUrl: null };\n }\n\n for (const base of baseCandidates) {\n const baseUrl = new URL(base, window.location.href).toString();\n const url = new URL(ref, baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`).toString();\n try {\n const response = await fetch(url);\n if (response.ok) {\n if (options.returnText) {\n const text = await response.text();\n return { url, baseUrl, text };\n }\n return { url, baseUrl };\n }\n } catch (e) {\n // try next base\n }\n }\n\n return { url: '', baseUrl: null };\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-custom-interaction': QtiCustomInteraction;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n /* The box this element already had. See the note in qti-match-interaction.styles.ts. */\n :host {\n display: block;\n }\n `\n];\n","import { html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport styles from './qti-end-attempt-interaction.styles';\n\nimport type { CSSResultGroup } from 'lit';\n/**\n * A button that ends the current attempt.\n *\n * @csspart button - The end-attempt button element.\n */\nexport class QtiEndAttemptInteraction extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n @property({ type: String, attribute: 'response-identifier' }) responseIdentifier: string;\n\n @property({ reflect: true, type: Boolean }) disabled = false;\n\n /** Defines the number of attempts that a user can make using the 'endAttemptInteraction' mechanism (this can be used to limit the number of hints, etc.). [More information](https://www.imsglobal.org/sites/default/files/spec/qti/v3/info/index.html#DataCharacteristic_EndAttemptInteraction.Attr_count-attempt) */\n @property({ type: String, attribute: 'count-attempt' })\n public countAttempt: 'true' | 'false' | null = null;\n\n @property({ type: String })\n public override title: string = 'end attempt';\n\n override render() {\n return html`<button ?disabled=${this.disabled} part=\"button\" @click=${this.endAttempt}>${this.title}</button>`;\n }\n public endAttempt(_: Event) {\n this.dispatchEvent(\n new CustomEvent('end-attempt', {\n bubbles: true,\n composed: true,\n detail: { responseIdentifier: this.responseIdentifier, countAttempt: this.countAttempt === 'true' }\n })\n );\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-end-attempt-interaction': QtiEndAttemptInteraction;\n }\n}\n","import { boxSizing } from '@qti-components/base';\n\nexport default [boxSizing];\n","import { html } from 'lit';\n\nimport { Interaction } from '@qti-components/base';\n\nimport styles from './qti-media-interaction.styles';\n\nimport type { CSSResultGroup } from 'lit';\n/**\n * Media interaction: wraps an embedded media object (audio/video) and tracks play events.\n *\n * @slot prompt - The prompt shown above the media element.\n * @slot - Default slot for the embedded media element.\n */\nexport class QtiMediaInteraction extends Interaction {\n static override styles: CSSResultGroup = styles;\n\n #value: number = null;\n\n override reset() {\n this.#value = null;\n }\n validate(): boolean {\n return true;\n }\n\n get response(): string | null {\n return this.#value ? this.#value.toString() : null;\n }\n\n set response(val: string | null) {\n if (val) {\n const isNumber = !isNaN(parseInt(val?.toString()));\n if (isNumber) {\n this.#value = parseInt(val.toString());\n } else {\n throw new Error(`Value must be a number ${val}`);\n }\n }\n }\n\n static override get properties() {\n return {\n ...Interaction.properties,\n ...{\n step: {\n type: Number,\n attribute: 'step',\n default: 10\n }\n }\n };\n }\n\n override render() {\n return html` <slot name=\"prompt\"></slot>\n <slot></slot>`;\n }\n\n constructor() {\n super();\n }\n\n override connectedCallback() {\n super.connectedCallback();\n // get audio, video of object tag.\n const mediaObject = this.querySelector('audio') || this.querySelector('video') || this.querySelector('object');\n if (mediaObject) {\n // listen to ended event\n mediaObject.addEventListener('ended', () => {\n // set value to 0\n // check if this.value is a number\n this.#value++;\n this.saveResponse(this.value);\n });\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-media-interaction': QtiMediaInteraction;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n /* The box this element already had. See the note in qti-match-interaction.styles.ts. */\n :host {\n display: block;\n }\n `\n];\n","import { LitElement, html } from 'lit';\n\nimport styles from './qti-position-object-interaction.styles';\n\nimport type { CSSResultGroup } from 'lit';\n\n/**\n * Position-object interaction: candidates place draggable objects onto a stage image.\n *\n * @slot - Default slot for the object choices and stage.\n */\nexport class QtiPositionObjectInteraction extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n override render() {\n return html`<slot></slot>`;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n :host {\n display: block;\n }\n ::slotted(img) {\n position: absolute;\n cursor: move;\n user-select: none;\n left: 50%;\n transform: translateX(-50%);\n }\n `\n];\n","import { LitElement, html } from 'lit';\n\nimport styles from './qti-position-object-stage.styles';\n\nimport type { CSSResultGroup, PropertyValueMap } from 'lit';\nexport class QtiPositionObjectStage extends LitElement {\n static override styles: CSSResultGroup = styles;\n\n choiceOrdering: boolean;\n startX: any;\n startY: any;\n dragElement: any;\n\n override render() {\n return html`<slot></slot>`;\n }\n\n constructor() {\n super();\n this.removeMoveListener = this.removeMoveListener.bind(this);\n this.dragElementHandler = this.dragElementHandler.bind(this);\n }\n\n // Define a function to handle the mousemove event on the draggable element\n dragElementHandler(event: MouseEvent): void {\n event.preventDefault();\n\n // Calculate the distance the mouse has moved since the last event\n const deltaX: number = event.clientX - this.startX;\n const deltaY: number = event.clientY - this.startY;\n\n // Update the position of the draggable element\n this.dragElement.style.left = this.dragElement.offsetLeft + deltaX + 'px';\n this.dragElement.style.top = this.dragElement.offsetTop + deltaY + 'px';\n\n // Update the starting position of the mouse\n this.startX = event.clientX;\n this.startY = event.clientY;\n }\n\n override firstUpdated(a: PropertyValueMap<any>): void {\n super.firstUpdated(a);\n\n // Get the draggable and drop zone elements\n this.dragElement = this.querySelector('qti-position-object-interaction>img');\n // const canvasElement = document.getElementById('canvas');\n\n // Initialize variables for the starting position of the draggable element\n this.startX = 0;\n this.startY = 0;\n\n // Add a mousedown event listener to the draggable element\n this.dragElement.addEventListener('mousedown', (event: MouseEvent) => {\n // Save the starting position of the mouse\n this.startX = event.clientX;\n this.startY = event.clientY;\n\n // Add a mousemove event listener to the document\n document.addEventListener('mousemove', this.dragElementHandler, true);\n });\n document.addEventListener('mouseup', this.removeMoveListener);\n }\n\n removeMoveListener() {\n document.removeEventListener('mousemove', this.dragElementHandler, true);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('mousemove', this.dragElementHandler);\n document.removeEventListener('mouseup', this.removeMoveListener);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-position-object-stage': QtiPositionObjectStage;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n :host {\n display: inline-block;\n position: relative;\n }\n `\n];\n","import { html } from 'lit';\n\nimport { Interaction } from '@qti-components/base';\n\nimport styles from './qti-upload-interaction.styles';\n\nimport type { CSSResultGroup } from 'lit';\n/**\n * Upload interaction: candidates attach a file as their response.\n *\n * @slot prompt - The prompt shown above the file input.\n */\nexport class QtiUploadInteraction extends Interaction {\n static override styles: CSSResultGroup = styles;\n\n #file: File | null = null;\n #base64: string | null = null;\n\n override reset() {\n this.#file = null;\n this.#base64 = null;\n this.saveResponse(null);\n }\n\n validate(): boolean {\n return this.#base64 !== null; // Ensure the Base64 string is set\n }\n\n get response(): string | null {\n return this.#base64; // Return the Base64 string\n }\n\n set response(base64: string | null) {\n if (typeof base64 === 'string') {\n this.#base64 = base64;\n this.saveResponse(base64); // Save Base64 string as the response\n } else if (base64 === null) {\n this.reset();\n } else {\n throw new Error('Value must be a Base64-encoded string or null');\n }\n }\n\n static override get properties() {\n return {\n ...Interaction.properties\n };\n }\n\n override render() {\n return html`\n <div>\n <slot name=\"prompt\"></slot>\n <input type=\"file\" @change=\"${this.#onFileChange}\" ?disabled=\"${this.disabled}\" ?readonly=\"${this.readonly}\" />\n </div>\n `;\n }\n\n async #onFileChange(event: Event) {\n const input = event.target as HTMLInputElement;\n if (input.files && input.files.length > 0) {\n this.#file = input.files[0];\n this.#base64 = await this.#convertToBase64(this.#file);\n this.saveResponse(this.#base64); // Save the Base64 string\n this.dispatchEvent(\n new CustomEvent('qti-interaction-response', {\n detail: { response: this.#base64 }\n })\n );\n }\n }\n\n #convertToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file); // Converts to Base64\n });\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-upload-interaction': QtiUploadInteraction;\n }\n}\n","import { css } from 'lit';\n\nimport { boxSizing } from '@qti-components/base';\n\nexport default [\n boxSizing,\n css`\n :host {\n display: block;\n margin: 1em 0;\n }\n input[type='file'] {\n display: block;\n margin-top: 0.5em;\n }\n `\n];\n","import { QtiAssociableHotspot } from './qti-associable-hotspot';\n\nexport const elements = [{ tag: 'qti-associable-hotspot', ctor: QtiAssociableHotspot }] as const;\n\nexport { QtiAssociableHotspot };\n","import { QtiGap } from './qti-gap';\n\nexport const elements = [{ tag: 'qti-gap', ctor: QtiGap }] as const;\n\nexport { QtiGap };\n","import { QtiGapImg } from './qti-gap-img';\n\nexport const elements = [{ tag: 'qti-gap-img', ctor: QtiGapImg }] as const;\n\nexport { QtiGapImg };\n","import { QtiGapText } from './qti-gap-text';\n\nexport const elements = [{ tag: 'qti-gap-text', ctor: QtiGapText }] as const;\n\nexport { QtiGapText };\n","import { QtiHotspotChoice } from './qti-hotspot-choice';\n\nexport const elements = [{ tag: 'qti-hotspot-choice', ctor: QtiHotspotChoice }] as const;\n\nexport { QtiHotspotChoice };\n","import { QtiHottext } from './qti-hottext';\n\nexport const elements = [{ tag: 'qti-hottext', ctor: QtiHottext }] as const;\n\nexport { QtiHottext };\n","import { QtiInlineChoice } from './qti-inline-choice';\n\nexport const elements = [{ tag: 'qti-inline-choice', ctor: QtiInlineChoice }] as const;\n\nexport { QtiInlineChoice };\n","import { QtiPrompt } from './qti-prompt';\n\nexport const elements = [{ tag: 'qti-prompt', ctor: QtiPrompt }] as const;\n\nexport { QtiPrompt };\n","import { QtiSimpleAssociableChoice } from './qti-simple-associable-choice';\n\nexport const elements = [{ tag: 'qti-simple-associable-choice', ctor: QtiSimpleAssociableChoice }] as const;\n\nexport { QtiSimpleAssociableChoice };\n","import { QtiSimpleChoice } from './qti-simple-choice';\n\nexport const elements = [{ tag: 'qti-simple-choice', ctor: QtiSimpleChoice }] as const;\n\nexport { QtiSimpleChoice };\n","import { elements as qtiAssociableHotspotElements } from './elements/qti-associable-hotspot/elements';\nimport { elements as qtiGapElements } from './elements/qti-gap/elements';\nimport { elements as qtiGapImgElements } from './elements/qti-gap-img/elements';\nimport { elements as qtiGapTextElements } from './elements/qti-gap-text/elements';\nimport { elements as qtiHotspotChoiceElements } from './elements/qti-hotspot-choice/elements';\nimport { elements as qtiHottextElements } from './elements/qti-hottext/elements';\nimport { elements as qtiInlineChoiceElements } from './elements/qti-inline-choice/elements';\nimport { elements as qtiPromptElements } from './elements/qti-prompt/elements';\nimport { elements as qtiSimpleAssociableChoiceElements } from './elements/qti-simple-associable-choice/elements';\nimport { elements as qtiSimpleChoiceElements } from './elements/qti-simple-choice/elements';\n\nexport const qtiInteractionCoreElements = [\n ...qtiAssociableHotspotElements,\n ...qtiGapElements,\n ...qtiGapImgElements,\n ...qtiGapTextElements,\n ...qtiHotspotChoiceElements,\n ...qtiHottextElements,\n ...qtiInlineChoiceElements,\n ...qtiPromptElements,\n ...qtiSimpleAssociableChoiceElements,\n ...qtiSimpleChoiceElements\n] as const;\n","import { QtiCustomInteraction } from './qti-custom-interaction';\n\nexport const elements = [{ tag: 'qti-custom-interaction', ctor: QtiCustomInteraction }] as const;\n\nexport { QtiCustomInteraction };\n","import { QtiEndAttemptInteraction } from './qti-end-attempt-interaction';\n\nexport const elements = [{ tag: 'qti-end-attempt-interaction', ctor: QtiEndAttemptInteraction }] as const;\n\nexport { QtiEndAttemptInteraction };\n","import { QtiMediaInteraction } from './qti-media-interaction';\n\nexport const elements = [{ tag: 'qti-media-interaction', ctor: QtiMediaInteraction }] as const;\n\nexport { QtiMediaInteraction };\n","import { QtiPositionObjectInteraction } from './qti-position-object-interaction';\nimport { QtiPositionObjectStage } from './qti-position-object-stage';\n\nexport const elements = [\n { tag: 'qti-position-object-interaction', ctor: QtiPositionObjectInteraction },\n { tag: 'qti-position-object-stage', ctor: QtiPositionObjectStage }\n] as const;\n\nexport { QtiPositionObjectInteraction, QtiPositionObjectStage };\n","import { QtiUploadInteraction } from './qti-upload-interaction';\n\nexport const elements = [{ tag: 'qti-upload-interaction', ctor: QtiUploadInteraction }] as const;\n\nexport { QtiUploadInteraction };\n","import { qtiInteractionCoreElements } from '@qti-components/interactions-core/elements';\nimport { elements as associateInteractionElements } from '@qti-components/associate-interaction/elements';\nimport { elements as choiceInteractionElements } from '@qti-components/choice-interaction/elements';\nimport { elements as customInteractionElements } from '@qti-components/custom-interaction/elements';\nimport { elements as endAttemptInteractionElements } from '@qti-components/end-attempt-interaction/elements';\nimport { elements as extendedTextInteractionElements } from '@qti-components/extended-text-interaction/elements';\nimport { elements as gapMatchInteractionElements } from '@qti-components/gap-match-interaction/elements';\nimport { elements as graphicAssociateInteractionElements } from '@qti-components/graphic-associate-interaction/elements';\nimport { elements as graphicGapMatchInteractionElements } from '@qti-components/graphic-gap-match-interaction/elements';\nimport { elements as graphicOrderInteractionElements } from '@qti-components/graphic-order-interaction/elements';\nimport { elements as hotspotInteractionElements } from '@qti-components/hotspot-interaction/elements';\nimport { elements as hottextInteractionElements } from '@qti-components/hottext-interaction/elements';\nimport { elements as inlineChoiceInteractionElements } from '@qti-components/inline-choice-interaction/elements';\nimport { elements as matchInteractionElements } from '@qti-components/match-interaction/elements';\nimport { elements as mediaInteractionElements } from '@qti-components/media-interaction/elements';\nimport { elements as orderInteractionElements } from '@qti-components/order-interaction/elements';\nimport { elements as portableCustomInteractionElements } from '@qti-components/portable-custom-interaction/elements';\nimport { elements as positionObjectInteractionElements } from '@qti-components/position-object-interaction/elements';\nimport { elements as selectPointInteractionElements } from '@qti-components/select-point-interaction/elements';\nimport { elements as sliderInteractionElements } from '@qti-components/slider-interaction/elements';\nimport { elements as textEntryInteractionElements } from '@qti-components/text-entry-interaction/elements';\nimport { elements as uploadInteractionElements } from '@qti-components/upload-interaction/elements';\n\nexport const qtiInteractionElements = [\n ...qtiInteractionCoreElements,\n ...associateInteractionElements,\n ...choiceInteractionElements,\n ...customInteractionElements,\n ...endAttemptInteractionElements,\n ...extendedTextInteractionElements,\n ...gapMatchInteractionElements,\n ...graphicAssociateInteractionElements,\n ...graphicGapMatchInteractionElements,\n ...graphicOrderInteractionElements,\n ...hotspotInteractionElements,\n ...hottextInteractionElements,\n ...inlineChoiceInteractionElements,\n ...matchInteractionElements,\n ...mediaInteractionElements,\n ...orderInteractionElements,\n ...portableCustomInteractionElements,\n ...positionObjectInteractionElements,\n ...selectPointInteractionElements,\n ...sliderInteractionElements,\n ...textEntryInteractionElements,\n ...uploadInteractionElements\n] as const;\n","import { qtiInteractionElements } from './elements';\n\nfor (const { tag, ctor } of qtiInteractionElements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n","import { elements } from './elements';\n\nfor (const { tag, ctor } of elements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n"],"mappings":"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","names":["html","LitElement","property","state","repeat","consume","css","css","LitElement","html","repeat","__decorate","property","consume","state","LitElement","property","css","css","LitElement","__decorate","property","html","LitElement","property","css","LitElement","html","__decorate","property","html","LitElement","css","css","LitElement","html","html","property","state","css","css","html","iframe","__decorate","property","state","html","LitElement","property","LitElement","html","__decorate","property","html","css","css","html","LitElement","html","css","css","LitElement","html","LitElement","html","css","css","LitElement","html","html","css","css","html","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements","elements"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../qti-base/src/utils/custom-state-set.ts","../../qti-base/src/context/computed-item.context.ts","../../qti-base/src/context/computed.context.ts","../../qti-base/src/context/config.context.ts","../../qti-base/src/context/interaction.context.ts","../../qti-base/src/context/item.context.ts","../../qti-base/src/context/types/item.types.ts","../../qti-base/src/context/qti.context.ts","../../qti-base/src/context/session.context.ts","../../qti-base/src/context/test.context.ts","../../qti-base/src/styles/box-sizing.styles.ts","../../qti-base/src/styles/drop-region.styles.ts","../../qti-base/src/styles/validation-message.styles.ts","../../qti-base/src/abstract/interaction.ts","../../qti-base/src/abstract/qti-variable-declaration.ts","../../qti-base/src/abstract/qti-expression.ts","../../qti-base/src/abstract/qti-condition-expression.ts","../../qti-base/src/utils/utils.ts","../../qti-base/src/abstract/qti-feedback.ts","../../qti-base/src/lib/response.ts","../../qti-base/src/lib/qti-rule-base.ts","../../qti-base/src/utils/scoring-helper.ts","../../qti-base/src/elements.ts","../../qti-base/src/register.ts"],"sourcesContent":["/**\n * Custom-state support shim for browsers this library cannot use natively.\n *\n * Interactions track selection and correct/incorrect marking through\n * `internals.states`, with bare state names (`checked`, `radio`,\n * `correct-response`, …). Two browser profiles cannot service that:\n *\n * - Safari 16.4–17.3 implement `ElementInternals` but not `CustomStateSet`, so\n * `internals.states` is `undefined` and reading it throws — \"undefined is not\n * an object (evaluating 'internals.states.has')\".\n * - Chrome and Edge before the CSS custom-state spec change expose `states` but\n * reject names that do not start with `--`, so `states.add('radio')` throws\n * \"The specified value 'radio' must start with '--'\".\n *\n * On both, picking a choice throws rather than registering. `attachInternals`\n * itself is unguarded throughout the interaction base classes, which puts the\n * hard support floor at Safari 16.4 — inside the range that breaks.\n *\n * The shim replaces `states` with a permissive `Set` and mirrors its contents to\n * a space-separated `data-state` attribute on the host, because these browsers'\n * CSS parsers also drop any selector list containing `:state()`. The theme's\n * built stylesheets pair every `:state(x)` with a `[data-state~='x']` arm (see\n * `tools/postcss/custom-state-fallback.mjs`), so styling survives too.\n *\n * Support is classified by behaviour rather than by browser version, and the\n * shim is not installed at all where `states` works.\n */\n\n/** A permissive `CustomStateSet` that mirrors its contents to `data-state`. */\nexport class CustomStateSetShim extends Set<string> {\n readonly #host: HTMLElement;\n\n constructor(host: HTMLElement) {\n super();\n this.#host = host;\n }\n\n override add(state: string): this {\n super.add(state);\n this.#reflect();\n return this;\n }\n\n override delete(state: string): boolean {\n const deleted = super.delete(state);\n this.#reflect();\n return deleted;\n }\n\n override clear(): void {\n super.clear();\n this.#reflect();\n }\n\n #reflect(): void {\n // A custom element must not gain attributes while it is upgrading, so defer\n // the write until the element is connected.\n if (this.#host.isConnected) this.#write();\n else queueMicrotask(() => this.#write());\n }\n\n #write(): void {\n if (this.size === 0) this.#host.removeAttribute('data-state');\n else this.#host.setAttribute('data-state', Array.from(this).join(' '));\n }\n}\n\nexport type CustomStateSupport = 'missing' | 'legacy' | 'modern';\n\nconst PROBE_TAG = 'custom-state-support-probe';\n\n/**\n * Classify native custom-state support by behaviour:\n *\n * - `missing`: `ElementInternals` carries no `states` at all.\n * - `legacy`: `states` exists but rejects a bare name.\n * - `modern`: `states` exists and accepts a bare name — no shim wanted.\n *\n * `attachInternals` only works on a custom element, so the probe registers a\n * throwaway one. That happens solely when `states` is present, so the `missing`\n * path never defines anything.\n */\nexport function classifyCustomStateSupport(\n attachInternals: (this: HTMLElement) => ElementInternals\n): CustomStateSupport {\n if (!('states' in ElementInternals.prototype)) return 'missing';\n if (typeof customElements === 'undefined') return 'modern';\n\n try {\n if (!customElements.get(PROBE_TAG)) customElements.define(PROBE_TAG, class extends HTMLElement {});\n const states = attachInternals.call(document.createElement(PROBE_TAG)).states;\n if (!states) return 'missing';\n // A bare name throws SyntaxError under the legacy spec and never does under\n // the current one, so classify on the throw alone — not on whether the value\n // sticks, which some environments do not honour on a detached element.\n states.add('probe');\n states.delete('probe');\n return 'modern';\n } catch {\n return 'legacy';\n }\n}\n\nlet installed = false;\n\n/**\n * Patch `HTMLElement.prototype.attachInternals` so every element's `states` is\n * the shim, on the two profiles that need it. Idempotent, and a no-op where\n * native support is usable.\n *\n * Returns the classification that was acted on, which is what the tests assert.\n */\nexport function installCustomStateSetFallback(): CustomStateSupport | 'already-installed' {\n if (installed) return 'already-installed';\n if (typeof HTMLElement === 'undefined' || typeof ElementInternals === 'undefined') return 'modern';\n\n const native = HTMLElement.prototype.attachInternals;\n if (!native) return 'modern';\n\n const support = classifyCustomStateSupport(native);\n if (support === 'modern') return support;\n\n installed = true;\n HTMLElement.prototype.attachInternals = function attachInternals(this: HTMLElement): ElementInternals {\n const internals = native.call(this);\n Object.defineProperty(internals, 'states', {\n configurable: true,\n enumerable: true,\n value: new CustomStateSetShim(this)\n });\n return internals;\n };\n\n return support;\n}\n","import { createContext } from '@lit/context';\n\nimport type { ComputedItemContext } from './types/computed-item.types';\n\nexport const computedItemContext = createContext<Readonly<ComputedItemContext>>(Symbol('computedItemContext'));\n","import { createContext } from '@lit/context';\n\nimport type { ComputedContext } from './types/computed.types';\n\nexport const computedContext = createContext<Readonly<ComputedContext>>(Symbol('computedContext'));\n","import { createContext } from '@lit/context';\n\nexport type ValidationDisplayMode = 'inline' | 'native' | 'both' | 'none';\n\n/**\n * Configuration context for QTI components. Provides runtime options for assessment item and\n * interaction behavior.\n *\n * ── Three ways to set it, in the order you should reach for them ─────────────────────────────\n *\n * 1. **On a provider**, for real delivery. `qti-test` and `qti-item` both provide it, so setting\n * `item.configContext = {…}` configures every interaction inside.\n *\n * 2. **On one interaction, directly** — the development-time route, and the reason\n * `Interaction.configContext` is public:\n *\n * orderInteraction.configContext = { allowReorder: false };\n *\n * or, in a lit-html template, as a property binding — which lands before `connectedCallback`:\n *\n * html`<qti-order-interaction .configContext=${{ allowReorder: false }}>…`\n *\n * An interaction has to work standalone, so in a story or a spec there is usually no provider\n * above it, and then nothing ever overwrites what you set. Where a provider DOES exist it wins on\n * its next emit, because `@consume` writes that same field.\n *\n * A `qti-config-test-provider` element used to exist for scoping config to a subtree. It is gone:\n * it was test-only yet registered itself into every consumer's element registry via an unguarded\n * `@customElement`, which threw whenever two copies of this package ended up in one module graph.\n * Bind the property on each interaction instead, or provide from `qti-item`.\n *\n * There is no merging at any level: @lit/context resolves to the nearest provider and that object\n * replaces the ancestor's wholesale. A deeper provider therefore has to restate anything from above\n * that it still wants.\n *\n * Note what is NOT here. Options an item author chooses per question are attributes on the\n * interaction (`auto-size-dropzones`, `max-associations`, `disable-animations`); options only a\n * developer chooses are mixin factory arguments or method overrides. This context is for what a\n * delivery environment decides across items. `interactionContext` and `dragDropContext` are neither\n * — they publish derived state (what a choice IS, what a drop HOLDS), never configuration.\n */\nexport interface ConfigContext {\n /**\n * Optional category label for info items, used for reporting or display purposes.\n * Example: \"General Information\", \"Instructions\".\n */\n infoItemCategory?: string;\n\n /**\n * If true, calls reportValidity() on interactions after scoring to show validation feedback.\n * Used to trigger UI validation after a scoring event.\n */\n reportValidityAfterScoring?: boolean;\n\n /**\n * Controls how validation feedback is displayed by interactions:\n * - 'inline': render message in #validation-message (default behavior)\n * - 'native': use browser-native reportValidity popup behavior\n * - 'both': show both inline and native feedback\n * - 'none': keep validity state only, without visual feedback\n */\n validationDisplayMode?: ValidationDisplayMode;\n\n /**\n * If true, disables further user actions when an interaction reaches its configured maximum.\n * Applies to both choice-based and drag/drop interactions.\n */\n disableAfterMaxReached?: boolean;\n\n /**\n * If false, chips already placed in a drop target cannot be reordered or moved between targets in\n * drag/drop sortable interactions (order, match, gap-match). Defaults to true. A per-interaction\n * `allowReorder` property overrides this.\n */\n allowReorder?: boolean;\n\n /**\n * If true, disables further selection in choice interactions after the maximum number of choices is reached.\n * @deprecated Legacy alias for choice interactions. Prefer disableAfterMaxReached.\n */\n disableAfterIfMaxChoicesReached?: boolean;\n\n /**\n * Optional prompt text to display in inline choice interactions when no option is selected.\n * Example: \"Select an answer...\"\n */\n inlineChoicePrompt?: string;\n\n /**\n * If true, the inline choice interaction automatically measures the widest option and sizes the\n * trigger button to match. Defaults to false.\n * When a `qti-input-width-*` class is present on the interaction, that class width always takes\n * precedence and autosizing is skipped regardless of this setting.\n */\n inlineChoiceAutosize?: boolean;\n}\n\nexport const configContext = createContext<Readonly<ConfigContext>>(Symbol('configContext'));\n","import { createContext } from '@lit/context';\n\n/**\n * What a choice element should render and behave as. The same element — `qti-simple-choice`,\n * `qti-hottext` — is a radio in one interaction and a checkbox in another. It cannot know this\n * by itself.\n *\n * Note \"drag\" is deliberately *not* a choiceRole. In `qti-match-interaction` the same element\n * type is a drag in one match-set and a drop target in the other, so draggability is positional,\n * not a property of the interaction. It is derived from `draggablesSelector` instead. It is also\n * not a valid ARIA role, so it may only ever be a custom state.\n */\nexport type ChoiceRole = 'radio' | 'checkbox';\n\n/**\n * State an interaction publishes to the choice elements inside it.\n *\n * Provided by the `qti-*-interaction`, never by `qti-assessment-item`: interactions must work\n * standalone — in a plain form, in a story, in a vendor's app — with no QTI ancestor. Consumers\n * must therefore tolerate its absence and fall back to a sensible default:\n *\n * const role = this.interactionContext?.choiceRole ?? null;\n */\nexport interface InteractionContext {\n /** `null` when the interaction assigns no particular role to its choices. */\n choiceRole: ChoiceRole | null;\n\n /**\n * The selector this interaction uses to recognise its draggable chips. An element tests\n * itself with `this.matches(draggablesSelector)` and takes `:state(chip)` if it matches.\n *\n * Published rather than pushed because draggability can be positional: match-interaction's\n * selector distinguishes the source match-set from the target one, so two elements of the\n * same tag get different answers.\n */\n draggablesSelector: string | null;\n}\n\nexport const interactionContext = createContext<Readonly<InteractionContext>>(Symbol('interactionContext'));\n","import { createContext } from '@lit/context';\n\nimport type { ItemContext } from './types/item.types';\n\nexport const itemContext = createContext<ItemContext>(Symbol('item'));\n","import type { VariableDeclaration } from '../../lib/variables';\n\nexport interface ItemContext {\n identifier?: string;\n href?: string;\n variables?: ReadonlyArray<VariableDeclaration<string | string[] | null>>;\n /**\n * Optional per-interaction opaque state, keyed by responseIdentifier.\n * Used for interactions that support state save/restore (e.g. PCI).\n */\n state?: Record<string, string | null>;\n}\n\nexport const itemContextVariables = [\n {\n identifier: 'completionStatus',\n cardinality: 'single',\n baseType: 'string',\n value: 'unknown',\n type: 'outcome'\n },\n {\n identifier: 'numAttempts',\n cardinality: 'single',\n baseType: 'integer',\n value: '0',\n type: 'response'\n }\n] as VariableDeclaration<string | string[]>[];\n","import { createContext } from '@lit/context';\n\n/**\n * A validated deterministic shuffle seed.\n *\n * Branded so that only values verified through {@link isSeed} (or constructed via\n * {@link asSeed}) can be assigned where a seed is expected. This prevents arbitrary\n * strings from silently being used as a seed.\n *\n * A usable seed is a non-empty string of letters, digits and hyphens (e.g. a GUID\n * \"N\" format like `8f14e45fceea167a5a36dedd4bea2543`, or a readable label like\n * `delivery-2026-06-05`). Whitespace and other characters are rejected.\n */\nexport type Seed = string & { readonly __seedBrand: 'Seed' };\n\n/** Format a value must match to be usable as a {@link Seed}. */\nconst SEED_PATTERN = /^[A-Za-z0-9-]+$/;\n\n/**\n * Runtime type guard that narrows an unknown value to a {@link Seed}.\n * Use this at boundaries (e.g. values coming from XML, a host application or a\n * backend) before treating a string as a seed.\n */\nexport const isSeed = (value: unknown): value is Seed => typeof value === 'string' && SEED_PATTERN.test(value);\n\n/**\n * Validates and brands a value as a {@link Seed}, returning `undefined` when the\n * value is missing or not in a usable seed format.\n */\nexport const asSeed = (value: unknown): Seed | undefined => (isSeed(value) ? value : undefined);\n\nexport type QtiContextType = {\n testIdentifier: string;\n candidateIdentifier: string;\n environmentIdentifier: string;\n /**\n * Optional deterministic seed for shuffling.\n *\n * When set, it is used to reproduce a stable shuffle order across reloads/restarts:\n * - test ordering in `test-container` (`<qti-ordering shuffle=\"true\">`),\n * - seeded item interaction shuffling in `item-container` and during test navigation.\n *\n * Typically generated once per session by the host/backend and passed in via\n * `QTI_CONTEXT`. When omitted, each item falls back to its own URI-derived seed.\n */\n seed?: Seed;\n [key: string]: string | string[]; // Allow for additional context variables\n};\n\nexport interface QtiContext {\n QTI_CONTEXT: QtiContextType;\n}\n\nexport const qtiContext = createContext<Readonly<QtiContext>>(Symbol('qtiContext'));\n","import { createContext } from '@lit/context';\n\nexport type View = 'author' | 'candidate' | 'proctor' | 'scorer' | 'testConstructor' | 'tutor' | '';\n\nexport interface SessionContext {\n navPartId?: string | null;\n navSectionId?: string | null;\n navItemRefId?: string | null;\n navItemLoading?: boolean;\n navTestLoading?: boolean;\n view?: View;\n}\n\nexport const INITIAL_SESSION_CONTEXT: Readonly<SessionContext> = { view: 'candidate' };\n\nexport const sessionContext = createContext<Readonly<SessionContext>>(Symbol('testContext'));\n","import { createContext } from '@lit/context';\n\nimport type { ItemContext } from './types/item.types';\nimport type { VariableDeclaration } from '../lib/variables';\n\nexport interface TestContext {\n items: (ItemContext & { category?: string })[];\n testOutcomeVariables?: VariableDeclaration<string | string[] | null>[];\n}\n\nexport const INITIAL_TEST_CONTEXT: Readonly<TestContext> = { items: [], testOutcomeVariables: [] };\n\nexport const testContext = createContext<Readonly<TestContext>>(Symbol('testContext'));\n","import { css } from 'lit';\n\n/**\n * The border-box reset, for shadow trees.\n *\n * `modern-normalize` applies `*, ::before, ::after { box-sizing: border-box }` to the document,\n * but a universal selector never crosses a shadow boundary: every shadow root starts over at\n * the UA default, `content-box`. So each component has to opt in, and until now 15 of them did\n * so ad hoc — one of them with `content-box`, one with `!important`.\n *\n * Why this matters beyond tidiness: under `content-box`, padding and border are *size*. A rule\n * that only means to repaint a chip — `:state(dragging) { border: none }` — silently shrinks it\n * by two pixels per axis, the drag bank rewraps, and a drop target slides out from under the\n * user's pointer mid-drag. Border-box is what makes \"a state may repaint but never re-lay-out\"\n * a rule the CSS can actually keep.\n *\n * `:host` is set explicitly and descendants inherit, so a component that genuinely needs\n * `content-box` for a subtree (an image map, say) can opt out at one node and have it hold for\n * everything below it.\n */\nexport const boxSizing = css`\n :host {\n box-sizing: border-box;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: inherit;\n }\n`;\n","import { css } from 'lit';\n\n/**\n * The `drop` region of every drop target.\n *\n * One rule: **a drop container hosts a chip, it never sizes one.** No `flex: 1`, no stretch, no\n * centring. The chip's box is decided by the chip — in the drag bank, mid-flight as a clone, and\n * once dropped — and a container that centres or stretches it makes the drop the one place where\n * that stops being true. That is felt as the chip jumping the instant it lands.\n *\n * `flex: 0 1 auto` on the children says \"intrinsic size, no growing, shrink if you must\".\n * `align-items: flex-start` stops the cross axis stretching them, which is the flex default and\n * the reason a chip in a tall dropzone used to grow to fill it.\n *\n * The shrink half used to be 0 as well, on the reading that a drop must not resize a chip. It does\n * not say that. `flex-shrink: 0` does not preserve the chip's size, it preserves the chip's\n * UNCONSTRAINED max-content size — and those are the same number only while the bank is wide enough\n * to give the chip its full width. Once the bank is narrower, the bank chip (`flex: 0 1 auto`, like\n * any flex item) shrinks and wraps, the placed chip does not, and the two disagree.\n *\n * Measured on the order fixture, bank vs placed: 209x36 / 209x36 at a 480px interaction, but\n * 204x55 / 209x36 at 440px and 154x55 / 209x36 at 340px — the placed chip a fixed 209px wide,\n * overflowing a drop that had correctly reserved 156px for it. It reached CI as a font difference:\n * the same label measures ~227px under the Linux fonts, which puts 480px on the wrong side of the\n * boundary too.\n *\n * Shrinking cannot make a placed chip smaller than the reservation, because the reservation IS the\n * measured chip (`--qti-dropzone-min-*`, applied to this region's content box). So the floor a\n * shrink stops at is the chip's own size, which is the rule above, not an exception to it.\n * `flex-grow: 0` is what actually prevents the stretch this block cares about, and it is untouched.\n *\n * A container that wants a *minimum* size still declares one (see `--qti-dropzone-min-*`). That\n * sizes the container, never its contents.\n *\n * Verified by drag-drop.invariance.spec.ts: \"a chip is the same chip wherever it lives\" — including\n * the narrow-bank order fixture, which is there because the wide one passes either way.\n */\nexport const dropRegion = css`\n [part~='drop'] {\n /*\n * The one deliberate opt-out from the border-box reset.\n *\n * --qti-dropzone-min-* is the border-box of the largest chip, and what has to hold that chip is\n * this region's *content* area. Under border-box a theme's dashed drop border is subtracted\n * from the chip's own size, the content comes up short, and the drop grows the moment a chip\n * lands in it. Order's drop did exactly that: 64px empty, 66px full, for a 1px border.\n */\n box-sizing: content-box;\n\n /*\n * No padding, and no token for one.\n *\n * A drop reserves --qti-dropzone-min-*, which is the chip's BORDER-box, as this region's CONTENT\n * area — so the chip already fits exactly, with nothing to spare and nothing squeezed. An inset\n * on top would only make the drop bigger than the thing it holds.\n *\n * There was a 1px one, to make the drop read as a frame a hair outside the chip. It never painted:\n * an EMPTY slot has nothing inside the inset to separate from, and a FILLED one hides its edge\n * (DROP-SIZING.md §4), so both states spent 2px on an invisible ring. The one drop that genuinely\n * wants breathing room — match's category card — declares padding on its own rule, which a\n * theme reaches with ::part(drop). A token in between bought nothing.\n */\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: flex-start;\n /* No gap either: 0 is the flex initial value, so the declaration only existed to host a token.\n A drop that wants space between chips sets gap on its own rule. */\n /* Containing block for anything a theme draws over the drop. Was 'position: relative' in the\n theme's 'drop' mixin, which put a document stylesheet in charge of a shadow node's position. */\n position: relative;\n }\n\n [part~='drop'] > * {\n flex: 0 1 auto;\n align-self: flex-start;\n }\n`;\n","import { css } from 'lit';\n\n/**\n * The `#validation-message` region every interaction renders, hidden until there is a message.\n *\n * `Interaction` owns showing and hiding it: `reportValidity` sets\n * `display: block !important` inline when `_internals.validationMessage` is non-empty, and clears the\n * text and sets `display: none` inline again when it is not (see interaction.ts). An inline\n * `!important` beats this rule, so the JS still wins whenever it speaks.\n *\n * What it did not own was the *initial* state. Before first validation the div has no inline style,\n * so it needs a stylesheet to start hidden — otherwise it paints as an empty box with the theme's\n * warning border and padding. That hide used to be a `display: none` inside the theme's\n * `validation-message` mixin, which made a document stylesheet responsible for a shadow node's box.\n * Two components had already noticed and worked around it with `style=\"display:none\"` in their\n * template; the other five relied on the theme.\n *\n * The theme still paints the message — colour, border, padding, radius — via `::part(message)`.\n */\nexport const validationMessage = css`\n [part~='message'] {\n display: none;\n }\n`;\n","import { consume, provide } from '@lit/context';\nimport { LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { configContext } from '../context/config.context';\nimport { interactionContext } from '../context/interaction.context';\nimport { itemContext } from '../context/item.context';\n\nimport type { PropertyValues } from 'lit';\nimport type { InteractionContext } from '../context/interaction.context';\nimport type { ConfigContext, ValidationDisplayMode } from '../context/config.context';\nimport type { ItemContext } from '../context/types/item.types';\nimport type { ValidatableInteraction } from '../lib/interaction.interface';\nimport type { ResponseVariable } from '../lib/variables';\n\n/**\n * Shared QTI interaction base. Formative correction behavior is supplied by the\n * `@qti-components/corrections` package.\n */\nexport abstract class Interaction extends LitElement implements ValidatableInteraction {\n @consume({ context: itemContext, subscribe: true })\n private _context: ItemContext;\n\n /**\n * Delivery configuration, from the nearest provider — `qti-test` or `qti-item`.\n *\n * **Public so it can be assigned directly, which is the development-time route.** An interaction\n * has to work standalone, and in a story or a spec there is usually no provider above it — so\n * setting the field is all that is needed:\n *\n * orderInteraction.configContext = { allowReorder: false, validationDisplayMode: 'none' };\n *\n * With no provider, nothing ever overwrites it. That is the whole contract, and its limit: where a\n * provider DOES exist it re-emits on its next update and wins, because `@consume` writes this same\n * field. There is no merging — set the value on the provider in that case.\n *\n * In a lit-html template, bind it as a property rather than assigning after the fact:\n *\n * html`<qti-order-interaction .configContext=${{ allowReorder: false }}>…`\n *\n * The binding is committed on the detached template clone, before the fragment is inserted, so it\n * is in place by `connectedCallback` — which matters for anything that reads config on connect.\n *\n * It was `protected`, which fooled nobody: every caller reached it anyway through an\n * `as any` / `as { configContext?: … }` cast. Public says what was already true and removes the\n * casts, rather than pretending at an encapsulation the type system was the only thing enforcing.\n */\n @consume({ context: configContext, subscribe: true })\n public configContext: ConfigContext;\n\n #didLogDisableAfterIfMaxChoicesReachedDeprecation = false;\n\n /*\n * Published to the choice elements inside this interaction — their role, and how to tell\n * whether they are draggable. Provided here on the base rather than in a mixin so that\n * ChoicesMixin and the drag-drop mixins can each contribute without two providers of the same\n * context competing on one element.\n *\n * Reassign, never mutate: an in-place change does not notify consumers.\n */\n @provide({ context: interactionContext })\n protected _interactionContext: Readonly<InteractionContext> = { choiceRole: null, draggablesSelector: null };\n\n static formAssociated = true;\n protected _internals: ElementInternals;\n\n get internals(): ElementInternals {\n return this._internals;\n }\n\n @property({ type: String, attribute: 'response-identifier' }) responseIdentifier: string;\n\n @property({ reflect: true, type: Boolean }) disabled = false;\n\n @property({ reflect: true, type: Boolean }) readonly = false;\n\n @property({ type: String }) name;\n\n /** Extension point used by wrappers that should not register as candidate inputs. */\n protected get registersWithItem(): boolean {\n return true;\n }\n\n get isInline(): boolean {\n return false;\n }\n\n get responseVariable(): ResponseVariable | undefined {\n if (!this._context?.variables) {\n return undefined;\n }\n const responseVariables = this._context.variables.filter(v => v.type === 'response') as ResponseVariable[];\n const responseIdentifier = this.getAttribute('response-identifier');\n return responseVariables.find(v => v.identifier === responseIdentifier);\n }\n\n abstract validate(): boolean;\n\n get value(): string | null {\n return JSON.stringify(this.response);\n }\n\n set value(val: string | null) {\n this.response = val ? JSON.parse(val) : null;\n }\n\n abstract get response(): string | string[] | null;\n abstract set response(val: string | string[] | null);\n\n public reportValidity(): boolean {\n const isValid = this._internals.validity.valid;\n const mode = this.validationDisplayMode;\n\n if (mode === 'native' || mode === 'both') {\n this._internals.reportValidity();\n }\n\n if (mode === 'inline' || mode === 'both') {\n this.updateInlineValidationMessage();\n } else {\n this.clearInlineValidationMessage();\n }\n\n if (mode === 'none') {\n this.clearInlineValidationMessage();\n }\n\n return isValid;\n }\n\n protected get validationDisplayMode(): ValidationDisplayMode {\n return this.configContext?.validationDisplayMode ?? 'inline';\n }\n\n protected resolveAllowReorder(options?: { defaultWhenUnset?: boolean }): boolean {\n const defaultWhenUnset = options?.defaultWhenUnset ?? true;\n const config = this.configContext;\n if (!config) {\n return defaultWhenUnset;\n }\n if (config.allowReorder !== undefined) {\n return config.allowReorder;\n }\n return defaultWhenUnset;\n }\n\n protected resolveDisableAfterMaxReached(options?: { defaultWhenUnset?: boolean }): boolean {\n const defaultWhenUnset = options?.defaultWhenUnset ?? false;\n const config = this.configContext;\n\n if (!config) {\n return defaultWhenUnset;\n }\n\n if (config.disableAfterMaxReached !== undefined) {\n return config.disableAfterMaxReached;\n }\n\n if (config.disableAfterIfMaxChoicesReached !== undefined) {\n if (!this.#didLogDisableAfterIfMaxChoicesReachedDeprecation) {\n this.#didLogDisableAfterIfMaxChoicesReachedDeprecation = true;\n console.log(\n '[QTI Config] `disableAfterIfMaxChoicesReached` is deprecated. Use `disableAfterMaxReached` instead.'\n );\n }\n return config.disableAfterIfMaxChoicesReached;\n }\n\n return defaultWhenUnset;\n }\n\n protected setInteractionValidity(\n isValid: boolean,\n validityMessage = '',\n anchor?: HTMLElement | null,\n options?: { suppressInline?: boolean }\n ): void {\n const validityAnchor = anchor ?? this;\n this._internals.setValidity(isValid ? {} : { customError: true }, validityMessage, validityAnchor);\n\n if (\n options?.suppressInline !== true &&\n (this.validationDisplayMode === 'inline' || this.validationDisplayMode === 'both')\n ) {\n this.updateInlineValidationMessage();\n }\n }\n\n protected updateInlineValidationMessage(): void {\n const validationMessageElement = this.getValidationMessageElement();\n if (!validationMessageElement) {\n return;\n }\n\n if (!this._internals.validity.valid) {\n validationMessageElement.textContent = this._internals.validationMessage;\n validationMessageElement.style.setProperty('display', 'block', 'important');\n return;\n }\n\n validationMessageElement.textContent = '';\n validationMessageElement.style.display = 'none';\n }\n\n protected clearInlineValidationMessage(): void {\n const validationMessageElement = this.getValidationMessageElement();\n if (!validationMessageElement) {\n return;\n }\n\n validationMessageElement.textContent = '';\n validationMessageElement.style.display = 'none';\n }\n\n protected getValidationMessageElement(): HTMLElement | null {\n return this.shadowRoot?.querySelector('#validation-message') as HTMLElement | null;\n }\n\n public reset(): void {\n this.response = null;\n }\n\n public formResetCallback(): void {\n this.reset();\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n\n if (!this.registersWithItem) {\n return;\n }\n\n this.dispatchEvent(\n new CustomEvent('qti-register-interaction', {\n bubbles: true,\n composed: true,\n cancelable: false,\n detail: {\n interactionElement: this,\n responseIdentifier: this.responseIdentifier\n }\n })\n );\n }\n\n public saveResponse(value: string | string[], state?: string | null): void {\n this.dispatchEvent(\n new CustomEvent('qti-interaction-response', {\n bubbles: true,\n composed: true,\n cancelable: false,\n detail: {\n responseIdentifier: this.responseIdentifier,\n response: Array.isArray(value) ? [...value] : value,\n ...(state !== undefined ? { state } : {})\n }\n })\n );\n }\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n /**\n * Optional lifecycle bridge for interaction subclasses that do not need changed-property data.\n *\n * The parameter is `PropertyValues`, matching LitElement, and NOT `PropertyValues<this>`.\n * The polymorphic `this` narrowed the parameter per subclass, which made every interaction\n * class structurally incompatible with `LitElement` — so `Constructor<LitElement>`, the\n * standard constraint for a Lit mixin, rejected all of them and consumers could not wrap an\n * interaction in a mixin without casting. `this` buys nothing in a parameter position and\n * costs contravariant compatibility with the base class.\n *\n * Still optional, so subclasses that ignore the argument can override with `firstUpdated()`.\n */\n protected override firstUpdated(_changedProperties?: PropertyValues): void {}\n}\n","import { html, LitElement } from 'lit';\n\nimport type { Cardinality } from '../lib/expression-result';\n\nexport abstract class QtiVariableDeclaration extends LitElement {\n override render() {\n return html`<slot></slot>`;\n }\n\n protected defaultValues(cardinality: Cardinality) {\n const htmlValues = Array.from(this.querySelectorAll('qti-default-value > qti-value'));\n\n if (htmlValues.length === 0) {\n return null;\n }\n\n const defaultValues = htmlValues.map(n => n.innerHTML.trim());\n if (defaultValues.length > 1 || cardinality === 'multiple' || cardinality === 'ordered') {\n return defaultValues;\n }\n return defaultValues[0];\n }\n}\n","import { consume } from '@lit/context';\nimport { css, html, LitElement } from 'lit';\nimport { state } from 'lit/decorators.js';\n\nimport { itemContext } from '../context/item.context';\nimport { qtiContext } from '../context/qti.context';\nimport { testContext } from '../context/test.context';\n\nimport type { ItemContext } from '../context/types/item.types';\nimport type { QtiContext, QtiContextType } from '../context/qti.context';\nimport type { ResponseVariable, VariableDeclaration } from '../lib/variables';\nimport type { TestContext } from '../context/test.context';\n\nexport interface QtiExpressionBase<T> {\n // get assessmentItem(): QtiAssessmentItem;\n\n // getVariables(): VariableDeclaration<number | string | (number | string)[] | null>[];\n calculate(): Readonly<T>;\n}\n\nexport abstract class QtiExpression<T> extends LitElement implements QtiExpressionBase<T> {\n @state()\n protected result: any;\n\n /*\n * Written here rather than imported from a .css file, and that is a packaging constraint rather\n * than a style preference.\n *\n * The rule used to live in qti-expression.css, imported with Vite's inline-stylesheet query so\n * DevTools could show source-file provenance. That query is a VITE specifier, and tsc copies it\n * verbatim into dist — so the published package shipped an import only a Vite-based consumer\n * could resolve. Every other consumer broke on it: plain Node, tsx, any non-Vite bundler. It was\n * the single such specifier reachable from this package, and it took down QTI-Editor's schema\n * check, which loads the components under tsx to build the real ProseMirror schema\n * (ERR_UNKNOWN_FILE_EXTENSION on a file that has nothing to do with schemas).\n *\n * A `build:assets` step used to copy the .css into dist beside it. That went too — it existed\n * only to give the unresolvable import something to point at.\n *\n * Two lines of CSS are not worth a dist that only one bundler can consume. If this ever grows\n * into a real stylesheet, give it a `.styles.ts` exporting a `css` template — the house pattern\n * everywhere else in this repo — rather than reintroducing a bundler-specific import.\n *\n * The element renders a debug <pre> of its computed result plus a <slot>; hiding the slot is all\n * the styling it has ever had.\n */\n static override styles = css`\n slot {\n display: none;\n }\n `;\n\n override render() {\n return html`<pre>${JSON.stringify(this.result, null, 2)}</pre>\n <slot></slot>`;\n }\n\n public calculate(): Readonly<T> {\n this.result = this.getResult();\n return this.result;\n }\n\n protected getResult(): Readonly<T> {\n throw new Error('Not implemented');\n }\n\n @consume({ context: itemContext, subscribe: true })\n @state()\n protected context?: ItemContext;\n\n @consume({ context: qtiContext, subscribe: true })\n @state()\n protected qtiContext?: QtiContext;\n\n @consume({ context: testContext, subscribe: true })\n @state()\n protected _testContext?: TestContext;\n\n /**\n * Resolve a declared variable from the closest available scope: item-level\n * first, then the test-level outcome variables. So an expression used in an\n * assessmentTest's outcome processing can reference a test-level outcome\n * (e.g. a total set earlier in the same run) — which the QTI variable\n * expression is specified to do. Returns null when unresolved rather than\n * throwing, so callers degrade gracefully.\n */\n protected resolveVariable(identifier: string): VariableDeclaration<string | string[] | null> | null {\n return (\n this.context?.variables.find(v => v.identifier === identifier) ??\n this._testContext?.testOutcomeVariables?.find(v => v.identifier === identifier) ??\n null\n );\n }\n\n getVariables = (): (ResponseVariable | VariableDeclaration<QtiContextType>)[] =>\n // FIXME: if this itself is multiple, this will never enter the qti-multiple switch\n // See this example here: https://github.com/1EdTech/qti-examples/blob/master/qtiv3-examples/packaging/items/Example05-feedbackBlock-adaptive.xml\n\n Array.from(this.children)\n .map((e: Element) => {\n console.debug('getVariables', e.tagName.toLowerCase());\n switch (e.tagName.toLowerCase()) {\n case 'qti-base-value': {\n return {\n baseType: e.getAttribute('base-type'),\n value: e.textContent.trim(),\n cardinality: 'single'\n } as ResponseVariable;\n }\n case 'qti-variable': {\n const identifier = e.getAttribute('identifier') || '';\n\n // Special handling for QTI_CONTEXT\n if (identifier === 'QTI_CONTEXT') {\n if (!this.qtiContext?.QTI_CONTEXT) {\n console.warn('QTI_CONTEXT not available');\n return {\n identifier: 'QTI_CONTEXT',\n baseType: 'record',\n value: this.qtiContext.QTI_CONTEXT,\n cardinality: 'record',\n type: 'context'\n } as VariableDeclaration<QtiContextType>;\n }\n return {\n identifier: 'QTI_CONTEXT',\n baseType: 'record',\n value: this.qtiContext.QTI_CONTEXT,\n cardinality: 'record',\n type: 'context'\n } as VariableDeclaration<QtiContextType>;\n }\n\n return this.resolveVariable(identifier);\n }\n case 'qti-multiple': {\n const multiple = e as QtiExpression<ResponseVariable[]>;\n\n const values = multiple.getResult();\n console.debug('values', values);\n if (values?.length > 0) {\n return {\n identifier: '',\n baseType: values[0].baseType,\n value: values.map(v => v.value),\n cardinality: 'multiple',\n type: 'response'\n } as ResponseVariable;\n }\n return null;\n }\n case 'qti-ordered': {\n const multiple = e as QtiExpression<ResponseVariable[]>;\n const values = multiple.getResult();\n if (values?.length > 0) {\n return {\n identifier: '',\n baseType: values[0].baseType,\n value: values.map(v => v.value),\n cardinality: 'ordered',\n type: 'response'\n } as ResponseVariable;\n }\n return null;\n }\n case 'qti-repeat': {\n const repeat = e as QtiExpression<ResponseVariable[]>;\n const values = repeat.getResult();\n if (values?.length > 0) {\n return values;\n }\n return null;\n }\n case 'qti-correct': {\n const identifier = e.getAttribute('identifier') || '';\n const responseVariable: ResponseVariable =\n this.context?.variables?.find(v => v.identifier === identifier) || null;\n return {\n baseType: responseVariable.baseType,\n value: responseVariable.correctResponse,\n cardinality: responseVariable.cardinality\n } as ResponseVariable;\n }\n default: {\n // added for use of qti-equal-rounded\n try {\n const expression = e as QtiExpression<number>;\n const value = expression.getResult();\n return {\n baseType: 'integer',\n value: value?.toString() || null,\n cardinality: 'single'\n } as ResponseVariable;\n } catch (error) {\n console.warn('default not sufficient');\n }\n return null;\n }\n }\n })\n .flatMap(v => (Array.isArray(v) ? v : [v]))\n .filter(v => v !== null);\n}\n","import { QtiExpression } from './qti-expression';\n\nexport abstract class QtiConditionExpression extends QtiExpression<boolean> {\n public override calculate(): Readonly<boolean> {\n this.result = this.getResult();\n return this.result;\n }\n\n public override getResult(): Readonly<boolean> {\n throw new Error('Not implemented');\n }\n}\n","export const decimalSeparator = () => {\n return new Intl.NumberFormat().format(0.1).replace(/\\d/g, '');\n};\n\nexport const convertNumberToUniversalFormat = (number: number | string) => {\n // check if type is string\n if (typeof number === 'string') {\n return number;\n }\n const dSep = decimalSeparator();\n if (dSep === '.') {\n return number.toLocaleString();\n } else {\n return number.toString().replace('.', '').replace(dSep, '.');\n }\n};\n\nexport function IsNullOrUndefined(value: unknown) {\n return value === null || value === undefined;\n}\n\nexport function removeDoubleSlashes(str: string) {\n const singleForwardSlashes = str\n .replace(/([^:]\\/)\\/+/g, '$1')\n .replace(/\\/\\//g, '/')\n .replace('http:/', 'http://')\n .replace('https:/', 'https://');\n return singleForwardSlashes;\n}\n","import { consume } from '@lit/context';\nimport { LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\n\nimport { computedContext } from '../context/computed.context';\nimport { itemContext } from '../context/item.context';\nimport { IsNullOrUndefined } from '../utils/utils';\n\nimport type { ComputedContext } from '../context/types/computed.types';\nimport type { ItemContext } from '../context/types/item.types';\n\nexport abstract class QtiFeedback extends LitElement {\n @property({ type: String, attribute: 'show-hide' })\n protected showHide: 'show' | 'hide' = 'show';\n\n @property({ type: String, attribute: 'outcome-identifier' })\n public outcomeIdentifier: string;\n\n @property({ type: String })\n protected identifier: string;\n\n @property({ type: String, attribute: false })\n public showStatus: string;\n\n @consume({ context: itemContext, subscribe: true })\n @state()\n private _context?: ItemContext;\n\n @consume({ context: computedContext, subscribe: true })\n @state()\n private _computedContext?: ComputedContext;\n\n public override connectedCallback() {\n super.connectedCallback();\n this.dispatchEvent(\n new CustomEvent<QtiFeedback>('qti-register-feedback', {\n bubbles: true,\n composed: true,\n detail: this\n })\n );\n }\n\n public checkShowFeedback(outcomeIdentifier: string) {\n const outcomeVariable = this._context.variables.find(v => v.identifier === outcomeIdentifier) || null;\n if (this.outcomeIdentifier !== outcomeIdentifier || !outcomeVariable) return;\n let isFound = false;\n if (Array.isArray(outcomeVariable.value)) {\n isFound = outcomeVariable.value.includes(this.identifier);\n } else {\n isFound =\n (!IsNullOrUndefined(this.identifier) &&\n !IsNullOrUndefined(outcomeVariable?.value) &&\n this.identifier === outcomeVariable.value) ||\n false;\n }\n\n this.#showFeedback(isFound);\n }\n\n #showFeedback(value: boolean) {\n if (!this.#sessionControlAllowsFeedback()) {\n this.showStatus = 'off';\n return;\n }\n this.showStatus = (value && this.showHide === 'show') || (!value && this.showHide === 'hide') ? 'on' : 'off';\n }\n\n /**\n * The QTI `show-feedback` constraint governs exactly one state: after the end of\n * the last attempt. Up to that point the spec requires any applicable feedback to\n * be shown — \"a value of max-attempts greater than 1, by definition, indicates\n * that any applicable feedback must be shown\" — and only \"once the maximum number\n * of allowed attempts have been used (or for adaptive items, completionStatus has\n * been set to completed)\" does `show-feedback` decide.\n *\n * This only ever forces feedback off, so `show-feedback` being true settles it:\n * there is no state in which the constraint hides feedback. It defaults to\n * false, and an absent value suppresses once the attempts are gone.\n *\n * That leaves one question — is the item out of attempts? — and the two item\n * kinds answer it from different variables, so each reads only its own.\n */\n #sessionControlAllowsFeedback(): boolean {\n if (!this._computedContext) return true;\n const activeItem = this._computedContext.testParts\n ?.find(tp => tp.active)\n ?.sections.flatMap(s => s.items)\n .find(i => i.active);\n if (!activeItem || activeItem.showFeedback) return true;\n\n // Adaptive items ignore max-attempts: \"the number of attempts is limited by\n // the value of the completionStatus built-in outcome variable\".\n if (activeItem.adaptive) return activeItem.completionStatus !== 'completed';\n\n // `max-attempts=\"0\"` is \"no limit\", so the last attempt never arrives.\n const maxAttempts = activeItem.maxAttempts ?? 1;\n if (maxAttempts <= 0) return true;\n\n const numAttempts = Number(this._context?.variables?.find(v => v.identifier === 'numAttempts')?.value) || 0;\n return numAttempts < maxAttempts;\n }\n}\n","/**\n * Canonical `response=\"...\"` / `correct-response=\"...\"` attribute codec.\n *\n * Authors put a single string on an interaction element. This module is the\n * single source of truth for how that string parses into the runtime's\n * internal value AND how an editor serializes the internal value back to the\n * attribute. Both `@qti-components/*` interactions and `@citolab/prose-qti`\n * (the editor) import from here — no per-codebase parsers, no drift.\n *\n * The two attributes share the same grammar; the codec is agnostic about\n * which of them is being parsed.\n *\n * ---\n *\n * Format reference (per interaction):\n *\n * | Interaction | base-type | cardinality | attribute value |\n * |----------------------|---------------|----------------------|---------------------------|\n * | choice | identifier | single / multiple | \"A\" / \"A,B,C\" |\n * | inline-choice | identifier | single | \"Y\" |\n * | hottext | identifier | single / multiple | \"h1\" / \"h1,h2\" |\n * | hotspot | identifier | single / multiple | \"spot1\" / \"spot1,spot2\" |\n * | order | identifier | ordered | \"a,b,c\" (order matters) |\n * | graphic-order | identifier | ordered | \"spot1,spot2,spot3\" |\n * | match | directedPair | multiple | \"src1 tgt1,src2 tgt2\" |\n * | associate | directedPair | multiple | \"A B,C D\" |\n * | gap-match | directedPair | multiple | \"gtext1 gap1,...\" |\n * | graphic-associate | directedPair | multiple | \"spot1 spot2,...\" |\n * | graphic-gap-match | directedPair | multiple | \"gimg1 spot1,...\" |\n * | select-point | point | single / multiple | \"100 150\" / \"100 150,…\" |\n * | slider | integer | single | \"50\" |\n * | text-entry | string | single | \"paris\" |\n *\n * Rules:\n * - Comma `,` separates VALUES (different identifiers / pairs / points).\n * - Space ` ` separates PARTS within one value (pair members or point coords).\n * - Each value is trimmed on parse.\n * - No escape mechanism. Identifiers that contain commas cannot round-trip.\n */\n\n// ─── parsed shape ────────────────────────────────────────────────────────────\n\n/** Canonical parsed value of a `response` / `correct-response` attribute. */\nexport type ResponseValue = string | string[] | null;\n\n// ─── per-shape branded types (advisory at compile time) ──────────────────────\n\n/** Identifier literal — opaque QTI identifier (e.g. `\"choice1\"`). */\nexport type Identifier = string;\n\n/** Directed pair literal — `\"sourceId targetId\"`. Used by match / associate / gap-match. */\nexport type DirectedPair = `${string} ${string}`;\n\n/** Point literal — `\"x y\"` integer coordinates. Used by select-point / graphic-*. */\nexport type Point = `${number} ${number}`;\n\n// ─── attribute-level parser / serializer ─────────────────────────────────────\n\n/**\n * Parse a raw `response` / `correct-response` attribute string into the\n * canonical value.\n *\n * - `null` / `undefined` / empty → `null`\n * - no comma → trimmed string\n * - one or more commas → trimmed array (single-element collapses to a string)\n */\nexport function parseResponseAttribute(raw: string | null | undefined): ResponseValue {\n if (raw == null) return null;\n if (!raw.includes(',')) {\n const trimmed = raw.trim();\n return trimmed.length > 0 ? trimmed : null;\n }\n const tokens = raw\n .split(',')\n .map(token => token.trim())\n .filter(token => token.length > 0);\n if (tokens.length === 0) return null;\n if (tokens.length === 1) return tokens[0];\n return tokens;\n}\n\n/**\n * Serialize a canonical value back to the attribute string. Returns `null` for\n * empty inputs so a Lit `@property({ reflect: true })` drops the attribute.\n */\nexport function serializeResponseAttribute(value: ResponseValue): string | null {\n if (value == null) return null;\n if (Array.isArray(value)) {\n const tokens = value.map(token => token.trim()).filter(token => token.length > 0);\n return tokens.length > 0 ? tokens.join(',') : null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\n// ─── value-shape helpers (per interaction type) ──────────────────────────────\n\n/**\n * Iterate over the comma-separated entries in a response value, regardless of\n * whether the caller has the raw string, the parsed string, or a string[].\n * Yields trimmed non-empty entries.\n */\nexport function* iterResponseValues(raw: ResponseValue): Generator<string> {\n if (raw == null) return;\n if (Array.isArray(raw)) {\n for (const v of raw) {\n const t = v.trim();\n if (t) yield t;\n }\n return;\n }\n if (!raw.includes(',')) {\n const t = raw.trim();\n if (t) yield t;\n return;\n }\n for (const v of raw.split(',')) {\n const t = v.trim();\n if (t) yield t;\n }\n}\n\n/** Parse a directed-pair value into `{ source, target }`. Throws on malformed input. */\nexport function parsePair(value: string): { source: string; target: string } {\n const [source, target, ...rest] = value.trim().split(/\\s+/);\n if (!source || !target || rest.length > 0) {\n throw new Error(`malformed directed-pair value: \"${value}\" (expected \"source target\")`);\n }\n return { source, target };\n}\n\n/** Serialize a directed pair to canonical `\"source target\"` form. */\nexport function serializePair(source: string, target: string): DirectedPair {\n return `${source} ${target}`;\n}\n\n/** Parse a point value into `{ x, y }`. Throws on malformed input. */\nexport function parsePoint(value: string): { x: number; y: number } {\n const [xStr, yStr, ...rest] = value.trim().split(/\\s+/);\n const x = Number(xStr);\n const y = Number(yStr);\n if (!Number.isFinite(x) || !Number.isFinite(y) || rest.length > 0) {\n throw new Error(`malformed point value: \"${value}\" (expected \"x y\" numeric coords)`);\n }\n return { x, y };\n}\n\n/** Serialize a point to canonical `\"x y\"` form. */\nexport function serializePoint(x: number, y: number): Point {\n return `${x} ${y}`;\n}\n\n// ─── Lit converter factory ───────────────────────────────────────────────────\n\n/**\n * Ready-to-use Lit `converter` for `response` / `correct-response` attributes.\n * Assign to the `converter` option:\n *\n * @property({ attribute: 'response', converter: responseAttributeConverter({ emptyAs: [] }) })\n *\n * `emptyAs` picks the sentinel returned when the attribute is absent / blank.\n * Three sentinels exist across the codebase — match the one your call site\n * already uses. Future work may normalize to a single sentinel.\n *\n * - '' (empty string) — ChoicesMixin convention\n * - [] — DragDropSlottedMixin / graphic-associate convention\n * - null — base interaction / select-point convention\n *\n * On the serialize side, the `emptyAs` value roundtrips back to `null` so a\n * `reflect: true` property drops the attribute rather than emitting `\"\"`.\n */\nexport function responseAttributeConverter<E extends '' | null | readonly unknown[]>(opts: {\n emptyAs: E;\n}): {\n fromAttribute: (value: string | null) => ResponseValue | E;\n toAttribute: (value: ResponseValue | E) => string | null;\n} {\n const { emptyAs } = opts;\n const isEmptySentinel = (value: unknown): boolean =>\n value === emptyAs || value == null || value === '' || (Array.isArray(value) && value.length === 0);\n\n return {\n fromAttribute: (value: string | null): ResponseValue | E => {\n const parsed = parseResponseAttribute(value);\n return parsed === null ? emptyAs : parsed;\n },\n toAttribute: (value: ResponseValue | E): string | null => {\n if (isEmptySentinel(value)) return null;\n return serializeResponseAttribute(value as ResponseValue);\n }\n };\n}\n","import { LitElement } from 'lit';\n\n/**\n * Interface for any object that can process QTI rules\n */\nexport interface QtiRuleBase {\n process(): any;\n}\n\n/**\n * Abstract base class for QTI rule DOM elements\n */\nexport abstract class QtiRuleElement extends LitElement implements QtiRuleBase {\n abstract process(): any;\n}\n","import type { BaseType } from '../lib/expression-result';\n\nexport class ScoringHelper {\n /**\n * Checks if a given point is within a specified area.\n * @param point The point to test, represented as a string \"x y\" (e.g., \"102 113\").\n * @param areaKey The area definition, including shape and coordinates (e.g., \"circle,102,113,16\").\n * @param baseType The base type of the response, must be \"point\" for this method to proceed.\n * @returns True if the point is within the area; false otherwise.\n */\n public static isPointInArea(point: string, areaKey: string, baseType: string): boolean {\n if (baseType !== 'point') {\n console.warn(`Base type ${baseType} is not supported for point area mapping.`);\n return false;\n }\n\n // Parse the point as x and y coordinates\n const [px, py] = point.split(' ').map(Number);\n\n // Parse the area definition\n const [shape, ...coords] = areaKey.split(',');\n const coordinates = coords.map(Number);\n\n switch (shape.toLowerCase()) {\n case 'circle':\n case 'default': {\n const [cx, cy, radius] = coordinates;\n if (coordinates.length !== 3) {\n console.warn(`Invalid circle definition: ${areaKey}`);\n return false;\n }\n const distance = Math.sqrt((px - cx) ** 2 + (py - cy) ** 2);\n return distance <= radius;\n }\n\n case 'rect': {\n const [x1, y1, x2, y2] = coordinates;\n if (coordinates.length !== 4) {\n console.warn(`Invalid rectangle definition: ${areaKey}`);\n return false;\n }\n return px >= x1 && px <= x2 && py >= y1 && py <= y2;\n }\n\n case 'ellipse': {\n const [cx, cy, rx, ry] = coordinates;\n if (coordinates.length !== 4) {\n console.warn(`Invalid ellipse definition: ${areaKey}`);\n return false;\n }\n // Ellipse equation: ((px - cx)² / rx²) + ((py - cy)² / ry²) <= 1\n const normalizedX = (px - cx) ** 2 / rx ** 2;\n const normalizedY = (py - cy) ** 2 / ry ** 2;\n return normalizedX + normalizedY <= 1;\n }\n\n case 'poly': {\n if (coordinates.length < 6 || coordinates.length % 2 !== 0) {\n console.warn(`Invalid polygon definition: ${areaKey}`);\n return false;\n }\n const vertices = [];\n for (let i = 0; i < coordinates.length; i += 2) {\n vertices.push({ x: coordinates[i], y: coordinates[i + 1] });\n }\n return this.isPointInPolygon({ x: px, y: py }, vertices);\n }\n\n default:\n console.warn(`Unsupported shape type: ${shape}`);\n return false;\n }\n }\n\n /**\n * Checks if a point is inside a polygon using the ray-casting algorithm.\n * @param point The point to test.\n * @param vertices The vertices of the polygon in order (array of {x, y} objects).\n * @returns True if the point is inside the polygon; false otherwise.\n */\n static isPointInPolygon(point: { x: number; y: number }, vertices: { x: number; y: number }[]): boolean {\n let inside = false;\n for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {\n const xi = vertices[i].x,\n yi = vertices[i].y;\n const xj = vertices[j].x,\n yj = vertices[j].y;\n\n const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;\n\n if (intersect) inside = !inside;\n }\n return inside;\n }\n\n public static compareSingleValues(value1: Readonly<string>, value2: Readonly<string>, baseType: BaseType): boolean {\n switch (baseType) {\n case 'identifier':\n case 'string':\n return value1 === value2;\n case 'integer': {\n const int1 = parseInt(value1, 10);\n const int2 = parseInt(value2, 10);\n if (!isNaN(int1) && !isNaN(int2)) {\n return int1 === int2;\n } else {\n console.error(`Cannot convert ${value1} and/or ${value2} to int.`);\n }\n break;\n }\n case 'float': {\n const float1 = parseFloat(value1);\n const float2 = parseFloat(value2);\n if (!isNaN(float1) && !isNaN(float2)) {\n return float1 === float2;\n } else {\n console.error(`couldn't convert ${value1} and/or ${value2} to float.`);\n }\n break;\n }\n case 'pair':\n case 'directedPair': {\n const pair1 = value1.split(' ').sort();\n const pair2 = value2.split(' ').sort();\n if (pair1.length === 2 && pair2.length === 2) {\n if (baseType === 'pair') {\n pair1.sort();\n pair2.sort();\n }\n return pair1.join(' ') === pair2.join(' ');\n } else {\n console.error(`compared two pair but one of the values does not have 2 values: 1: ${value1} 2: ${value2}`);\n }\n break;\n }\n }\n\n return false;\n }\n}\n","/**\n * Custom elements this package registers into an application's registry.\n *\n * Empty, deliberately. `qti-base` is abstractions and context — it contributes no elements to a\n * delivery application.\n *\n * The one entry that used to be here, `qti-config-test-provider`, is gone entirely. It was a\n * TEST-ONLY wrapper that every consumer of `import '@qti-components/base'` registered transitively,\n * and it carried `@customElement(...)` on top of this list — an UNGUARDED `customElements.define()`\n * at module-evaluation time. A module graph holding two copies of this package (a workspace build\n * alongside a published dist, which is what the editor resolves) evaluated it twice and the second\n * threw `NotSupportedError: ... already been used with this registry`, aborting module evaluation\n * and taking down every test file that imported it — 34 suites in the editor, none of which used\n * the element. `register.ts` had the guard right all along; the decorator bypassed it.\n *\n * Config for a single interaction is a property binding now — see config.context.ts.\n *\n * The array and `register.ts` stay so the elements + guarded-register convention the other 30\n * packages follow is already in place the day this package does own an element.\n */\nexport const qtiBaseElements: readonly { tag: string; ctor: CustomElementConstructor }[] = [];\n","import { qtiBaseElements } from './elements';\nimport { installCustomStateSetFallback } from './utils/custom-state-set';\n\n// Before any element is defined, so the patched `attachInternals` is in place by\n// the time the first interaction upgrades. No-op where `states` works natively.\ninstallCustomStateSetFallback();\n\nfor (const { tag, ctor } of qtiBaseElements) {\n if (!customElements.get(tag)) {\n customElements.define(tag, ctor);\n }\n}\n"],"mappings":"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","names":["state","createContext","createContext","createContext","createContext","createContext","createContext","createContext","css","css","state","LitElement","consume","css","html","LitElement","LitElement","css","html","__decorate","consume","consume","LitElement","property","state","LitElement","__decorate","property","consume","state","LitElement"]}