@examplary/qti 0.0.1 → 1.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 (66) hide show
  1. package/README.md +6 -1
  2. package/dist/ims/ims-manifest.js +15 -7
  3. package/dist/ims/ims-package.d.ts +1 -1
  4. package/dist/ims/ims-package.js +16 -8
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +23 -6
  7. package/dist/qti/interactions/associate-interaction.d.ts +36 -0
  8. package/dist/qti/interactions/associate-interaction.js +49 -0
  9. package/dist/qti/interactions/choice-interaction.d.ts +36 -0
  10. package/dist/qti/interactions/choice-interaction.js +46 -0
  11. package/dist/qti/interactions/drawing-interaction.d.ts +25 -0
  12. package/dist/qti/interactions/drawing-interaction.js +33 -0
  13. package/dist/qti/interactions/end-attempt-interaction.d.ts +21 -0
  14. package/dist/qti/interactions/end-attempt-interaction.js +30 -0
  15. package/dist/qti/interactions/extended-text-interaction.d.ts +28 -0
  16. package/dist/qti/interactions/extended-text-interaction.js +37 -0
  17. package/dist/qti/interactions/gap-match-interaction.d.ts +34 -0
  18. package/dist/qti/interactions/gap-match-interaction.js +49 -0
  19. package/dist/qti/interactions/graphic-associate-interaction.d.ts +37 -0
  20. package/dist/qti/interactions/graphic-associate-interaction.js +50 -0
  21. package/dist/qti/interactions/graphic-gap-match-interaction.d.ts +42 -0
  22. package/dist/qti/interactions/graphic-gap-match-interaction.js +67 -0
  23. package/dist/qti/interactions/graphic-order-interaction.d.ts +28 -0
  24. package/dist/qti/interactions/graphic-order-interaction.js +49 -0
  25. package/dist/qti/interactions/hotspot-interaction.d.ts +41 -0
  26. package/dist/qti/interactions/hotspot-interaction.js +49 -0
  27. package/dist/qti/interactions/hottext-interaction.d.ts +22 -0
  28. package/dist/qti/interactions/hottext-interaction.js +34 -0
  29. package/dist/qti/interactions/index.d.ts +63 -0
  30. package/dist/qti/interactions/index.js +80 -0
  31. package/dist/qti/interactions/inline-choice-interaction.d.ts +30 -0
  32. package/dist/qti/interactions/inline-choice-interaction.js +43 -0
  33. package/dist/qti/interactions/interaction.d.ts +20 -0
  34. package/dist/qti/interactions/interaction.js +31 -0
  35. package/dist/qti/interactions/match-interaction.d.ts +31 -0
  36. package/dist/qti/interactions/match-interaction.js +66 -0
  37. package/dist/qti/interactions/media-interaction.d.ts +31 -0
  38. package/dist/qti/interactions/media-interaction.js +39 -0
  39. package/dist/qti/interactions/order-interaction.d.ts +28 -0
  40. package/dist/qti/interactions/order-interaction.js +46 -0
  41. package/dist/qti/interactions/position-object-interaction.d.ts +36 -0
  42. package/dist/qti/interactions/position-object-interaction.js +46 -0
  43. package/dist/qti/interactions/select-point-interaction.d.ts +28 -0
  44. package/dist/qti/interactions/select-point-interaction.js +36 -0
  45. package/dist/qti/interactions/slider-interaction.d.ts +26 -0
  46. package/dist/qti/interactions/slider-interaction.js +35 -0
  47. package/dist/qti/interactions/text-entry-interaction.d.ts +25 -0
  48. package/dist/qti/interactions/text-entry-interaction.js +34 -0
  49. package/dist/qti/interactions/upload-interaction.d.ts +19 -0
  50. package/dist/qti/interactions/upload-interaction.js +28 -0
  51. package/dist/qti/qti-element.d.ts +11 -0
  52. package/dist/qti/qti-element.js +32 -0
  53. package/dist/qti/qti-item.d.ts +7 -3
  54. package/dist/qti/qti-item.js +38 -28
  55. package/dist/qti/qti-test.d.ts +5 -3
  56. package/dist/qti/qti-test.js +25 -11
  57. package/dist/qti/types.js +2 -2
  58. package/dist/utils/html.d.ts +2 -0
  59. package/dist/utils/html.js +18 -0
  60. package/package.json +3 -3
  61. package/dist/ims/ims-manifest.js.map +0 -1
  62. package/dist/ims/ims-package.js.map +0 -1
  63. package/dist/index.js.map +0 -1
  64. package/dist/qti/qti-item.js.map +0 -1
  65. package/dist/qti/qti-test.js.map +0 -1
  66. package/dist/qti/types.js.map +0 -1
@@ -0,0 +1,31 @@
1
+ import { SimpleAssociableChoiceOptions } from "./associate-interaction";
2
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
3
+ export type MatchInteractionOptions = QtiPromptInteractionOptions & {
4
+ shuffle?: boolean;
5
+ minAssociations?: number;
6
+ maxAssociations?: number;
7
+ sourceChoices?: SimpleAssociableChoiceOptions[];
8
+ targetChoices?: SimpleAssociableChoiceOptions[];
9
+ };
10
+ /**
11
+ * Presents two sets of choices for candidates to match or associate with each other.
12
+ * Commonly used for matching terms with definitions or pairing related concepts.
13
+ *
14
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.be4ll1tm4t99
15
+ *
16
+ * @example
17
+ * const interaction = new MatchInteraction({
18
+ * responseIdentifier: "RESPONSE",
19
+ * sourceChoices: [
20
+ * { identifier: "S1", content: "Paris", matchMax: 1 },
21
+ * { identifier: "S2", content: "London", matchMax: 1 },
22
+ * ],
23
+ * targetChoices: [
24
+ * { identifier: "T1", content: "France", matchMax: 1 },
25
+ * { identifier: "T2", content: "England", matchMax: 1 },
26
+ * ],
27
+ * });
28
+ */
29
+ export declare class MatchInteraction extends QtiPromptInteraction {
30
+ constructor(options: MatchInteractionOptions);
31
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MatchInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ const html_1 = require("../../utils/html");
7
+ /**
8
+ * Presents two sets of choices for candidates to match or associate with each other.
9
+ * Commonly used for matching terms with definitions or pairing related concepts.
10
+ *
11
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.be4ll1tm4t99
12
+ *
13
+ * @example
14
+ * const interaction = new MatchInteraction({
15
+ * responseIdentifier: "RESPONSE",
16
+ * sourceChoices: [
17
+ * { identifier: "S1", content: "Paris", matchMax: 1 },
18
+ * { identifier: "S2", content: "London", matchMax: 1 },
19
+ * ],
20
+ * targetChoices: [
21
+ * { identifier: "T1", content: "France", matchMax: 1 },
22
+ * { identifier: "T2", content: "England", matchMax: 1 },
23
+ * ],
24
+ * });
25
+ */
26
+ class MatchInteraction extends interaction_1.QtiPromptInteraction {
27
+ constructor(options) {
28
+ super(options);
29
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-match-interaction", {
30
+ "response-identifier": options.responseIdentifier,
31
+ label: options.label,
32
+ shuffle: options.shuffle ? "true" : "false",
33
+ "min-associations": options.minAssociations?.toString(),
34
+ "max-associations": options.maxAssociations?.toString(),
35
+ });
36
+ const sourceSet = this.item.ele("qti-simple-match-set");
37
+ for (const choice of options.sourceChoices || []) {
38
+ const choiceEl = sourceSet.ele("qti-simple-associable-choice", {
39
+ identifier: choice.identifier,
40
+ "match-max": choice.matchMax?.toString(),
41
+ "match-min": choice.matchMin?.toString(),
42
+ "match-group": choice.matchGroup,
43
+ fixed: choice.fixed ? "true" : undefined,
44
+ "template-identifier": choice.templateIdentifier,
45
+ });
46
+ if (choice.content) {
47
+ (0, html_1.appendHtmlFragment)(choice.content, choiceEl);
48
+ }
49
+ }
50
+ const targetSet = this.item.ele("qti-simple-match-set");
51
+ for (const choice of options.targetChoices || []) {
52
+ const choiceEl = targetSet.ele("qti-simple-associable-choice", {
53
+ identifier: choice.identifier,
54
+ "match-max": choice.matchMax?.toString(),
55
+ "match-min": choice.matchMin?.toString(),
56
+ "match-group": choice.matchGroup,
57
+ fixed: choice.fixed ? "true" : undefined,
58
+ "template-identifier": choice.templateIdentifier,
59
+ });
60
+ if (choice.content) {
61
+ (0, html_1.appendHtmlFragment)(choice.content, choiceEl);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ exports.MatchInteraction = MatchInteraction;
@@ -0,0 +1,31 @@
1
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
2
+ export type MediaObjectOptions = {
3
+ data: string;
4
+ type: string;
5
+ width?: number;
6
+ height?: number;
7
+ };
8
+ export type MediaInteractionOptions = QtiPromptInteractionOptions & {
9
+ autostart?: boolean;
10
+ minPlays?: number;
11
+ maxPlays?: number;
12
+ loop?: boolean;
13
+ object: MediaObjectOptions;
14
+ };
15
+ /**
16
+ * Presents audio or video content that candidates must engage with before responding.
17
+ * Used for listening comprehension, video analysis, or multimedia-based questions.
18
+ *
19
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.u9utgghwf8ck
20
+ *
21
+ * @example
22
+ * const interaction = new MediaInteraction({
23
+ * responseIdentifier: "RESPONSE",
24
+ * minPlays: 1,
25
+ * maxPlays: 3,
26
+ * object: { data: "audio.mp3", type: "audio/mpeg" },
27
+ * });
28
+ */
29
+ export declare class MediaInteraction extends QtiPromptInteraction {
30
+ constructor(options: MediaInteractionOptions);
31
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MediaInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ /**
7
+ * Presents audio or video content that candidates must engage with before responding.
8
+ * Used for listening comprehension, video analysis, or multimedia-based questions.
9
+ *
10
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.u9utgghwf8ck
11
+ *
12
+ * @example
13
+ * const interaction = new MediaInteraction({
14
+ * responseIdentifier: "RESPONSE",
15
+ * minPlays: 1,
16
+ * maxPlays: 3,
17
+ * object: { data: "audio.mp3", type: "audio/mpeg" },
18
+ * });
19
+ */
20
+ class MediaInteraction extends interaction_1.QtiPromptInteraction {
21
+ constructor(options) {
22
+ super(options);
23
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-media-interaction", {
24
+ "response-identifier": options.responseIdentifier,
25
+ label: options.label,
26
+ autostart: options.autostart ? "true" : undefined,
27
+ "min-plays": options.minPlays?.toString(),
28
+ "max-plays": options.maxPlays?.toString(),
29
+ loop: options.loop ? "true" : undefined,
30
+ });
31
+ this.item.ele("object", {
32
+ data: options.object.data,
33
+ type: options.object.type,
34
+ width: options.object.width?.toString(),
35
+ height: options.object.height?.toString(),
36
+ });
37
+ }
38
+ }
39
+ exports.MediaInteraction = MediaInteraction;
@@ -0,0 +1,28 @@
1
+ import { SimpleChoiceOptions } from "./choice-interaction";
2
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
3
+ export type OrderInteractionOptions = QtiPromptInteractionOptions & {
4
+ shuffle?: boolean;
5
+ minChoices?: number;
6
+ maxChoices?: number;
7
+ orientation?: "horizontal" | "vertical";
8
+ choices?: SimpleChoiceOptions[];
9
+ };
10
+ /**
11
+ * Presents a set of choices for candidates to arrange in a specific order or sequence.
12
+ * Used for ranking, sequencing, or prioritization questions.
13
+ *
14
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.4n8gips6tlv4
15
+ *
16
+ * @example
17
+ * const interaction = new OrderInteraction({
18
+ * responseIdentifier: "RESPONSE",
19
+ * choices: [
20
+ * { identifier: "A", content: "First step" },
21
+ * { identifier: "B", content: "Second step" },
22
+ * { identifier: "C", content: "Third step" },
23
+ * ],
24
+ * });
25
+ */
26
+ export declare class OrderInteraction extends QtiPromptInteraction {
27
+ constructor(options: OrderInteractionOptions);
28
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrderInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ const html_1 = require("../../utils/html");
7
+ /**
8
+ * Presents a set of choices for candidates to arrange in a specific order or sequence.
9
+ * Used for ranking, sequencing, or prioritization questions.
10
+ *
11
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.4n8gips6tlv4
12
+ *
13
+ * @example
14
+ * const interaction = new OrderInteraction({
15
+ * responseIdentifier: "RESPONSE",
16
+ * choices: [
17
+ * { identifier: "A", content: "First step" },
18
+ * { identifier: "B", content: "Second step" },
19
+ * { identifier: "C", content: "Third step" },
20
+ * ],
21
+ * });
22
+ */
23
+ class OrderInteraction extends interaction_1.QtiPromptInteraction {
24
+ constructor(options) {
25
+ super(options);
26
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-order-interaction", {
27
+ "response-identifier": options.responseIdentifier,
28
+ label: options.label,
29
+ shuffle: options.shuffle ? "true" : "false",
30
+ "min-choices": options.minChoices?.toString(),
31
+ "max-choices": options.maxChoices?.toString(),
32
+ orientation: options.orientation,
33
+ });
34
+ for (const choice of options.choices || []) {
35
+ const choiceEl = this.item.ele("qti-simple-choice", {
36
+ identifier: choice.identifier,
37
+ fixed: choice.fixed ? "true" : undefined,
38
+ "template-identifier": choice.templateIdentifier,
39
+ });
40
+ if (choice.content) {
41
+ (0, html_1.appendHtmlFragment)(choice.content, choiceEl);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ exports.OrderInteraction = OrderInteraction;
@@ -0,0 +1,36 @@
1
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
2
+ export type PositionObjectStageOptions = {
3
+ data: string;
4
+ type: string;
5
+ width?: number;
6
+ height?: number;
7
+ };
8
+ export type PositionObjectOptions = {
9
+ data: string;
10
+ type: string;
11
+ width?: number;
12
+ height?: number;
13
+ };
14
+ export type PositionObjectInteractionOptions = QtiPromptInteractionOptions & {
15
+ centerPoint?: string;
16
+ minChoices?: number;
17
+ maxChoices?: number;
18
+ object: PositionObjectOptions;
19
+ positionObjectStage?: PositionObjectStageOptions;
20
+ };
21
+ /**
22
+ * Presents a movable object that candidates must position on a background stage.
23
+ * Used for placing items at specific coordinates on a canvas or diagram.
24
+ *
25
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.4jhs37jil26s
26
+ *
27
+ * @example
28
+ * const interaction = new PositionObjectInteraction({
29
+ * responseIdentifier: "RESPONSE",
30
+ * object: { data: "marker.png", type: "image/png", width: 20, height: 20 },
31
+ * positionObjectStage: { data: "map.png", type: "image/png", width: 400, height: 300 },
32
+ * });
33
+ */
34
+ export declare class PositionObjectInteraction extends QtiPromptInteraction {
35
+ constructor(options: PositionObjectInteractionOptions);
36
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PositionObjectInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ /**
7
+ * Presents a movable object that candidates must position on a background stage.
8
+ * Used for placing items at specific coordinates on a canvas or diagram.
9
+ *
10
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.4jhs37jil26s
11
+ *
12
+ * @example
13
+ * const interaction = new PositionObjectInteraction({
14
+ * responseIdentifier: "RESPONSE",
15
+ * object: { data: "marker.png", type: "image/png", width: 20, height: 20 },
16
+ * positionObjectStage: { data: "map.png", type: "image/png", width: 400, height: 300 },
17
+ * });
18
+ */
19
+ class PositionObjectInteraction extends interaction_1.QtiPromptInteraction {
20
+ constructor(options) {
21
+ super(options);
22
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-position-object-interaction", {
23
+ "response-identifier": options.responseIdentifier,
24
+ label: options.label,
25
+ "center-point": options.centerPoint,
26
+ "min-choices": options.minChoices?.toString(),
27
+ "max-choices": options.maxChoices?.toString(),
28
+ });
29
+ this.item.ele("object", {
30
+ data: options.object.data,
31
+ type: options.object.type,
32
+ width: options.object.width?.toString(),
33
+ height: options.object.height?.toString(),
34
+ });
35
+ if (options.positionObjectStage) {
36
+ const stage = this.item.ele("qti-position-object-stage");
37
+ stage.ele("object", {
38
+ data: options.positionObjectStage.data,
39
+ type: options.positionObjectStage.type,
40
+ width: options.positionObjectStage.width?.toString(),
41
+ height: options.positionObjectStage.height?.toString(),
42
+ });
43
+ }
44
+ }
45
+ }
46
+ exports.PositionObjectInteraction = PositionObjectInteraction;
@@ -0,0 +1,28 @@
1
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
2
+ export type SelectPointObjectOptions = {
3
+ data: string;
4
+ type: string;
5
+ width?: number;
6
+ height?: number;
7
+ };
8
+ export type SelectPointInteractionOptions = QtiPromptInteractionOptions & {
9
+ minChoices?: number;
10
+ maxChoices?: number;
11
+ object: SelectPointObjectOptions;
12
+ };
13
+ /**
14
+ * Presents an image where candidates select specific coordinate points.
15
+ * Used for identifying precise locations on maps, graphs, or diagrams.
16
+ *
17
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.ev30y6ze263d
18
+ *
19
+ * @example
20
+ * const interaction = new SelectPointInteraction({
21
+ * responseIdentifier: "RESPONSE",
22
+ * maxChoices: 1,
23
+ * object: { data: "graph.png", type: "image/png", width: 400, height: 300 },
24
+ * });
25
+ */
26
+ export declare class SelectPointInteraction extends QtiPromptInteraction {
27
+ constructor(options: SelectPointInteractionOptions);
28
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectPointInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ /**
7
+ * Presents an image where candidates select specific coordinate points.
8
+ * Used for identifying precise locations on maps, graphs, or diagrams.
9
+ *
10
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.ev30y6ze263d
11
+ *
12
+ * @example
13
+ * const interaction = new SelectPointInteraction({
14
+ * responseIdentifier: "RESPONSE",
15
+ * maxChoices: 1,
16
+ * object: { data: "graph.png", type: "image/png", width: 400, height: 300 },
17
+ * });
18
+ */
19
+ class SelectPointInteraction extends interaction_1.QtiPromptInteraction {
20
+ constructor(options) {
21
+ super(options);
22
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-select-point-interaction", {
23
+ "response-identifier": options.responseIdentifier,
24
+ label: options.label,
25
+ "min-choices": options.minChoices?.toString(),
26
+ "max-choices": options.maxChoices?.toString(),
27
+ });
28
+ this.item.ele("object", {
29
+ data: options.object.data,
30
+ type: options.object.type,
31
+ width: options.object.width?.toString(),
32
+ height: options.object.height?.toString(),
33
+ });
34
+ }
35
+ }
36
+ exports.SelectPointInteraction = SelectPointInteraction;
@@ -0,0 +1,26 @@
1
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
2
+ export type SliderInteractionOptions = QtiPromptInteractionOptions & {
3
+ lowerBound: number;
4
+ upperBound: number;
5
+ step?: number;
6
+ stepLabel?: boolean;
7
+ orientation?: "horizontal" | "vertical";
8
+ reverse?: boolean;
9
+ };
10
+ /**
11
+ * Presents a slider control for candidates to select a numeric value within a range.
12
+ * Used for questions requiring numeric input, ratings, or scale-based responses.
13
+ *
14
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.s61xcrj4qcyj
15
+ *
16
+ * @example
17
+ * const interaction = new SliderInteraction({
18
+ * responseIdentifier: "RESPONSE",
19
+ * lowerBound: 0,
20
+ * upperBound: 100,
21
+ * step: 10,
22
+ * });
23
+ */
24
+ export declare class SliderInteraction extends QtiPromptInteraction {
25
+ constructor(options: SliderInteractionOptions);
26
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SliderInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ /**
7
+ * Presents a slider control for candidates to select a numeric value within a range.
8
+ * Used for questions requiring numeric input, ratings, or scale-based responses.
9
+ *
10
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.s61xcrj4qcyj
11
+ *
12
+ * @example
13
+ * const interaction = new SliderInteraction({
14
+ * responseIdentifier: "RESPONSE",
15
+ * lowerBound: 0,
16
+ * upperBound: 100,
17
+ * step: 10,
18
+ * });
19
+ */
20
+ class SliderInteraction extends interaction_1.QtiPromptInteraction {
21
+ constructor(options) {
22
+ super(options);
23
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-slider-interaction", {
24
+ "response-identifier": options.responseIdentifier,
25
+ label: options.label,
26
+ "lower-bound": options.lowerBound.toString(),
27
+ "upper-bound": options.upperBound.toString(),
28
+ step: options.step?.toString(),
29
+ "step-label": options.stepLabel ? "true" : undefined,
30
+ orientation: options.orientation,
31
+ reverse: options.reverse ? "true" : undefined,
32
+ });
33
+ }
34
+ }
35
+ exports.SliderInteraction = SliderInteraction;
@@ -0,0 +1,25 @@
1
+ import { QtiInteraction, QtiInteractionOptions } from "./interaction";
2
+ export type TextEntryInteractionOptions = QtiInteractionOptions & {
3
+ stringIdentifier?: string;
4
+ expectedLength?: number;
5
+ placeholderText?: string;
6
+ format?: string;
7
+ patternMask?: string;
8
+ patternMaskMessage?: string;
9
+ };
10
+ /**
11
+ * Presents a text input field for candidates to enter a short text response.
12
+ * Used for fill-in-the-blank or short answer questions embedded inline.
13
+ *
14
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.5bw8rpbotrcs
15
+ *
16
+ * @example
17
+ * const interaction = new TextEntryInteraction({
18
+ * responseIdentifier: "RESPONSE",
19
+ * expectedLength: 20,
20
+ * placeholderText: "Enter your answer",
21
+ * });
22
+ */
23
+ export declare class TextEntryInteraction extends QtiInteraction {
24
+ constructor(options: TextEntryInteractionOptions);
25
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TextEntryInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ /**
7
+ * Presents a text input field for candidates to enter a short text response.
8
+ * Used for fill-in-the-blank or short answer questions embedded inline.
9
+ *
10
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.5bw8rpbotrcs
11
+ *
12
+ * @example
13
+ * const interaction = new TextEntryInteraction({
14
+ * responseIdentifier: "RESPONSE",
15
+ * expectedLength: 20,
16
+ * placeholderText: "Enter your answer",
17
+ * });
18
+ */
19
+ class TextEntryInteraction extends interaction_1.QtiInteraction {
20
+ constructor(options) {
21
+ super(options);
22
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-text-entry-interaction", {
23
+ "response-identifier": options.responseIdentifier,
24
+ label: options.label,
25
+ "string-identifier": options.stringIdentifier,
26
+ "expected-length": options.expectedLength?.toString(),
27
+ "placeholder-text": options.placeholderText,
28
+ format: options.format,
29
+ "pattern-mask": options.patternMask,
30
+ "data-patternmask-message": options.patternMaskMessage,
31
+ });
32
+ }
33
+ }
34
+ exports.TextEntryInteraction = TextEntryInteraction;
@@ -0,0 +1,19 @@
1
+ import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
2
+ export type UploadInteractionOptions = QtiPromptInteractionOptions & {
3
+ type?: string;
4
+ };
5
+ /**
6
+ * Allows candidates to upload a file as their response.
7
+ * Used for submitting documents, images, or other file-based answers.
8
+ *
9
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.qtnex0r52anx
10
+ *
11
+ * @example
12
+ * const interaction = new UploadInteraction({
13
+ * responseIdentifier: "RESPONSE",
14
+ * type: "application/pdf",
15
+ * });
16
+ */
17
+ export declare class UploadInteraction extends QtiPromptInteraction {
18
+ constructor(options: UploadInteractionOptions);
19
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UploadInteraction = void 0;
4
+ const xmlbuilder2_1 = require("xmlbuilder2");
5
+ const interaction_1 = require("./interaction");
6
+ /**
7
+ * Allows candidates to upload a file as their response.
8
+ * Used for submitting documents, images, or other file-based answers.
9
+ *
10
+ * @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.qtnex0r52anx
11
+ *
12
+ * @example
13
+ * const interaction = new UploadInteraction({
14
+ * responseIdentifier: "RESPONSE",
15
+ * type: "application/pdf",
16
+ * });
17
+ */
18
+ class UploadInteraction extends interaction_1.QtiPromptInteraction {
19
+ constructor(options) {
20
+ super(options);
21
+ this.item = (0, xmlbuilder2_1.fragment)().ele("qti-upload-interaction", {
22
+ "response-identifier": options.responseIdentifier,
23
+ label: options.label,
24
+ type: options.type,
25
+ });
26
+ }
27
+ }
28
+ exports.UploadInteraction = UploadInteraction;
@@ -0,0 +1,11 @@
1
+ import { XMLBuilder } from "xmlbuilder2/lib/interfaces";
2
+ export type NamespacedElementContent = string | {
3
+ [key: string]: NamespacedElementContent;
4
+ } | NamespacedElementContent[];
5
+ export declare abstract class QtiElement {
6
+ protected abstract getRootElement(): XMLBuilder;
7
+ buildXml(): string;
8
+ registerNamespace(prefix: string, uri: string): void;
9
+ addNamespacedElement(namespace: string, elementName: string, content: NamespacedElementContent, attributes?: Record<string, string>): void;
10
+ private appendContent;
11
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QtiElement = void 0;
4
+ class QtiElement {
5
+ buildXml() {
6
+ return this.getRootElement().end({ prettyPrint: true });
7
+ }
8
+ registerNamespace(prefix, uri) {
9
+ this.getRootElement().att(`xmlns:${prefix}`, uri);
10
+ }
11
+ addNamespacedElement(namespace, elementName, content, attributes) {
12
+ const element = this.getRootElement().ele(`${namespace}:${elementName}`, attributes);
13
+ this.appendContent(element, namespace, content);
14
+ }
15
+ appendContent(element, namespace, content) {
16
+ if (typeof content === "string") {
17
+ element.txt(content);
18
+ }
19
+ else if (Array.isArray(content)) {
20
+ for (const item of content) {
21
+ this.appendContent(element, namespace, item);
22
+ }
23
+ }
24
+ else {
25
+ for (const [key, value] of Object.entries(content)) {
26
+ const child = element.ele(`${namespace}:${key}`);
27
+ this.appendContent(child, namespace, value);
28
+ }
29
+ }
30
+ }
31
+ }
32
+ exports.QtiElement = QtiElement;
@@ -1,3 +1,6 @@
1
+ import { XMLBuilder } from "xmlbuilder2/lib/interfaces";
2
+ import { QtiInteraction } from "./interactions/interaction";
3
+ import { QtiElement } from "./qti-element";
1
4
  import { QtiTest } from "./qti-test";
2
5
  import { QtiCardinality, QtiBaseType, QtiAudience } from "./types";
3
6
  import { ImsPackage } from "../ims/ims-package";
@@ -35,7 +38,7 @@ export declare enum ResponseProcessingTemplate {
35
38
  MapResponse = "https://purl.imsglobal.org/spec/qti/v3p0/rptemplates/map_response.xml",
36
39
  MapResponsePoint = "https://purl.imsglobal.org/spec/qti/v3p0/rptemplates/map_response_point.xml"
37
40
  }
38
- export declare class QtiItem {
41
+ export declare class QtiItem extends QtiElement {
39
42
  identifier: string;
40
43
  adaptive?: boolean;
41
44
  timeDependent?: boolean;
@@ -48,14 +51,15 @@ export declare class QtiItem {
48
51
  private itemBody?;
49
52
  private responseDeclarations;
50
53
  constructor(options?: QtiItemOptions);
51
- buildXml(): string;
52
- addToPackage(pkg: ImsPackage): void;
54
+ addToPackage(pkg: ImsPackage): Promise<void>;
53
55
  addToTest(test: QtiTest): void;
54
56
  private getOrCreateItemBody;
55
57
  addItemBodyFromHtml(html: string): void;
58
+ addInteraction(interaction: QtiInteraction): void;
56
59
  addPciInteraction(interaction: PciInteraction, externalModules?: boolean): void;
57
60
  addResponseDeclaration(responseDeclaration?: ResponseDeclaration): void;
58
61
  addCorrectResponse(identifier: string, values: string[]): void;
59
62
  addResponseProcessing(template: ResponseProcessingTemplate): void;
60
63
  addOutcomeDeclaration(outcomeDeclaration?: OutcomeDeclaration): void;
64
+ protected getRootElement(): XMLBuilder;
61
65
  }