@citolab/qti-components 7.28.1 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/cdn/index.global.js +1 -1
  2. package/cdn/index.js +6316 -2710
  3. package/dist/base.d.ts +100 -15
  4. package/dist/base.js +27 -6
  5. package/dist/chunk-3AJOQCDU.js +11 -0
  6. package/dist/chunk-3AJOQCDU.js.map +1 -0
  7. package/dist/chunk-64XSIBGO.js +241 -0
  8. package/dist/chunk-64XSIBGO.js.map +1 -0
  9. package/dist/chunk-7HC5SMCU.js +102 -0
  10. package/dist/chunk-7HC5SMCU.js.map +1 -0
  11. package/dist/{chunk-SP6S2WMG.js → chunk-7V4HJFHW.js} +3 -3
  12. package/dist/{chunk-SP6S2WMG.js.map → chunk-7V4HJFHW.js.map} +1 -1
  13. package/dist/chunk-CAO4JRLY.js +11 -0
  14. package/dist/chunk-CAO4JRLY.js.map +1 -0
  15. package/dist/{chunk-MPC7LIPC.js → chunk-F4BNJWYN.js} +4264 -3647
  16. package/dist/chunk-F4BNJWYN.js.map +1 -0
  17. package/dist/{chunk-3XV26R5M.js → chunk-H3J7LFRO.js} +829 -1005
  18. package/dist/chunk-H3J7LFRO.js.map +1 -0
  19. package/dist/{chunk-3WBG257S.js → chunk-IJD53WY6.js} +96 -74
  20. package/dist/chunk-IJD53WY6.js.map +1 -0
  21. package/dist/chunk-LVBIQDPM.js +1374 -0
  22. package/dist/chunk-LVBIQDPM.js.map +1 -0
  23. package/dist/{chunk-REI3AMCZ.js → chunk-NA2N2WSG.js} +1303 -1193
  24. package/dist/chunk-NA2N2WSG.js.map +1 -0
  25. package/dist/chunk-QECOPVPO.js +294 -0
  26. package/dist/chunk-QECOPVPO.js.map +1 -0
  27. package/dist/{chunk-HFCZFWSH.js → chunk-RXGDQDOV.js} +1993 -1764
  28. package/dist/chunk-RXGDQDOV.js.map +1 -0
  29. package/dist/chunk-V5G7X53Y.js +11 -0
  30. package/dist/chunk-V5G7X53Y.js.map +1 -0
  31. package/dist/{chunk-WDO2TRFM.js → chunk-WVVMNF74.js} +851 -925
  32. package/dist/chunk-WVVMNF74.js.map +1 -0
  33. package/dist/{chunk-FLJAKWXL.js → chunk-X3E5HXG2.js} +2 -2
  34. package/dist/chunk-XU7HNT4F.js +1608 -0
  35. package/dist/chunk-XU7HNT4F.js.map +1 -0
  36. package/dist/{computed-item.context-DfsW_96S.d.ts → computed-item.types.d-BKZdSLLJ.d.ts} +2 -5
  37. package/dist/{computed.context-DHbxad0N.d.ts → computed.types.d-rKLSPvVG.d.ts} +2 -5
  38. package/dist/config.context.d-BvU9r-Mg.d.ts +91 -0
  39. package/dist/corrections.d.ts +432 -0
  40. package/dist/corrections.js +84 -0
  41. package/dist/elements.d.ts +8 -14
  42. package/dist/elements.js +6 -5
  43. package/dist/index.d.ts +51 -16
  44. package/dist/index.js +193 -76
  45. package/dist/interaction.d-D4MstYRz.d.ts +115 -0
  46. package/dist/interaction.interface.d-CvjHM2bi.d.ts +46 -0
  47. package/dist/interactions.d.ts +1206 -552
  48. package/dist/interactions.js +19 -15
  49. package/dist/item.css +4228 -1656
  50. package/dist/item.d.ts +13 -55
  51. package/dist/item.js +6 -11
  52. package/dist/{variables-CMYcDbyW.d.ts → item.types.d-QU7LljEK.d.ts} +13 -1
  53. package/dist/loader.d.ts +4 -4
  54. package/dist/loader.js +2 -3
  55. package/dist/processing.d.ts +6 -7
  56. package/dist/processing.js +2 -3
  57. package/dist/qti-components-jsx.d.ts +5348 -2709
  58. package/dist/qti-components-jsx.js +1 -0
  59. package/dist/qti-condition-expression.d-aMvBvpc6.d.ts +8 -0
  60. package/dist/{qti-condition-expression-Dam-RER6.d.ts → qti-expression.d-BietT_8b.d.ts} +14 -9
  61. package/dist/{qti-feedback-ChmXhZuf.d.ts → qti-feedback.d-DZbad0RN.d.ts} +1 -1
  62. package/dist/{qti-transform-test-DoZaWItm.d.ts → qti-transform-test.d-BL7GGFJj.d.ts} +2 -2
  63. package/dist/response.d-_8y4kjGP.d.ts +106 -0
  64. package/dist/test.d.ts +199 -39
  65. package/dist/test.js +34 -11
  66. package/dist/transformers.d.ts +1 -1
  67. package/dist/transformers.js +1 -2
  68. package/package.json +24 -17
  69. package/custom-elements.json +0 -43251
  70. package/dist/chunk-3WBG257S.js.map +0 -1
  71. package/dist/chunk-3XV26R5M.js.map +0 -1
  72. package/dist/chunk-AQ5RJFM6.js +0 -3673
  73. package/dist/chunk-AQ5RJFM6.js.map +0 -1
  74. package/dist/chunk-HFCZFWSH.js.map +0 -1
  75. package/dist/chunk-MPC7LIPC.js.map +0 -1
  76. package/dist/chunk-QXBXORM3.js +0 -27
  77. package/dist/chunk-REI3AMCZ.js.map +0 -1
  78. package/dist/chunk-RLTYVS2I.js +0 -530
  79. package/dist/chunk-RLTYVS2I.js.map +0 -1
  80. package/dist/chunk-WDO2TRFM.js.map +0 -1
  81. package/dist/config.context-BjZ2bZSY.d.ts +0 -42
  82. package/dist/interaction-Bgzlw7Iu.d.ts +0 -110
  83. package/dist/item.context-CkUeDcaO.d.ts +0 -15
  84. package/dist/test.context-CByZZjkR.d.ts +0 -15
  85. /package/dist/{chunk-FLJAKWXL.js.map → chunk-X3E5HXG2.js.map} +0 -0
  86. /package/dist/{chunk-QXBXORM3.js.map → corrections.js.map} +0 -0
  87. /package/dist/{qti-rule-base-ajOnfGXY.d.ts → qti-rule-base.d-ajOnfGXY.d.ts} +0 -0
  88. /package/dist/{qti.context-CejJMlfZ.d.ts → qti.context.d-CejJMlfZ.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { Q as QtiExpression } from './qti-expression.d-BietT_8b.js';
2
+
3
+ declare abstract class QtiConditionExpression extends QtiExpression<boolean> {
4
+ calculate(): Readonly<boolean>;
5
+ getResult(): Readonly<boolean>;
6
+ }
7
+
8
+ export { QtiConditionExpression as Q };
@@ -1,8 +1,18 @@
1
+ import { I as ItemContext, V as VariableDeclaration, f as ResponseVariable } from './item.types.d-QU7LljEK.js';
1
2
  import * as lit from 'lit';
2
3
  import { LitElement } from 'lit';
3
- import { Q as QtiContext, a as QtiContextType } from './qti.context-CejJMlfZ.js';
4
- import { f as ResponseVariable, V as VariableDeclaration } from './variables-CMYcDbyW.js';
5
- import { I as ItemContext } from './item.context-CkUeDcaO.js';
4
+ import { Q as QtiContext, a as QtiContextType } from './qti.context.d-CejJMlfZ.js';
5
+
6
+ interface TestContext {
7
+ items: (ItemContext & {
8
+ category?: string;
9
+ })[];
10
+ testOutcomeVariables?: VariableDeclaration<string | string[] | null>[];
11
+ }
12
+ declare const INITIAL_TEST_CONTEXT: Readonly<TestContext>;
13
+ declare const testContext: {
14
+ __context__: Readonly<TestContext>;
15
+ };
6
16
 
7
17
  interface QtiExpressionBase<T> {
8
18
  calculate(): Readonly<T>;
@@ -18,9 +28,4 @@ declare abstract class QtiExpression<T> extends LitElement implements QtiExpress
18
28
  getVariables: () => (ResponseVariable | VariableDeclaration<QtiContextType>)[];
19
29
  }
20
30
 
21
- declare abstract class QtiConditionExpression extends QtiExpression<boolean> {
22
- calculate(): Readonly<boolean>;
23
- getResult(): Readonly<boolean>;
24
- }
25
-
26
- export { QtiConditionExpression as Q, QtiExpression as a, type QtiExpressionBase as b };
31
+ export { INITIAL_TEST_CONTEXT as I, QtiExpression as Q, type TestContext as T, type QtiExpressionBase as a, testContext as t };
@@ -1,6 +1,6 @@
1
1
  import * as lit from 'lit';
2
2
  import { LitElement } from 'lit';
3
- import { a as Cardinality } from './variables-CMYcDbyW.js';
3
+ import { a as Cardinality } from './item.types.d-QU7LljEK.js';
4
4
 
5
5
  declare abstract class QtiVariableDeclaration extends LitElement {
6
6
  render(): lit.TemplateResult<1>;
@@ -29,7 +29,7 @@ type transformItemApi = {
29
29
  stripStyleSheets: () => transformItemApi;
30
30
  html: () => string;
31
31
  xml: () => string;
32
- htmlDoc: () => DocumentFragment;
32
+ htmlDoc: (registry?: CustomElementRegistry) => DocumentFragment;
33
33
  xmlDoc: () => XMLDocument;
34
34
  };
35
35
  declare const qtiTransformItem: () => transformItemApi;
@@ -62,7 +62,7 @@ type transformTestApi = {
62
62
  }[];
63
63
  html: () => string;
64
64
  xml: () => string;
65
- htmlDoc: () => DocumentFragment;
65
+ htmlDoc: (registry?: CustomElementRegistry) => DocumentFragment;
66
66
  xmlDoc: () => XMLDocument;
67
67
  };
68
68
  declare const qtiTransformTest: () => transformTestApi;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Canonical `response="..."` / `correct-response="..."` attribute codec.
3
+ *
4
+ * Authors put a single string on an interaction element. This module is the
5
+ * single source of truth for how that string parses into the runtime's
6
+ * internal value AND how an editor serializes the internal value back to the
7
+ * attribute. Both `@qti-components/*` interactions and `@citolab/prose-qti`
8
+ * (the editor) import from here — no per-codebase parsers, no drift.
9
+ *
10
+ * The two attributes share the same grammar; the codec is agnostic about
11
+ * which of them is being parsed.
12
+ *
13
+ * ---
14
+ *
15
+ * Format reference (per interaction):
16
+ *
17
+ * | Interaction | base-type | cardinality | attribute value |
18
+ * |----------------------|---------------|----------------------|---------------------------|
19
+ * | choice | identifier | single / multiple | "A" / "A,B,C" |
20
+ * | inline-choice | identifier | single | "Y" |
21
+ * | hottext | identifier | single / multiple | "h1" / "h1,h2" |
22
+ * | hotspot | identifier | single / multiple | "spot1" / "spot1,spot2" |
23
+ * | order | identifier | ordered | "a,b,c" (order matters) |
24
+ * | graphic-order | identifier | ordered | "spot1,spot2,spot3" |
25
+ * | match | directedPair | multiple | "src1 tgt1,src2 tgt2" |
26
+ * | associate | directedPair | multiple | "A B,C D" |
27
+ * | gap-match | directedPair | multiple | "gtext1 gap1,..." |
28
+ * | graphic-associate | directedPair | multiple | "spot1 spot2,..." |
29
+ * | graphic-gap-match | directedPair | multiple | "gimg1 spot1,..." |
30
+ * | select-point | point | single / multiple | "100 150" / "100 150,…" |
31
+ * | slider | integer | single | "50" |
32
+ * | text-entry | string | single | "paris" |
33
+ *
34
+ * Rules:
35
+ * - Comma `,` separates VALUES (different identifiers / pairs / points).
36
+ * - Space ` ` separates PARTS within one value (pair members or point coords).
37
+ * - Each value is trimmed on parse.
38
+ * - No escape mechanism. Identifiers that contain commas cannot round-trip.
39
+ */
40
+ /** Canonical parsed value of a `response` / `correct-response` attribute. */
41
+ type ResponseValue = string | string[] | null;
42
+ /** Identifier literal — opaque QTI identifier (e.g. `"choice1"`). */
43
+ type Identifier = string;
44
+ /** Directed pair literal — `"sourceId targetId"`. Used by match / associate / gap-match. */
45
+ type DirectedPair = `${string} ${string}`;
46
+ /** Point literal — `"x y"` integer coordinates. Used by select-point / graphic-*. */
47
+ type Point = `${number} ${number}`;
48
+ /**
49
+ * Parse a raw `response` / `correct-response` attribute string into the
50
+ * canonical value.
51
+ *
52
+ * - `null` / `undefined` / empty → `null`
53
+ * - no comma → trimmed string
54
+ * - one or more commas → trimmed array (single-element collapses to a string)
55
+ */
56
+ declare function parseResponseAttribute(raw: string | null | undefined): ResponseValue;
57
+ /**
58
+ * Serialize a canonical value back to the attribute string. Returns `null` for
59
+ * empty inputs so a Lit `@property({ reflect: true })` drops the attribute.
60
+ */
61
+ declare function serializeResponseAttribute(value: ResponseValue): string | null;
62
+ /**
63
+ * Iterate over the comma-separated entries in a response value, regardless of
64
+ * whether the caller has the raw string, the parsed string, or a string[].
65
+ * Yields trimmed non-empty entries.
66
+ */
67
+ declare function iterResponseValues(raw: ResponseValue): Generator<string>;
68
+ /** Parse a directed-pair value into `{ source, target }`. Throws on malformed input. */
69
+ declare function parsePair(value: string): {
70
+ source: string;
71
+ target: string;
72
+ };
73
+ /** Serialize a directed pair to canonical `"source target"` form. */
74
+ declare function serializePair(source: string, target: string): DirectedPair;
75
+ /** Parse a point value into `{ x, y }`. Throws on malformed input. */
76
+ declare function parsePoint(value: string): {
77
+ x: number;
78
+ y: number;
79
+ };
80
+ /** Serialize a point to canonical `"x y"` form. */
81
+ declare function serializePoint(x: number, y: number): Point;
82
+ /**
83
+ * Ready-to-use Lit `converter` for `response` / `correct-response` attributes.
84
+ * Assign to the `converter` option:
85
+ *
86
+ * @property({ attribute: 'response', converter: responseAttributeConverter({ emptyAs: [] }) })
87
+ *
88
+ * `emptyAs` picks the sentinel returned when the attribute is absent / blank.
89
+ * Three sentinels exist across the codebase — match the one your call site
90
+ * already uses. Future work may normalize to a single sentinel.
91
+ *
92
+ * - '' (empty string) — ChoicesMixin convention
93
+ * - [] — DragDropSlottedMixin / graphic-associate convention
94
+ * - null — base interaction / select-point convention
95
+ *
96
+ * On the serialize side, the `emptyAs` value roundtrips back to `null` so a
97
+ * `reflect: true` property drops the attribute rather than emitting `""`.
98
+ */
99
+ declare function responseAttributeConverter<E extends '' | null | readonly unknown[]>(opts: {
100
+ emptyAs: E;
101
+ }): {
102
+ fromAttribute: (value: string | null) => ResponseValue | E;
103
+ toAttribute: (value: ResponseValue | E) => string | null;
104
+ };
105
+
106
+ export { type DirectedPair as D, type Identifier as I, type Point as P, type ResponseValue as R, parsePoint as a, parseResponseAttribute as b, serializePoint as c, serializeResponseAttribute as d, iterResponseValues as i, parsePair as p, responseAttributeConverter as r, serializePair as s };
package/dist/test.d.ts CHANGED
@@ -1,17 +1,18 @@
1
1
  import * as lit from 'lit';
2
2
  import { LitElement, PropertyValues, nothing } from 'lit';
3
- import { QtiAssessmentItem, QtiModalFeedback } from './elements.js';
3
+ import { QtiAssessmentItem } from './elements.js';
4
4
  import { TemplateFunction } from '@heximal/templates';
5
- import { T as TestContext } from './test.context-CByZZjkR.js';
6
- import { g as VariableValue, b as OutcomeVariable, V as VariableDeclaration } from './variables-CMYcDbyW.js';
7
- import { S as SessionContext, C as ComputedContext, a as ComputedItem, V as View } from './computed.context-DHbxad0N.js';
8
- import { C as ConfigContext } from './config.context-BjZ2bZSY.js';
9
- import { Q as QtiContext } from './qti.context-CejJMlfZ.js';
10
- import { t as transformItemApi, b as transformTestApi } from './qti-transform-test-DoZaWItm.js';
11
- import './item.context-CkUeDcaO.js';
12
- import './qti-feedback-ChmXhZuf.js';
13
- import './qti-rule-base-ajOnfGXY.js';
14
- import './computed-item.context-DfsW_96S.js';
5
+ import { T as TestContext, Q as QtiExpression, a as QtiExpressionBase } from './qti-expression.d-BietT_8b.js';
6
+ import { g as VariableValue, b as OutcomeVariable, V as VariableDeclaration } from './item.types.d-QU7LljEK.js';
7
+ import { S as SessionContext, V as View, C as ComputedContext, a as ComputedItem } from './computed.types.d-rKLSPvVG.js';
8
+ import { C as ConfigContext } from './config.context.d-BvU9r-Mg.js';
9
+ import { QtiModalFeedback } from '@qti-components/elements/elements';
10
+ import { Q as QtiRuleBase } from './qti-rule-base.d-ajOnfGXY.js';
11
+ import { Q as QtiContext } from './qti.context.d-CejJMlfZ.js';
12
+ import { t as transformItemApi, b as transformTestApi } from './qti-transform-test.d-BL7GGFJj.js';
13
+ import './interaction.interface.d-CvjHM2bi.js';
14
+ import './qti-feedback.d-DZbad0RN.js';
15
+ import './computed-item.types.d-BKZdSLLJ.js';
15
16
 
16
17
  declare class QtiAssessmentItemRef extends LitElement {
17
18
  category?: string;
@@ -59,7 +60,9 @@ interface TestBaseInterface extends LitElement {
59
60
  type PostLoadTransformCallback = (transformer: transformItemApi, itemRef: QtiAssessmentItemRef) => transformItemApi | Promise<transformItemApi>;
60
61
  type PostLoadTestTransformCallback = (transformer: transformTestApi, testElement: QtiAssessmentTest) => transformTestApi | Promise<transformTestApi>;
61
62
 
62
- declare const QtiTest_base: (abstract new (...args: any[]) => {}) & (abstract new (...args: any[]) => {}) & (abstract new (...args: any[]) => {
63
+ declare const QtiTest_base: (abstract new (...args: any[]) => {}) & (abstract new (...args: any[]) => {
64
+ updateAssessmentItemView(assessmentItem: QtiAssessmentItem, view: View): void;
65
+ }) & (abstract new (...args: any[]) => {
63
66
  updateOutcomeVariable(identifier: string, value: string | string[] | undefined): void;
64
67
  getOutcome(identifier: string): Readonly<OutcomeVariable>;
65
68
  getVariable(identifier: string): Readonly<VariableDeclaration<string | string[] | null>>;
@@ -174,11 +177,45 @@ declare global {
174
177
  }
175
178
  }
176
179
 
180
+ declare class QtiOutcomeProcessing extends LitElement {
181
+ static styles: lit.CSSResult[];
182
+ render(): lit.TemplateResult<1>;
183
+ process(): void;
184
+ }
185
+ declare global {
186
+ interface HTMLElementTagNameMap {
187
+ 'qti-outcome-processing': QtiOutcomeProcessing;
188
+ }
189
+ }
190
+ declare class QtiOutcomeProcessingProcessor {
191
+ process(rules: QtiRuleBase[]): void;
192
+ }
193
+
194
+ declare class QtiTestVariables extends QtiExpression<number> {
195
+ #private;
196
+ _testContext?: TestContext;
197
+ constructor();
198
+ getResult(): number;
199
+ calculate(): number;
200
+ }
201
+ declare class QtiTestVariablesExpression implements QtiExpressionBase<number> {
202
+ private testContext;
203
+ private itemVariable;
204
+ private includedItems;
205
+ constructor(testContext: TestContext, itemVariable: string, includedItems: {
206
+ item: string;
207
+ weight: number;
208
+ }[]);
209
+ calculate(): number;
210
+ }
211
+ declare global {
212
+ interface HTMLElementTagNameMap {
213
+ 'qti-test-variables': QtiTestVariables;
214
+ }
215
+ }
216
+
177
217
  type CustomEventMap = {
178
218
  'test-end-attempt': CustomEvent;
179
- 'test-show-correct-response': CustomEvent<{
180
- value: boolean;
181
- }>;
182
219
  };
183
220
  declare global {
184
221
  interface GlobalEventHandlersEventMap extends CustomEventMap {
@@ -198,9 +235,16 @@ declare class TestNavigation extends LitElement {
198
235
  protected computedContext: ComputedContext;
199
236
  autoScoreItems: boolean;
200
237
  constructor();
238
+ /** The currently active assessment item, exposed for optional presentation extensions. */
239
+ protected get activeAssessmentItem(): QtiAssessmentItem | undefined;
201
240
  render(): lit.TemplateResult<1>;
202
241
  protected willUpdate(_changedProperties: PropertyValues): void;
203
242
  }
243
+ declare global {
244
+ interface HTMLElementTagNameMap {
245
+ 'test-navigation': TestNavigation;
246
+ }
247
+ }
204
248
 
205
249
  /**
206
250
  * Represents a custom element for navigating to the next test item.
@@ -260,7 +304,7 @@ declare class TestPrev extends LitElement {
260
304
  }
261
305
  declare global {
262
306
  interface HTMLElementTagNameMap {
263
- 'test-previous': TestPrev;
307
+ 'test-prev': TestPrev;
264
308
  }
265
309
  }
266
310
 
@@ -308,27 +352,6 @@ declare global {
308
352
  }
309
353
  }
310
354
 
311
- /**
312
- * @deprecated test-show-correct-response is deprecated and will be removed in the future.
313
- */
314
- declare class TestShowCorrectResponse extends LitElement {
315
- #private;
316
- computedContext?: ComputedContext;
317
- static styles: lit.CSSResult;
318
- shown: boolean;
319
- disabled: boolean;
320
- showCorrectText: string;
321
- hideCorrectText: string;
322
- noCorrectResponseText: string;
323
- willUpdate(_changedProperties: Map<string | number | symbol, unknown>): void;
324
- render(): lit.TemplateResult<1>;
325
- }
326
- declare global {
327
- interface HTMLElementTagNameMap {
328
- 'test-show-correct-response': TestShowCorrectResponse;
329
- }
330
- }
331
-
332
355
  /**
333
356
  * @deprecated test-paging-buttons-stamp is deprecated and will be removed in the future.
334
357
  */
@@ -362,6 +385,8 @@ declare global {
362
385
  */
363
386
  declare class TestContainer extends LitElement {
364
387
  #private;
388
+ /** Scoped registry used by the test shadow root. Must be set before connection. */
389
+ customElementRegistry: CustomElementRegistry | null;
365
390
  /** URL of the item to load */
366
391
  testURL: string;
367
392
  /** A parsed HTML document */
@@ -369,6 +394,7 @@ declare class TestContainer extends LitElement {
369
394
  /** The raw XML string */
370
395
  testXML: string;
371
396
  protected qtiContext: QtiContext;
397
+ protected createRenderRoot(): HTMLElement | DocumentFragment;
372
398
  /** Callback function to transform the test after loading */
373
399
  protected handleTestURLChange(): Promise<void>;
374
400
  protected handleTestXMLChange(): void;
@@ -467,7 +493,7 @@ declare class TestScoringButtons extends LitElement {
467
493
  protected createRenderRoot(): HTMLElement | DocumentFragment;
468
494
  connectedCallback(): void;
469
495
  protected computedContext?: ComputedContext;
470
- render(): typeof nothing | lit.TemplateResult<1>;
496
+ render(): lit.TemplateResult<1> | typeof nothing;
471
497
  constructor();
472
498
  }
473
499
  declare global {
@@ -513,11 +539,145 @@ declare global {
513
539
  }
514
540
  }
515
541
 
542
+ type SpeechState = 'idle' | 'playing' | 'paused';
543
+ interface TtsContext {
544
+ state: SpeechState;
545
+ /** Index of the currently highlighted reading element (0-based). */
546
+ currentElementIndex: number;
547
+ /** Total number of navigable reading elements in the current item. */
548
+ elementCount: number;
549
+ play(): void;
550
+ pause(): void;
551
+ resume(): void;
552
+ stop(): void;
553
+ prevElement(): void;
554
+ nextElement(): void;
555
+ }
556
+
557
+ declare const ttsContext: {
558
+ __context__: TtsContext;
559
+ };
560
+ /**
561
+ * Base class shared by all TTS control elements. Consumes `ttsContext` and
562
+ * mirrors the current speech state onto CSS custom states so each child can
563
+ * be styled with `:state(playing)`, `:state(paused)`, `:state(idle)`.
564
+ */
565
+ declare abstract class TtsButtonBase extends LitElement {
566
+ #private;
567
+ static styles: lit.CSSResult;
568
+ protected _tts?: TtsContext;
569
+ updated(changed: PropertyValues): void;
570
+ }
571
+ /**
572
+ * `<test-item-to-speech>` is the controller and context provider. It manages
573
+ * speech synthesis, word highlighting, and item element lookup. Compose your
574
+ * own player by placing control elements as children.
575
+ *
576
+ * @example
577
+ * ```html
578
+ * <test-item-to-speech language="nl-NL">
579
+ * <test-tts-play></test-tts-play>
580
+ * <test-tts-prev>◀◀</test-tts-prev>
581
+ * <test-tts-next>▶▶</test-tts-next>
582
+ * <test-tts-stop>■</test-tts-stop>
583
+ * </test-item-to-speech>
584
+ * ```
585
+ *
586
+ * @cssstate idle - No speech active
587
+ * @cssstate playing - Speech is playing
588
+ * @cssstate paused - Speech is paused
589
+ */
590
+ declare class TestItemToSpeech extends LitElement {
591
+ #private;
592
+ language: string;
593
+ protected _sessionContext?: SessionContext;
594
+ _ttsContext: TtsContext;
595
+ constructor();
596
+ willUpdate(changed: PropertyValues): void;
597
+ updated(_changed: PropertyValues): void;
598
+ connectedCallback(): void;
599
+ disconnectedCallback(): void;
600
+ render(): lit.TemplateResult<1>;
601
+ }
602
+ /**
603
+ * Play/pause/resume toggle button — always enabled, cycles through states.
604
+ * Use named slots `play` and `pause` to customise the icons/labels independently.
605
+ *
606
+ * @example
607
+ * ```html
608
+ * <test-tts-play>
609
+ * <span slot="play">▶ Play</span>
610
+ * <span slot="pause">⏸ Pause</span>
611
+ * </test-tts-play>
612
+ * ```
613
+ *
614
+ * @cssstate idle / playing / paused
615
+ * @csspart button
616
+ */
617
+ declare class TestTtsPlay extends TtsButtonBase {
618
+ #private;
619
+ render(): lit.TemplateResult<1>;
620
+ }
621
+ /**
622
+ * Pause button — enabled only when playing.
623
+ * @cssstate idle / playing / paused
624
+ * @csspart button
625
+ */
626
+ declare class TestTtsPause extends TtsButtonBase {
627
+ render(): lit.TemplateResult<1>;
628
+ }
629
+ /**
630
+ * Resume button — enabled only when paused.
631
+ * @cssstate idle / playing / paused
632
+ * @csspart button
633
+ */
634
+ declare class TestTtsResume extends TtsButtonBase {
635
+ render(): lit.TemplateResult<1>;
636
+ }
637
+ /**
638
+ * Stop button — enabled when playing or paused.
639
+ * @cssstate idle / playing / paused
640
+ * @csspart button
641
+ */
642
+ declare class TestTtsStop extends TtsButtonBase {
643
+ render(): lit.TemplateResult<1>;
644
+ }
645
+ /**
646
+ * Prev-element button — moves cursor to the previous reading element and pauses.
647
+ * Disabled at the first element or when no elements are loaded.
648
+ * @cssstate idle / playing / paused
649
+ * @csspart button
650
+ */
651
+ declare class TestTtsPrev extends TtsButtonBase {
652
+ render(): lit.TemplateResult<1>;
653
+ }
654
+ /**
655
+ * Next-element button — moves cursor to the next reading element and pauses.
656
+ * Disabled at the last element or when no elements are loaded.
657
+ * @cssstate idle / playing / paused
658
+ * @csspart button
659
+ */
660
+ declare class TestTtsNext extends TtsButtonBase {
661
+ render(): lit.TemplateResult<1>;
662
+ }
663
+ declare global {
664
+ interface HTMLElementTagNameMap {
665
+ 'test-item-to-speech': TestItemToSpeech;
666
+ 'test-tts-play': TestTtsPlay;
667
+ 'test-tts-pause': TestTtsPause;
668
+ 'test-tts-resume': TestTtsResume;
669
+ 'test-tts-stop': TestTtsStop;
670
+ 'test-tts-prev': TestTtsPrev;
671
+ 'test-tts-next': TestTtsNext;
672
+ }
673
+ }
674
+
516
675
  interface IQtiTest extends LitElement, ITestNavigationMixin, ITestProcessingMixin, IMyQtiTest {
517
676
  }
518
677
  interface IMyQtiTest {
519
678
  testContext: Readonly<TestContext>;
520
679
  sessionContext: Readonly<SessionContext>;
680
+ configContext: ConfigContext;
521
681
  updateItemVariables(itemRefID: string, variables: VariableValue<string | string[] | null>[]): void;
522
682
  }
523
683
  interface ITestNavigationMixin {
@@ -536,4 +696,4 @@ interface ITestProcessingMixin {
536
696
  outcomeProcessing(): boolean;
537
697
  }
538
698
 
539
- export { type IMyQtiTest, type IQtiTest, type ITestNavigationMixin, type ITestProcessingMixin, QtiAssessmentItemRef, QtiAssessmentSection, QtiAssessmentTest, QtiTest, QtiTestFeedback, QtiTestPart, TestCheckItem, TestContainer, TestEndAttempt, TestItemLink, TestNavigation, TestNext, TestPagingButtonsStamp, TestPrev, TestPrintContext, TestPrintVariables, TestScoringButtons, TestScoringFeedback, TestSectionButtonsStamp, TestSectionLink, TestShowCorrectResponse, TestStamp, TestView, TestViewToggle };
699
+ export { type IMyQtiTest, type IQtiTest, type ITestNavigationMixin, type ITestProcessingMixin, QtiAssessmentItemRef, QtiAssessmentSection, QtiAssessmentTest, QtiOutcomeProcessing, QtiOutcomeProcessingProcessor, QtiTest, QtiTestFeedback, QtiTestPart, QtiTestVariables, QtiTestVariablesExpression, type SpeechState, TestCheckItem, TestContainer, TestEndAttempt, TestItemLink, TestItemToSpeech, TestNavigation, TestNext, TestPagingButtonsStamp, TestPrev, TestPrintContext, TestPrintVariables, TestScoringButtons, TestScoringFeedback, TestSectionButtonsStamp, TestSectionLink, TestStamp, TestTtsNext, TestTtsPause, TestTtsPlay, TestTtsPrev, TestTtsResume, TestTtsStop, TestView, TestViewToggle, type TtsContext, ttsContext };
package/dist/test.js CHANGED
@@ -1,14 +1,20 @@
1
+ import "./chunk-CAO4JRLY.js";
1
2
  import {
2
3
  QtiAssessmentItemRef,
3
4
  QtiAssessmentSection,
4
5
  QtiAssessmentTest,
6
+ QtiOutcomeProcessing,
7
+ QtiOutcomeProcessingProcessor,
5
8
  QtiTest,
6
9
  QtiTestFeedback,
7
10
  QtiTestPart,
11
+ QtiTestVariables,
12
+ QtiTestVariablesExpression,
8
13
  TestCheckItem,
9
14
  TestContainer,
10
15
  TestEndAttempt,
11
16
  TestItemLink,
17
+ TestItemToSpeech,
12
18
  TestNavigation,
13
19
  TestNext,
14
20
  TestPagingButtonsStamp,
@@ -19,28 +25,39 @@ import {
19
25
  TestScoringFeedback,
20
26
  TestSectionButtonsStamp,
21
27
  TestSectionLink,
22
- TestShowCorrectResponse,
23
28
  TestStamp,
29
+ TestTtsNext,
30
+ TestTtsPause,
31
+ TestTtsPlay,
32
+ TestTtsPrev,
33
+ TestTtsResume,
34
+ TestTtsStop,
24
35
  TestView,
25
- TestViewToggle
26
- } from "./chunk-HFCZFWSH.js";
27
- import "./chunk-WDO2TRFM.js";
28
- import "./chunk-FLJAKWXL.js";
29
- import "./chunk-AQ5RJFM6.js";
30
- import "./chunk-3WBG257S.js";
31
- import "./chunk-3XV26R5M.js";
32
- import "./chunk-QXBXORM3.js";
36
+ TestViewToggle,
37
+ ttsContext
38
+ } from "./chunk-RXGDQDOV.js";
39
+ import "./chunk-WVVMNF74.js";
40
+ import "./chunk-X3E5HXG2.js";
41
+ import "./chunk-7HC5SMCU.js";
42
+ import "./chunk-64XSIBGO.js";
43
+ import "./chunk-IJD53WY6.js";
44
+ import "./chunk-H3J7LFRO.js";
33
45
  export {
34
46
  QtiAssessmentItemRef,
35
47
  QtiAssessmentSection,
36
48
  QtiAssessmentTest,
49
+ QtiOutcomeProcessing,
50
+ QtiOutcomeProcessingProcessor,
37
51
  QtiTest,
38
52
  QtiTestFeedback,
39
53
  QtiTestPart,
54
+ QtiTestVariables,
55
+ QtiTestVariablesExpression,
40
56
  TestCheckItem,
41
57
  TestContainer,
42
58
  TestEndAttempt,
43
59
  TestItemLink,
60
+ TestItemToSpeech,
44
61
  TestNavigation,
45
62
  TestNext,
46
63
  TestPagingButtonsStamp,
@@ -51,9 +68,15 @@ export {
51
68
  TestScoringFeedback,
52
69
  TestSectionButtonsStamp,
53
70
  TestSectionLink,
54
- TestShowCorrectResponse,
55
71
  TestStamp,
72
+ TestTtsNext,
73
+ TestTtsPause,
74
+ TestTtsPlay,
75
+ TestTtsPrev,
76
+ TestTtsResume,
77
+ TestTtsStop,
56
78
  TestView,
57
- TestViewToggle
79
+ TestViewToggle,
80
+ ttsContext
58
81
  };
59
82
  //# sourceMappingURL=test.js.map
@@ -1,4 +1,4 @@
1
- export { M as ModuleResolutionConfig, q as qtiTransformItem, a as qtiTransformTest, t as transformItemApi, b as transformTestApi } from './qti-transform-test-DoZaWItm.js';
1
+ export { M as ModuleResolutionConfig, q as qtiTransformItem, a as qtiTransformTest, t as transformItemApi, b as transformTestApi } from './qti-transform-test.d-BL7GGFJj.js';
2
2
 
3
3
  declare const qtiTransformManifest: () => {
4
4
  load: (uri: string, signal?: AbortSignal) => Promise<{
@@ -2,8 +2,7 @@ import {
2
2
  qtiTransformItem,
3
3
  qtiTransformManifest,
4
4
  qtiTransformTest
5
- } from "./chunk-3WBG257S.js";
6
- import "./chunk-QXBXORM3.js";
5
+ } from "./chunk-IJD53WY6.js";
7
6
  export {
8
7
  qtiTransformItem,
9
8
  qtiTransformManifest,