@conform-ed/qti-react 0.0.12 → 0.0.14

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 (134) hide show
  1. package/dist/capability.d.ts +17 -0
  2. package/dist/content-model.d.ts +42 -0
  3. package/dist/graphic.d.ts +23 -0
  4. package/dist/index.d.ts +14 -0
  5. package/dist/index.js +4556 -212
  6. package/dist/interactions/associate.d.ts +2 -0
  7. package/dist/interactions/choice.d.ts +2 -0
  8. package/dist/interactions/drawing.d.ts +2 -0
  9. package/dist/interactions/end-attempt.d.ts +2 -0
  10. package/dist/interactions/extended-text.d.ts +2 -0
  11. package/dist/interactions/gap-match.d.ts +2 -0
  12. package/dist/interactions/graphic.d.ts +13 -0
  13. package/dist/interactions/hottext.d.ts +2 -0
  14. package/dist/interactions/index.d.ts +18 -0
  15. package/dist/interactions/inline-choice.d.ts +2 -0
  16. package/dist/interactions/match.d.ts +2 -0
  17. package/dist/interactions/media.d.ts +2 -0
  18. package/dist/interactions/order.d.ts +2 -0
  19. package/dist/interactions/slider.d.ts +2 -0
  20. package/dist/interactions/text-entry.d.ts +2 -0
  21. package/dist/interactions/upload.d.ts +2 -0
  22. package/dist/normalized-item.d.ts +30 -0
  23. package/dist/pci/index.d.ts +6 -0
  24. package/dist/pci/interaction.d.ts +8 -0
  25. package/dist/pci/markup.d.ts +10 -0
  26. package/dist/pci/mount.d.ts +50 -0
  27. package/dist/pci/registry.d.ts +53 -0
  28. package/dist/pci/response.d.ts +11 -0
  29. package/dist/pci/skin.d.ts +12 -0
  30. package/dist/reference-skin/associate.d.ts +8 -0
  31. package/dist/reference-skin/choice.d.ts +8 -0
  32. package/dist/reference-skin/content.d.ts +6 -0
  33. package/dist/reference-skin/drawing.d.ts +9 -0
  34. package/dist/reference-skin/end-attempt.d.ts +7 -0
  35. package/dist/reference-skin/extended-text.d.ts +6 -0
  36. package/dist/reference-skin/gap-match.d.ts +8 -0
  37. package/dist/reference-skin/graphic-associate.d.ts +8 -0
  38. package/dist/reference-skin/graphic-base.d.ts +39 -0
  39. package/dist/reference-skin/graphic-gap-match.d.ts +8 -0
  40. package/dist/reference-skin/graphic-order.d.ts +8 -0
  41. package/dist/reference-skin/hotspot.d.ts +8 -0
  42. package/dist/reference-skin/hottext.d.ts +8 -0
  43. package/dist/reference-skin/index.d.ts +30 -0
  44. package/dist/reference-skin/inline-choice.d.ts +7 -0
  45. package/dist/reference-skin/match.d.ts +8 -0
  46. package/dist/reference-skin/media.d.ts +9 -0
  47. package/dist/reference-skin/order.d.ts +8 -0
  48. package/dist/reference-skin/position-object.d.ts +9 -0
  49. package/dist/reference-skin/select-point.d.ts +8 -0
  50. package/dist/reference-skin/slider.d.ts +8 -0
  51. package/dist/reference-skin/text-entry.d.ts +6 -0
  52. package/dist/reference-skin/upload.d.ts +8 -0
  53. package/dist/response-processing.d.ts +48 -0
  54. package/dist/rp/evaluate.d.ts +35 -0
  55. package/dist/rp/index.d.ts +4 -0
  56. package/dist/rp/interpreter.d.ts +15 -0
  57. package/dist/rp/template-processing.d.ts +49 -0
  58. package/dist/rp/templates.d.ts +8 -0
  59. package/dist/rp/types.d.ts +158 -0
  60. package/dist/rp/values.d.ts +27 -0
  61. package/dist/runtime.d.ts +164 -0
  62. package/dist/store.d.ts +61 -0
  63. package/dist/test/controller.d.ts +11 -0
  64. package/dist/test/index.d.ts +3 -0
  65. package/dist/test/session-store.d.ts +46 -0
  66. package/dist/test/types.d.ts +194 -0
  67. package/dist/types.d.ts +58 -0
  68. package/package.json +8 -6
  69. package/src/capability.ts +24 -0
  70. package/src/content-model.ts +104 -5
  71. package/src/graphic.ts +103 -0
  72. package/src/index.ts +139 -3
  73. package/src/interactions/associate.ts +22 -0
  74. package/src/interactions/choice.ts +2 -2
  75. package/src/interactions/drawing.ts +24 -0
  76. package/src/interactions/end-attempt.ts +19 -0
  77. package/src/interactions/extended-text.ts +21 -0
  78. package/src/interactions/gap-match.ts +22 -0
  79. package/src/interactions/graphic.ts +104 -0
  80. package/src/interactions/hottext.ts +21 -0
  81. package/src/interactions/index.ts +57 -3
  82. package/src/interactions/inline-choice.ts +2 -2
  83. package/src/interactions/match.ts +27 -0
  84. package/src/interactions/media.ts +24 -0
  85. package/src/interactions/order.ts +21 -0
  86. package/src/interactions/slider.ts +24 -0
  87. package/src/interactions/text-entry.ts +2 -2
  88. package/src/interactions/upload.ts +19 -0
  89. package/src/normalized-item.ts +563 -0
  90. package/src/pci/index.ts +22 -0
  91. package/src/pci/interaction.ts +42 -0
  92. package/src/pci/markup.ts +102 -0
  93. package/src/pci/mount.ts +134 -0
  94. package/src/pci/registry.ts +240 -0
  95. package/src/pci/response.ts +138 -0
  96. package/src/pci/skin.ts +86 -0
  97. package/src/reference-skin/associate.ts +98 -0
  98. package/src/reference-skin/choice.ts +44 -0
  99. package/src/reference-skin/content.ts +30 -0
  100. package/src/reference-skin/drawing.ts +160 -0
  101. package/src/reference-skin/end-attempt.ts +27 -0
  102. package/src/reference-skin/extended-text.ts +35 -0
  103. package/src/reference-skin/gap-match.ts +69 -0
  104. package/src/reference-skin/graphic-associate.ts +123 -0
  105. package/src/reference-skin/graphic-base.ts +142 -0
  106. package/src/reference-skin/graphic-gap-match.ts +143 -0
  107. package/src/reference-skin/graphic-order.ts +76 -0
  108. package/src/reference-skin/hotspot.ts +43 -0
  109. package/src/reference-skin/hottext.ts +42 -0
  110. package/src/reference-skin/index.ts +74 -0
  111. package/src/reference-skin/inline-choice.ts +42 -0
  112. package/src/reference-skin/match.ts +80 -0
  113. package/src/reference-skin/media.ts +74 -0
  114. package/src/reference-skin/order.ts +79 -0
  115. package/src/reference-skin/position-object.ts +84 -0
  116. package/src/reference-skin/select-point.ts +87 -0
  117. package/src/reference-skin/slider.ts +41 -0
  118. package/src/reference-skin/text-entry.ts +31 -0
  119. package/src/reference-skin/upload.ts +46 -0
  120. package/src/response-processing.ts +178 -29
  121. package/src/rp/evaluate.ts +827 -0
  122. package/src/rp/index.ts +30 -0
  123. package/src/rp/interpreter.ts +254 -0
  124. package/src/rp/template-processing.ts +290 -0
  125. package/src/rp/templates.ts +190 -0
  126. package/src/rp/types.ts +167 -0
  127. package/src/rp/values.ts +211 -0
  128. package/src/runtime.ts +476 -28
  129. package/src/store.ts +161 -5
  130. package/src/test/controller.ts +809 -0
  131. package/src/test/index.ts +25 -0
  132. package/src/test/session-store.ts +243 -0
  133. package/src/test/types.ts +203 -0
  134. package/src/types.ts +27 -1
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const associateInteraction: InteractionDescriptor<"associateInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const choiceInteraction: InteractionDescriptor<"choiceInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const drawingInteraction: InteractionDescriptor<"drawingInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const endAttemptInteraction: InteractionDescriptor<"endAttemptInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const extendedTextInteraction: InteractionDescriptor<"extendedTextInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const gapMatchInteraction: InteractionDescriptor<"gapMatchInteraction">;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The graphic interaction family: descriptors share the object (stage image) and
3
+ * hotspot (shape/coords) schemas. Coordinates are numbers in image space, normalized
4
+ * upstream from the QTI coords attribute.
5
+ */
6
+ import { type InteractionDescriptor } from "../runtime";
7
+ export declare const hotspotInteraction: InteractionDescriptor<"hotspotInteraction">;
8
+ export declare const graphicOrderInteraction: InteractionDescriptor<"graphicOrderInteraction">;
9
+ export declare const graphicAssociateInteraction: InteractionDescriptor<"graphicAssociateInteraction">;
10
+ export declare const graphicGapMatchInteraction: InteractionDescriptor<"graphicGapMatchInteraction">;
11
+ export declare const selectPointInteraction: InteractionDescriptor<"selectPointInteraction">;
12
+ /** The common single-interaction stage; multi-interaction stages fail validation. */
13
+ export declare const positionObjectStage: InteractionDescriptor<"positionObjectStage">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const hottextInteraction: InteractionDescriptor<"hottextInteraction">;
@@ -0,0 +1,18 @@
1
+ import type { InteractionDescriptor } from "../runtime";
2
+ export { associateInteraction } from "./associate";
3
+ export { choiceInteraction } from "./choice";
4
+ export { drawingInteraction } from "./drawing";
5
+ export { endAttemptInteraction } from "./end-attempt";
6
+ export { extendedTextInteraction } from "./extended-text";
7
+ export { gapMatchInteraction } from "./gap-match";
8
+ export { graphicAssociateInteraction, graphicGapMatchInteraction, graphicOrderInteraction, hotspotInteraction, positionObjectStage, selectPointInteraction, } from "./graphic";
9
+ export { hottextInteraction } from "./hottext";
10
+ export { inlineChoiceInteraction } from "./inline-choice";
11
+ export { matchInteraction } from "./match";
12
+ export { mediaInteraction } from "./media";
13
+ export { orderInteraction } from "./order";
14
+ export { sliderInteraction } from "./slider";
15
+ export { textEntryInteraction } from "./text-entry";
16
+ export { uploadInteraction } from "./upload";
17
+ /** The interaction set conform-ed ships; consumers assemble these plus their extensions. */
18
+ export declare const qtiCoreInteractions: readonly InteractionDescriptor[];
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const inlineChoiceInteraction: InteractionDescriptor<"inlineChoiceInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const matchInteraction: InteractionDescriptor<"matchInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const mediaInteraction: InteractionDescriptor<"mediaInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const orderInteraction: InteractionDescriptor<"orderInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const sliderInteraction: InteractionDescriptor<"sliderInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const textEntryInteraction: InteractionDescriptor<"textEntryInteraction">;
@@ -0,0 +1,2 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ export declare const uploadInteraction: InteractionDescriptor<"uploadInteraction">;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Adapter from `@conform-ed/qti-xml`'s normalized assessment-item JSON (the contracts
3
+ * vocabulary) to the runtime's `AssessmentItemView`. Pure data reshaping with no
4
+ * qti-xml dependency. The contracts shapes and the runtime's descriptor shapes
5
+ * deliberately differ in places; this seam is where they reconcile:
6
+ *
7
+ * - bare-string text fragments become `{ kind: "text", value }` nodes
8
+ * - `hotTextInteraction`/`hotText` rename to the runtime's `hottextInteraction`/`hottext`
9
+ * - graphic stages: contract `image` xml nodes become `{ data, width, height, type }`
10
+ * objects, and `coords` strings become number arrays (also in `areaMapping`)
11
+ * - `gapChoices` split into the runtime's `gapTexts` (gapMatch) / `gapImgs` (graphic)
12
+ * - media/upload/positionObjectStage flatten to the descriptor fields
13
+ * - processing trees: `children` → `expressions`, `actions` → `rules`,
14
+ * `responseElseIf`/`templateElseIf` pluralize
15
+ *
16
+ * Used by the corpus delivery meter (ADR-0002) and by any consumer ingesting
17
+ * normalized XML.
18
+ */
19
+ import type { AssessmentItemView } from "./runtime";
20
+ import type { AssessmentTestView } from "./test";
21
+ /**
22
+ * Reshape a normalized QTI document (the `normalizedDocument` from qti-xml validation)
23
+ * into an `AssessmentItemView`, or null when it is not an assessment item.
24
+ */
25
+ export declare function assessmentItemViewFromNormalized(document: unknown): AssessmentItemView | null;
26
+ /**
27
+ * Reshape a normalized QTI document into the Test Controller's `AssessmentTestView`,
28
+ * or null when it is not an assessment test.
29
+ */
30
+ export declare function assessmentTestViewFromNormalized(document: unknown): AssessmentTestView | null;
@@ -0,0 +1,6 @@
1
+ export { pciResponseToValue, valueToPciResponse } from "./response";
2
+ export { createPciModuleRegistry, type PciConfiguration, type PciInstance, type PciModule, type PciModuleRegistry, type PciModuleRegistryOptions, } from "./registry";
3
+ export { serializePciMarkup } from "./markup";
4
+ export { mountPci, type PciInteractionNode, type PciMountHandle, type PciMountOptions } from "./mount";
5
+ export { portableCustomInteraction } from "./interaction";
6
+ export { createPciSkin, type PciSkinOptions } from "./skin";
@@ -0,0 +1,8 @@
1
+ import { type InteractionDescriptor } from "../runtime";
2
+ /**
3
+ * The PCI interaction descriptor. Deliberately NOT part of `qtiCoreInteractions`:
4
+ * delivering a PCI executes item-supplied JavaScript, so consumers opt in by adding
5
+ * this descriptor plus a skin from `createPciSkin` (ADR-0003 — the capability gate
6
+ * keeps PCI items undeliverable until then).
7
+ */
8
+ export declare const portableCustomInteraction: InteractionDescriptor<"portableCustomInteraction">;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * PCI markup serialization: `qti-interaction-markup` content back to an HTML string
3
+ * for injection into the host container. PCI markup is module-owned — the module
4
+ * queries and mutates it directly — so unlike flow content it is not constrained to
5
+ * the content-model element allowlist. The serializer still strips what must never
6
+ * reach the DOM statically: event-handler attributes, script-scheme URLs, and
7
+ * `<script>` elements (modules bring behaviour through the registry, not markup).
8
+ */
9
+ import type { BodyNode } from "../runtime";
10
+ export declare function serializePciMarkup(nodes: ReadonlyArray<BodyNode | string> | undefined): string;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The PCI mount lifecycle, framework-free (the React skin is a thin wrapper): resolve
3
+ * the module through the registry (declared interaction modules with primary →
4
+ * fallback paths, then the bare `module` name), inject the serialized markup, call
5
+ * `getInstance(dom, configuration, state)`, and hand back a handle the host uses to
6
+ * collect the response at submit time and to tear the instance down.
7
+ */
8
+ import type { BodyNode } from "../runtime";
9
+ import type { ResponseDeclarationView, ResponseValue } from "../types";
10
+ import type { PciInstance, PciModuleRegistry } from "./registry";
11
+ /** The adapter's shape for a `portableCustomInteraction` body node. */
12
+ export interface PciInteractionNode {
13
+ readonly kind: "portableCustomInteraction";
14
+ readonly responseIdentifier: string;
15
+ readonly customInteractionTypeIdentifier: string;
16
+ readonly module?: string;
17
+ readonly class?: readonly string[];
18
+ readonly properties?: Readonly<Record<string, string>>;
19
+ readonly interactionMarkup?: {
20
+ readonly content?: ReadonlyArray<BodyNode | string>;
21
+ };
22
+ readonly interactionModules?: {
23
+ readonly primaryConfiguration?: string;
24
+ readonly modules?: ReadonlyArray<{
25
+ readonly id: string;
26
+ readonly primaryPath?: string;
27
+ readonly fallbackPath?: string;
28
+ }>;
29
+ };
30
+ }
31
+ export interface PciMountOptions {
32
+ readonly container: Element;
33
+ readonly node: PciInteractionNode;
34
+ readonly registry: PciModuleRegistry;
35
+ /** The bound response variable's declaration and current value (for `boundTo`). */
36
+ readonly declaration?: ResponseDeclarationView;
37
+ readonly boundValue?: ResponseValue;
38
+ /** A state string from a previous instance's getState() (session restore). */
39
+ readonly state?: string;
40
+ /** PCI `ondone`: the instance finished on its own and reports its response. */
41
+ readonly ondone?: (value: ResponseValue, state?: string) => void;
42
+ }
43
+ export interface PciMountHandle {
44
+ readonly instance: PciInstance;
45
+ /** The instance's current response as a runtime ResponseValue. */
46
+ readonly collectResponse: () => ResponseValue | undefined;
47
+ readonly getState: () => string | undefined;
48
+ readonly unmount: () => void;
49
+ }
50
+ export declare function mountPci(options: PciMountOptions): Promise<PciMountHandle>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The PCI Module Registry: PCI v1 modules are AMD (`define([deps], factory)`), so the
3
+ * registry provides a minimal AMD surface — source evaluation with a scoped `define`,
4
+ * dependency resolution among registered modules, the `qtiCustomInteractionContext`
5
+ * bridge (`register` keyed by typeIdentifier), and URL loading with primary → fallback
6
+ * candidates. PCI is a trust boundary: evaluating a module executes item-supplied
7
+ * code, which is why PCI support is opt-in and never part of `qtiCoreInteractions`.
8
+ */
9
+ /** The configuration handed to `getInstance` (IMS PCI v1). */
10
+ export interface PciConfiguration {
11
+ readonly properties: Readonly<Record<string, string>>;
12
+ readonly responseIdentifier?: string;
13
+ /** The bound response variable's current value in PCI JSON form. */
14
+ readonly boundTo?: Readonly<Record<string, unknown>>;
15
+ readonly status?: string;
16
+ readonly onready?: (instance: PciInstance, state?: string) => void;
17
+ readonly ondone?: (instance: PciInstance, response: unknown, state?: string, status?: string) => void;
18
+ }
19
+ export interface PciInstance {
20
+ readonly typeIdentifier?: string;
21
+ getResponse(): unknown;
22
+ getState?(): string;
23
+ /** Engine-invoked before the instance is unloaded (cleanup hook). */
24
+ oncompleted?(): void;
25
+ }
26
+ export interface PciModule {
27
+ readonly typeIdentifier?: string;
28
+ getInstance(dom: Element, configuration: PciConfiguration, state: string | undefined): PciInstance | undefined;
29
+ }
30
+ export interface PciModuleRegistryOptions {
31
+ /** Base for relative module paths (typically the item package root URL). */
32
+ readonly baseUrl?: string;
33
+ /** Module id → path overrides (a parsed `module_resolution.js` paths map). */
34
+ readonly paths?: Readonly<Record<string, string>>;
35
+ /** Source fetcher for URL loading; defaults to global fetch. */
36
+ readonly fetchText?: (url: string) => Promise<string>;
37
+ }
38
+ export interface PciModuleRegistry {
39
+ /** Evaluate AMD source text; its `define` registers under the given module id. */
40
+ readonly evaluate: (source: string, context: {
41
+ readonly id: string;
42
+ }) => void;
43
+ /** Register a prebuilt module directly (bundled PCIs, tests). */
44
+ readonly registerModule: (id: string, module: PciModule) => void;
45
+ /** Resolve by module id or by PCI typeIdentifier; undefined when unknown. */
46
+ readonly resolve: (id: string) => PciModule | undefined;
47
+ /**
48
+ * Load a module from candidate paths in order (primary → fallback), falling back to
49
+ * the registry's `paths` map when no candidates are given.
50
+ */
51
+ readonly load: (id: string, candidates: readonly string[]) => Promise<PciModule>;
52
+ }
53
+ export declare function createPciModuleRegistry(options?: PciModuleRegistryOptions): PciModuleRegistry;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * PCI JSON ↔ ResponseValue conversion (IMS PCI v1 "JSON representation of variable
3
+ * values"). PCI instances exchange `{ base: { integer: 3 } }` / `{ list: ... }` /
4
+ * `{ record: [{ name, base }] }` shapes; the attempt store speaks string / string[] /
5
+ * record-object / null. Record fields keep their runtime type so `fieldValue` in
6
+ * response processing sees properly typed members.
7
+ */
8
+ import type { ResponseDeclarationView, ResponseValue } from "../types";
9
+ export declare function pciResponseToValue(json: unknown): ResponseValue;
10
+ /** The current response in PCI JSON form — fed to `getInstance` as `boundTo`. */
11
+ export declare function valueToPciResponse(value: ResponseValue, declaration: ResponseDeclarationView): unknown;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The PCI host skin: a thin React wrapper over `mountPci`. It renders the container,
3
+ * mounts the module instance after first paint, registers a submit-time response
4
+ * collector with the attempt store, and tears the instance down on unmount. Module
5
+ * failures render an explicit error note — never a silent drop (ADR-0003).
6
+ */
7
+ import type { InteractionSkin } from "../runtime";
8
+ import type { PciModuleRegistry } from "./registry";
9
+ export interface PciSkinOptions {
10
+ readonly registry: PciModuleRegistry;
11
+ }
12
+ export declare function createPciSkin(options: PciSkinOptions): InteractionSkin;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `associateInteraction` (ADR-0001): a pair builder — two selects
3
+ * over the same choice set, an "Add pair" button, and a removable list of the pairs
4
+ * built so far. Pairs are unordered (`pair` baseType); scoring handles reversal.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function AssociateReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `choiceInteraction` (ADR-0001): unstyled, semantic, a11y-correct.
3
+ * Native `<button>` elements carry the option prop-getters so Space/Enter activation is
4
+ * free; all visual state is exposed as data attributes for downstream styling.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function ChoiceReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Plain-text extraction for places where the DOM only accepts text (e.g. `<option>`
3
+ * children). Walks a BodyNode fragment and concatenates its text values.
4
+ */
5
+ import type { BodyNode } from "../runtime";
6
+ export declare function textOf(nodes: readonly BodyNode[] | undefined): string;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Reference Skin for `drawingInteraction` (ADR-0001): a canvas drawing surface over
3
+ * the stage image. The candidate draws freehand strokes with the pointer; the result
4
+ * is captured as a PNG data URL into the `file` response (the upload convention).
5
+ * Items using drawing are typically scored externally, not by client RP.
6
+ */
7
+ import { type ReactNode } from "react";
8
+ import type { InteractionRenderProps } from "../runtime";
9
+ export declare function DrawingReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Reference Skin for `endAttemptInteraction` (ADR-0001): a titled button that sets its
3
+ * boolean response true and ends the current attempt (hints, give-up, adaptive moves).
4
+ */
5
+ import { type ReactNode } from "react";
6
+ import type { InteractionRenderProps } from "../runtime";
7
+ export declare function EndAttemptReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Reference Skin for `extendedTextInteraction` (ADR-0001): a controlled textarea.
3
+ */
4
+ import { type ReactNode } from "react";
5
+ import type { InteractionRenderProps } from "../runtime";
6
+ export declare function ExtendedTextReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `gapMatchInteraction` (ADR-0001): the interaction's flow content
3
+ * renders through the core walk with a `gap` override — each gap becomes a select over
4
+ * the gap texts. Choosing a gap text records the directedPair "GAPTEXT GAP".
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function GapMatchReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `graphicAssociateInteraction` (ADR-0001): click two hotspots to
3
+ * connect them; connections draw as lines and list below with remove buttons. Pairs
4
+ * are unordered (`pair` baseType).
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function GraphicAssociateReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared scaffolding for the graphic Reference Skins (ADR-0001): a stage (the image
3
+ * with an SVG overlay in image coordinates) plus QTI shape → SVG element mapping.
4
+ */
5
+ import { type ReactNode, type SVGProps } from "react";
6
+ import type { Point } from "../graphic";
7
+ export interface ObjectView {
8
+ data: string;
9
+ width?: number;
10
+ height?: number;
11
+ type?: string;
12
+ }
13
+ export interface HotspotView {
14
+ identifier: string;
15
+ shape: string;
16
+ coords: readonly number[];
17
+ matchMax?: number;
18
+ }
19
+ /** The geometric center of a shape, for badges, lines, and placed images. */
20
+ export declare function shapeCenter(shape: string, coords: readonly number[]): Point;
21
+ /** Extra props a shape may carry, including data-* attributes. */
22
+ export type ShapeProps = SVGProps<SVGElement> & {
23
+ [dataAttribute: `data-${string}`]: string | number | boolean;
24
+ };
25
+ /** Map a QTI (shape, coords) to an SVG element with the given extra props. */
26
+ export declare function shapeElement(shape: string, coords: readonly number[], key: string, props: ShapeProps): ReactNode;
27
+ export interface GraphicStageProps {
28
+ object: ObjectView;
29
+ resolveAsset: (href: string) => string;
30
+ interaction: string;
31
+ status: string;
32
+ /** Stage click in image coordinates (from the SVG overlay). */
33
+ onStageClick?: (point: Point) => void;
34
+ prompt?: ReactNode;
35
+ overlay?: ReactNode;
36
+ after?: ReactNode;
37
+ }
38
+ /** The image + coordinate-space SVG overlay every graphic interaction shares. */
39
+ export declare function GraphicStage(props: GraphicStageProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `graphicGapMatchInteraction` (ADR-0001): pick a gap image from
3
+ * the tray, then click a hotspot to place it — no drag-and-drop. Placed images draw
4
+ * at the hotspot center; responses are directedPairs gapImg→hotspot.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function GraphicGapMatchReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `graphicOrderInteraction` (ADR-0001): click hotspots in sequence;
3
+ * each selected hotspot shows its position badge. Clicking a selected hotspot removes
4
+ * it (and renumbers the rest).
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function GraphicOrderReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `hotspotInteraction` (ADR-0001): SVG hotspot shapes over the
3
+ * stage image, wired through the option prop-getters (selection semantics identical
4
+ * to choiceInteraction).
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function HotspotReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `hottextInteraction` (ADR-0001): the interaction's flow content is
3
+ * rendered through the core walk with a `hottext` override, so selectable spans nested
4
+ * anywhere in the prose become toggle buttons wired through the option prop-getters.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function HottextReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The Reference Skin (ADR-0001): the unstyled, semantic-HTML, a11y-correct Skin set
3
+ * conform-ed ships so every interaction can be exercised, demoed, and conformance-
4
+ * tested without a downstream product. Deliberately not a product UI: no styling
5
+ * beyond data attributes (`data-qti-interaction`, `data-status`) as styling hooks.
6
+ */
7
+ import type { SkinRegistry } from "../runtime";
8
+ export { textOf } from "./content";
9
+ export { AssociateReferenceSkin } from "./associate";
10
+ export { ChoiceReferenceSkin } from "./choice";
11
+ export { DrawingReferenceSkin } from "./drawing";
12
+ export { EndAttemptReferenceSkin } from "./end-attempt";
13
+ export { ExtendedTextReferenceSkin } from "./extended-text";
14
+ export { GapMatchReferenceSkin } from "./gap-match";
15
+ export { GraphicAssociateReferenceSkin } from "./graphic-associate";
16
+ export { GraphicGapMatchReferenceSkin } from "./graphic-gap-match";
17
+ export { GraphicOrderReferenceSkin } from "./graphic-order";
18
+ export { GraphicStage, shapeCenter, shapeElement } from "./graphic-base";
19
+ export { HotspotReferenceSkin } from "./hotspot";
20
+ export { PositionObjectReferenceSkin } from "./position-object";
21
+ export { SelectPointReferenceSkin } from "./select-point";
22
+ export { HottextReferenceSkin } from "./hottext";
23
+ export { InlineChoiceReferenceSkin } from "./inline-choice";
24
+ export { MatchReferenceSkin } from "./match";
25
+ export { MediaReferenceSkin } from "./media";
26
+ export { OrderReferenceSkin } from "./order";
27
+ export { SliderReferenceSkin } from "./slider";
28
+ export { TextEntryReferenceSkin } from "./text-entry";
29
+ export { UploadReferenceSkin } from "./upload";
30
+ export declare const referenceSkin: SkinRegistry;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Reference Skin for `inlineChoiceInteraction` (ADR-0001): a controlled native select.
3
+ * Option labels must be text, so choice content goes through plain-text extraction.
4
+ */
5
+ import { type ReactNode } from "react";
6
+ import type { InteractionRenderProps } from "../runtime";
7
+ export declare function InlineChoiceReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `matchInteraction` (ADR-0001): a table grid — rows are the first
3
+ * match set, columns the second; each cell is a checkbox toggling the directedPair
4
+ * "ROW COL". Conservative and screen-reader friendly; no drag-and-drop.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function MatchReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Reference Skin for `mediaInteraction` (ADR-0001): renders the wrapped audio/video
3
+ * element itself (skin-owned, so it can count plays), resolving the source through the
4
+ * runtime's Asset Resolver. The response is the play count as an integer string;
5
+ * playback is blocked once `maxPlays` is reached.
6
+ */
7
+ import { type ReactNode } from "react";
8
+ import type { InteractionRenderProps } from "../runtime";
9
+ export declare function MediaReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `orderInteraction` (ADR-0001): an ordered list with per-item
3
+ * move-up/move-down buttons — keyboard-accessible reordering without drag-and-drop.
4
+ * The displayed order is the response; the first move answers with the full order.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function OrderReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Reference Skin for `positionObjectStage` (ADR-0001): click the stage to place the
3
+ * movable object image, centered on the click point. The view models the common
4
+ * single-interaction stage (one movable object per stage); multi-interaction stages
5
+ * fail descriptor validation and surface through the capability gate.
6
+ */
7
+ import { type ReactNode } from "react";
8
+ import type { InteractionRenderProps } from "../runtime";
9
+ export declare function PositionObjectReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `selectPointInteraction` (ADR-0001): click the stage to record a
3
+ * point (image coordinates). With maxChoices 1 a new click replaces the point;
4
+ * otherwise clicks append until maxChoices is reached.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function SelectPointReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `sliderInteraction` (ADR-0001): a controlled native range input
3
+ * with a visible current value. Responses are stored as decimal strings; numeric
4
+ * baseTypes compare numerically in scoring.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function SliderReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Reference Skin for `textEntryInteraction` (ADR-0001): a controlled native text input.
3
+ */
4
+ import { type ReactNode } from "react";
5
+ import type { InteractionRenderProps } from "../runtime";
6
+ export declare function TextEntryReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Reference Skin for `uploadInteraction` (ADR-0001): a native file input. The selected
3
+ * file is stored as a data URL string (QTI `file` base type carries the content); items
4
+ * using upload are typically scored externally, not by client response processing.
5
+ */
6
+ import { type ReactNode } from "react";
7
+ import type { InteractionRenderProps } from "../runtime";
8
+ export declare function UploadReferenceSkin(props: InteractionRenderProps): ReactNode;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Standard-template scoring helpers, spec-strict by default (ADR-0004). `match_correct`
3
+ * is an exact match and mapping entries default to caseSensitive=true, per spec. The
4
+ * optional `normalize` parameter is the Response Normalization hook: a consumer-
5
+ * configured transform applied to both sides of string comparisons (off by default,
6
+ * always off in conformance runs). The RP interpreter (`src/rp/`) reuses these for its
7
+ * `mapResponse` operator; `scoreResponse` also backs the per-interaction feedback
8
+ * chrome in the runtime. Pure functions: deterministic given (declaration, response),
9
+ * so scoring is replayable and runs fully offline in the headless core.
10
+ */
11
+ import type { ResponseNormalization } from "./rp/types";
12
+ import type { ResponseDeclarationView, ResponseValue, ScoreResult } from "./types";
13
+ /**
14
+ * Lowercase + strip combining diacritics. Exported as a ready-made Response
15
+ * Normalization for language-learning leniency ("cafe" ≈ "Café") — a documented
16
+ * deviation a consumer must opt into.
17
+ */
18
+ export declare function foldString(value: string): string;
19
+ /**
20
+ * `match_correct`: true when the response exactly matches `correctResponse`, respecting
21
+ * cardinality and baseType. Spec-strict: no case or diacritic folding unless the
22
+ * consumer passes a Response Normalization. Returns false when no correctResponse
23
+ * exists.
24
+ */
25
+ export declare function matchCorrect(declaration: ResponseDeclarationView, response: ResponseValue, normalize?: ResponseNormalization): boolean;
26
+ /**
27
+ * `map_response`: sum the mapped values of the response's members, each member mapped at
28
+ * most once. Per spec, entries default to caseSensitive=true; `caseSensitive: false`
29
+ * lowercases both sides. A Response Normalization, when configured, applies on top for
30
+ * string base types. Applies the mapping's `defaultValue` to unmatched members and
31
+ * clamps to [lowerBound, upperBound]. Returns 0 when no mapping exists.
32
+ */
33
+ export declare function mapResponse(declaration: ResponseDeclarationView, response: ResponseValue, normalize?: ResponseNormalization): number;
34
+ /**
35
+ * `map_response_point`: sum the mapped values of the areas hit by the response's point
36
+ * members. Per spec each area counts at most once regardless of how many points land in
37
+ * it; points hitting no area add the mapping's `defaultValue`. Clamps to
38
+ * [lowerBound, upperBound]. Returns 0 when no areaMapping exists.
39
+ */
40
+ export declare function mapResponsePoint(declaration: ResponseDeclarationView, response: ResponseValue): number;
41
+ /**
42
+ * Apply the appropriate standard template: `map_response_point` when an areaMapping is
43
+ * declared, `map_response` when a mapping is declared, otherwise `match_correct`. `maxScore` is the mapping upper bound (or the sum of
44
+ * positive mapped values) for mapped items, else 1 for match_correct. This heuristic
45
+ * backs the per-interaction feedback chrome; item outcomes of record come from the RP
46
+ * interpreter when the item declares `responseProcessing`.
47
+ */
48
+ export declare function scoreResponse(declaration: ResponseDeclarationView, response: ResponseValue, normalize?: ResponseNormalization): ScoreResult;