@longsightgroup/qti3-player 0.3.0 → 0.5.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 (92) hide show
  1. package/README.md +153 -13
  2. package/dist/index.d.ts +13 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +6 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/player-adapter.d.ts +62 -0
  7. package/dist/player-adapter.d.ts.map +1 -0
  8. package/dist/player-adapter.js +119 -0
  9. package/dist/player-adapter.js.map +1 -0
  10. package/dist/player-dev.d.ts +4 -0
  11. package/dist/player-dev.d.ts.map +1 -0
  12. package/dist/player-dev.js +14 -0
  13. package/dist/player-dev.js.map +1 -0
  14. package/dist/player-element.d.ts +14 -1
  15. package/dist/player-element.d.ts.map +1 -1
  16. package/dist/player-element.js +57 -5
  17. package/dist/player-element.js.map +1 -1
  18. package/dist/player-locale.d.ts +8 -3
  19. package/dist/player-locale.d.ts.map +1 -1
  20. package/dist/player-locale.js +16 -175
  21. package/dist/player-locale.js.map +1 -1
  22. package/dist/player-message-catalog-default.d.ts +4 -0
  23. package/dist/player-message-catalog-default.d.ts.map +1 -0
  24. package/dist/player-message-catalog-default.js +118 -0
  25. package/dist/player-message-catalog-default.js.map +1 -0
  26. package/dist/player-message-catalog-validate.d.ts +31 -0
  27. package/dist/player-message-catalog-validate.d.ts.map +1 -0
  28. package/dist/player-message-catalog-validate.js +327 -0
  29. package/dist/player-message-catalog-validate.js.map +1 -0
  30. package/dist/player-message-catalog.d.ts +18 -0
  31. package/dist/player-message-catalog.d.ts.map +1 -0
  32. package/dist/player-message-catalog.js +40 -0
  33. package/dist/player-message-catalog.js.map +1 -0
  34. package/dist/player-message-keys.d.ts +6 -0
  35. package/dist/player-message-keys.d.ts.map +1 -0
  36. package/dist/player-message-keys.js +7 -0
  37. package/dist/player-message-keys.js.map +1 -0
  38. package/dist/player-message-manifest.d.ts +272 -0
  39. package/dist/player-message-manifest.d.ts.map +1 -0
  40. package/dist/player-message-manifest.js +83 -0
  41. package/dist/player-message-manifest.js.map +1 -0
  42. package/dist/player-message-overrides.d.ts +3 -0
  43. package/dist/player-message-overrides.d.ts.map +1 -0
  44. package/dist/player-message-overrides.js +28 -0
  45. package/dist/player-message-overrides.js.map +1 -0
  46. package/dist/player-message-resolver.d.ts +31 -0
  47. package/dist/player-message-resolver.d.ts.map +1 -0
  48. package/dist/player-message-resolver.js +110 -0
  49. package/dist/player-message-resolver.js.map +1 -0
  50. package/dist/player-messages.d.ts +0 -38
  51. package/dist/player-messages.d.ts.map +1 -1
  52. package/dist/player-types.d.ts +12 -2
  53. package/dist/player-types.d.ts.map +1 -1
  54. package/package.json +3 -3
  55. package/src/controls/remove-button.ts +8 -5
  56. package/src/index.ts +61 -5
  57. package/src/interactions/choice-interaction.ts +6 -2
  58. package/src/interactions/drawing-interaction.ts +14 -9
  59. package/src/interactions/end-attempt-interaction.ts +3 -3
  60. package/src/interactions/gap-match-interaction.ts +32 -13
  61. package/src/interactions/graphic-associate-interaction.ts +15 -10
  62. package/src/interactions/hotspot-interaction.ts +10 -6
  63. package/src/interactions/inline-choice-interaction.ts +4 -4
  64. package/src/interactions/interaction-registry.ts +12 -12
  65. package/src/interactions/match-interaction.ts +9 -6
  66. package/src/interactions/pair-interaction.ts +22 -14
  67. package/src/interactions/position-object-interaction.ts +22 -13
  68. package/src/interactions/select-point-interaction.ts +25 -13
  69. package/src/interactions/shared.ts +21 -4
  70. package/src/interactions/text-interaction.ts +14 -4
  71. package/src/interactions/upload-interaction.ts +6 -3
  72. package/src/player/content-state.ts +12 -1
  73. package/src/player/interaction-render.ts +4 -4
  74. package/src/player-adapter.ts +253 -0
  75. package/src/player-dev.ts +14 -0
  76. package/src/player-element.ts +78 -8
  77. package/src/player-locale.ts +28 -199
  78. package/src/player-message-catalog-default.ts +119 -0
  79. package/src/player-message-catalog-validate.ts +425 -0
  80. package/src/player-message-catalog.ts +72 -0
  81. package/src/player-message-keys.ts +12 -0
  82. package/src/player-message-manifest.ts +103 -0
  83. package/src/player-message-overrides.ts +38 -0
  84. package/src/player-message-resolver.ts +205 -0
  85. package/src/player-messages.ts +0 -30
  86. package/src/player-types.ts +15 -4
  87. package/src/reorder/a11y.ts +22 -7
  88. package/src/reorder/graphic-order-interaction.ts +23 -16
  89. package/src/reorder/list-controls.ts +8 -6
  90. package/src/reorder/order-interaction.ts +7 -5
  91. package/src/styles/base-styles.ts +20 -5
  92. package/src/styles/graphic-styles.ts +0 -6
package/README.md CHANGED
@@ -39,25 +39,133 @@ player?.addEventListener("qti-statechange", (event) => {
39
39
  });
40
40
  ```
41
41
 
42
- ## Player Chrome Messages
42
+ ## Scoring Trust Boundary
43
43
 
44
- The player keeps authored QTI content language separate from player chrome such as
45
- remove buttons. Chrome language defaults to the player `languageOfInterface` property,
46
- the `language-of-interface` attribute, browser language, document language, then
47
- English. Hosts can override it when delivery settings require a fixed interface language.
44
+ The player can score attempts locally through `@longsightgroup/qti3-core`, but browser
45
+ scoring is a convenience for validation, feedback, previews, and response snapshots.
46
+ High-stakes assessment systems must treat browser outcomes as untrusted and recompute
47
+ scores server-side from authoritative QTI XML and trusted response variables.
48
48
 
49
- Built-in catalogs are currently available for English, Spanish (`es-MX`, `es-ES`),
50
- Swedish (`sv-SE`), German (`de-DE`), Portuguese (`pt-BR`, `pt-PT`), and French
51
- (`fr-FR`, `fr-CA`).
49
+ ## Player Chrome Messages (host-owned i18n)
50
+
51
+ The player keeps **authored QTI content** (prompts, choice labels, `title` on
52
+ end-attempt) separate from **player chrome** (remove buttons, aria labels, live-region
53
+ status, gap labels).
54
+
55
+ Only **English** ships in the package. `language-of-interface="sv-SE"` does **not**
56
+ change chrome by itself; the host loads a locale file.
57
+
58
+ ### Locale files (recommended)
59
+
60
+ Harbor or an LMS maintains JSON (or ICU/Fluent exported to JSON) with the shape
61
+ `PlayerMessageCatalog`: a flat `strings` map, optional `interactionTypes`, and
62
+ `directions`. Copy `defaultPlayerMessageCatalog` from the package as the template; omit
63
+ keys you do not need to translate (missing keys fall back to English).
52
64
 
53
65
  ```ts
54
- player.languageOfInterface = "es-MX";
55
- player.messages = {
56
- remove: () => "Eliminar",
57
- removePair: ({ label }) => `Eliminar ${label}`,
58
- };
66
+ import type { PlayerMessageCatalog } from "@longsightgroup/qti3-player";
67
+
68
+ const sv = (await fetch("/locales/player/sv-SE.json")).json() as PlayerMessageCatalog;
69
+
70
+ player.languageOfInterface = "sv-SE";
71
+ player.messageCatalog = sv;
72
+ await player.loadXml(xml);
59
73
  ```
60
74
 
75
+ Example entries:
76
+
77
+ ```json
78
+ {
79
+ "locale": "sv-SE",
80
+ "strings": {
81
+ "remove": "Ta bort",
82
+ "removePair": "Ta bort {label}",
83
+ "associationPairLabel": "{source} med {target}",
84
+ "extendedTextCounter": "{characters} tecken, {words} ord",
85
+ "associationsMade.one": "{count} koppling skapad.",
86
+ "associationsMade.other": "{count} kopplingar skapade."
87
+ },
88
+ "interactionTypes": {
89
+ "graphicOrder": "Grafisk ordning"
90
+ },
91
+ "directions": { "up": "upp", "down": "ner", "left": "vänster", "right": "höger" }
92
+ }
93
+ ```
94
+
95
+ Templates use `{placeholder}` names. For English-style singular/plural, use
96
+ `messageKey.one` and `messageKey.other` (for example `associationsMade.one`). Languages
97
+ that do not inflect by count can use a single key (for example one `extendedTextCounter`
98
+ string for all counts).
99
+
100
+ Validate locale files in CI with `validatePlayerMessageCatalog()` — pass `JSON.parse` output
101
+ directly (`unknown`). Shape errors (non-object root, missing `strings`, numeric templates, bad
102
+ `directions` / `interactionTypes`) return diagnostics instead of throwing:
103
+
104
+ ```ts
105
+ import { validatePlayerMessageCatalog } from "@longsightgroup/qti3-player";
106
+
107
+ const raw = JSON.parse(await readFile("locales/player/sv-SE.json", "utf8"));
108
+ const result = validatePlayerMessageCatalog(raw);
109
+ if (!result.valid) {
110
+ for (const issue of result.diagnostics) {
111
+ console.error(`${issue.code} ${issue.key}: ${issue.message}`);
112
+ }
113
+ process.exit(1);
114
+ }
115
+ ```
116
+
117
+ Use `requireAllKeys: true` only for complete locale files forked from `defaultPlayerMessageCatalog`.
118
+ Partial delivery catalogs should omit that flag.
119
+
120
+ Reference exports:
121
+
122
+ - `PLAYER_MESSAGE_KEYS` — message ids from `PLAYER_MESSAGE_MANIFEST`
123
+ - `PLAYER_MESSAGE_STRING_KEYS` — all keys in `defaultPlayerMessageCatalog.strings`
124
+ - `defaultPlayerMessageCatalog` — English template to fork
125
+ - `allowedCatalogPlaceholders(entry)` — placeholders a template may use
126
+ - `requiredCatalogPlaceholders(catalogKey)` — placeholders required for that key per English default
127
+ - `createPlayerMessageResolver(catalog)` — canonical key-driven runtime API
128
+ - `PlayerMessageParams<K>` — typed params for `message(key, params)`
129
+
130
+ Resolver kinds in the manifest (hosts only edit `strings`; behavior is fixed):
131
+
132
+ | Resolver | Meaning |
133
+ | --------------------- | ---------------------------------------------------- |
134
+ | `plain` | Static string |
135
+ | `template` | `{placeholder}` interpolation from params |
136
+ | `plural` | Uses `key.one` / `key.other` when `count` is present |
137
+ | `typeLabel` | Interaction type short name from `interactionTypes` |
138
+ | `typeTemplate` | Template with `{typeName}` derived from `type` |
139
+ | `directionTemplate` | Template with localized `{direction}` |
140
+ | `extendedTextCounter` | `{characters}`, `{words}`, and unit plural helpers |
141
+
142
+ ### Runtime API
143
+
144
+ Chrome resolves to a key-driven `PlayerMessageResolver`:
145
+
146
+ ```ts
147
+ const messages = resolvePlayerMessages(locale, {}, catalog);
148
+
149
+ messages.message("remove");
150
+ messages.message("removePair", { label: pairLabel });
151
+ messages.message("associationsMade", { count: 2 });
152
+ ```
153
+
154
+ `createPlayerMessageResolver(catalog)` builds the same resolver directly from a locale file.
155
+
156
+ ### Per-message overrides
157
+
158
+ `player.messages` accepts `QtiPlayerMessageOverrides` — each key uses the same param types as
159
+ `message(key, params)` (for example `removePair: ({ label }) => ...`). Use only when a catalog
160
+ entry is not enough; composed strings (for example `removePair` using `associationPairLabel`
161
+ text) are easy to break.
162
+
163
+ ### Item language vs interface language
164
+
165
+ Do not copy item `xml:lang` onto `<qti-assessment-item-player lang="...">` unless you
166
+ intentionally want the player element's `lang` attribute to influence
167
+ `defaultPlayerLocale()`. Prefer `player.messageCatalog` for UI chrome.
168
+
61
169
  ## Portable Custom Interactions
62
170
 
63
171
  For `qti-portable-custom-interaction`, the player renders a
@@ -68,11 +176,43 @@ definition. Host code can attach a PCI runtime and send response/state updates b
68
176
  Production sandboxing, CSP, origin policy, and audit logging belong to the host delivery
69
177
  system.
70
178
 
179
+ ## Framework adapters
180
+
181
+ Optional React and Preact TSX wrappers ship as separate packages. They keep the web component as
182
+ the rendering primitive and only handle framework lifecycle wiring:
183
+
184
+ - `@longsightgroup/qti3-player-react`
185
+ - `@longsightgroup/qti3-player-preact`
186
+
187
+ Use the native element directly when you do not need React or Preact integration.
188
+
189
+ Local manual proof for the React adapter: from the repo root run
190
+ `pnpm dev:adapter-react` and open `/adapter-react.html` (linked from the main manual harness).
191
+
192
+ ## Clearing a loaded item
193
+
194
+ `clearItem()` (or omitting declarative `xml` on the adapters) removes rendered content and in-memory
195
+ session state. It does not emit `qti-statechange` or other player events because no item is loaded.
196
+ Hosts should treat the prop transition or imperative call as the source of truth.
197
+
198
+ Framework adapters treat `xml={undefined}` as a clear and `xml=""` as a load attempt. An empty
199
+ string shows the parse error view when the XML is invalid.
200
+
201
+ Restored `loadOptions.state` reload keys use JSON serialization: equivalent content with different
202
+ object references does not reload, but key order follows construction order and in-place mutation
203
+ without a reload key change is not detected.
204
+
71
205
  ## Styling
72
206
 
73
207
  The player uses light DOM and is style-neutral by design. Host applications can style
74
208
  the rendered `qti3-*` classes directly while preserving the item author's QTI shared
75
209
  vocabulary classes.
76
210
 
211
+ Screen-reader status lines (`.qti3-selection-summary`, `aria-live="polite"`) are
212
+ visually hidden by default so LMS shells do not show reorder or selection announcements
213
+ to sighted users. They remain available to assistive technology. Set
214
+ `data-show-live-regions` on `qti-assessment-item-player` only in local debug or harness
215
+ pages when you want those messages visible on screen.
216
+
77
217
  See the main repository README for the support matrix and release notes:
78
218
  https://github.com/LongsightGroup/qti3
package/dist/index.d.ts CHANGED
@@ -1,4 +1,15 @@
1
- export type { QtiPlayerAssociationPairLabelParams, QtiPlayerMessages, QtiPlayerRemoveMessageParams, } from "./player-messages.js";
2
- export type { QtiAssessmentItemPlayerCustomEventMap, QtiAssessmentItemPlayerEvent, QtiAssessmentItemPlayerEventDetailMap, QtiAssessmentItemPlayerEventName, QtiEndAttemptEventDetail, QtiPlayerFetchXml, QtiPlayerLoadOptions, QtiPlayerMessageOverrides, QtiPlayerResolveAsset, QtiPlayerSessionControl, QtiPortableCustomMountEventDetail, QtiReadyEventDetail, QtiResponseChangeEventDetail, QtiScoreAttemptOptions, QtiScoreEventDetail, QtiStateChangeEventDetail, QtiSuspendEventDetail, QtiValidationEventDetail, } from "./player-types.js";
1
+ export type { QtiPlayerMovementDirection } from "./player-messages.js";
2
+ export type { QtiAttemptStateV1, QtiCatalogSupportResolution, QtiCatalogSupportResolutionOptions, QtiScoreResult, QtiTextToSpeechTraversal, } from "@longsightgroup/qti3-core";
3
+ export type { QtiAssessmentItemPlayerCustomEventMap, QtiAssessmentItemPlayerEvent, QtiAssessmentItemPlayerEventDetailMap, QtiAssessmentItemPlayerEventName, QtiDiagnosticsEventDetail, QtiEndAttemptEventDetail, QtiPlayerFetchXml, QtiPlayerLoadOptions, QtiPlayerResolveAsset, QtiPlayerSessionControl, QtiPortableCustomMountEventDetail, QtiReadyEventDetail, QtiResponseChangeEventDetail, QtiResetEventDetail, QtiRestoreEventDetail, QtiScoreAttemptOptions, QtiScoreEventDetail, QtiStateChangeEventDetail, QtiSuspendEventDetail, QtiValidationEventDetail, } from "./player-types.js";
4
+ export type { QtiAssessmentItemPlayerAdapterEventCallback, QtiAssessmentItemPlayerAdapterEventHandlerProps, QtiAssessmentItemPlayerAdapterEventPropName, QtiAssessmentItemPlayerAdapterLoadSyncInput, QtiAssessmentItemPlayerAdapterProps, QtiAssessmentItemPlayerAdapterPropName, QtiAssessmentItemPlayerHandle, QtiAssessmentItemPlayerLoadDependencies, } from "./player-adapter.js";
5
+ export { bindQtiAssessmentItemPlayerAdapterEvents, createQtiAssessmentItemPlayerAdapterLoadSync, createQtiAssessmentItemPlayerHandle, isQtiAssessmentItemPlayerAdapterPropName, normalizeQtiAssessmentItemPlayerLoadError, qtiAssessmentItemPlayerAdapterEventEntries, qtiAssessmentItemPlayerAdapterPropNames, qtiAssessmentItemPlayerLoadDependencies, qtiAssessmentItemPlayerLoadStateKey, syncQtiAssessmentItemPlayerAdapterChrome, syncQtiAssessmentItemPlayerAdapterMessages, } from "./player-adapter.js";
6
+ export type { PlayerMessageCatalog } from "./player-message-catalog.js";
7
+ export type { PlayerMessageKey, PlayerMessageResolverKind } from "./player-message-manifest.js";
8
+ export { PLAYER_MESSAGE_MANIFEST } from "./player-message-manifest.js";
9
+ export { createPlayerMessageResolver, defaultPlayerMessageCatalog, defaultPlayerMessageResolver, extractMessagePlaceholders, formatPlayerMessage, mergePlayerMessageCatalogs, type PlayerMessageOverride, type PlayerMessageParams, type PlayerMessageResolver, type QtiPlayerMessageOverrides, } from "./player-message-catalog.js";
10
+ export { PLAYER_MESSAGE_KEYS, PLAYER_MESSAGE_STRING_KEYS } from "./player-message-keys.js";
11
+ export type { PlayerMessageCatalogDiagnostic, PlayerMessageCatalogDiagnosticCode, PlayerMessageCatalogValidationResult, ValidatePlayerMessageCatalogOptions, } from "./player-message-catalog-validate.js";
12
+ export { allowedCatalogPlaceholders, requiredCatalogPlaceholders, validatePlayerMessageCatalog, } from "./player-message-catalog-validate.js";
13
+ export { resolvePlayerMessages } from "./player-locale.js";
3
14
  export { QtiAssessmentItemPlayer, defineQtiAssessmentItemPlayer } from "./player-element.js";
4
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mCAAmC,EACnC,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,qCAAqC,EACrC,4BAA4B,EAC5B,qCAAqC,EACrC,gCAAgC,EAChC,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,iCAAiC,EACjC,mBAAmB,EACnB,4BAA4B,EAC5B,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACvE,YAAY,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,kCAAkC,EAClC,cAAc,EACd,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,qCAAqC,EACrC,4BAA4B,EAC5B,qCAAqC,EACrC,gCAAgC,EAChC,yBAAyB,EACzB,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,iCAAiC,EACjC,mBAAmB,EACnB,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,2CAA2C,EAC3C,+CAA+C,EAC/C,2CAA2C,EAC3C,2CAA2C,EAC3C,mCAAmC,EACnC,sCAAsC,EACtC,6BAA6B,EAC7B,uCAAuC,GACxC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wCAAwC,EACxC,4CAA4C,EAC5C,mCAAmC,EACnC,wCAAwC,EACxC,yCAAyC,EACzC,0CAA0C,EAC1C,uCAAuC,EACvC,uCAAuC,EACvC,mCAAmC,EACnC,wCAAwC,EACxC,0CAA0C,GAC3C,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,YAAY,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC3F,YAAY,EACV,8BAA8B,EAC9B,kCAAkC,EAClC,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,8 @@
1
+ export { bindQtiAssessmentItemPlayerAdapterEvents, createQtiAssessmentItemPlayerAdapterLoadSync, createQtiAssessmentItemPlayerHandle, isQtiAssessmentItemPlayerAdapterPropName, normalizeQtiAssessmentItemPlayerLoadError, qtiAssessmentItemPlayerAdapterEventEntries, qtiAssessmentItemPlayerAdapterPropNames, qtiAssessmentItemPlayerLoadDependencies, qtiAssessmentItemPlayerLoadStateKey, syncQtiAssessmentItemPlayerAdapterChrome, syncQtiAssessmentItemPlayerAdapterMessages, } from "./player-adapter.js";
2
+ export { PLAYER_MESSAGE_MANIFEST } from "./player-message-manifest.js";
3
+ export { createPlayerMessageResolver, defaultPlayerMessageCatalog, defaultPlayerMessageResolver, extractMessagePlaceholders, formatPlayerMessage, mergePlayerMessageCatalogs, } from "./player-message-catalog.js";
4
+ export { PLAYER_MESSAGE_KEYS, PLAYER_MESSAGE_STRING_KEYS } from "./player-message-keys.js";
5
+ export { allowedCatalogPlaceholders, requiredCatalogPlaceholders, validatePlayerMessageCatalog, } from "./player-message-catalog-validate.js";
6
+ export { resolvePlayerMessages } from "./player-locale.js";
1
7
  export { QtiAssessmentItemPlayer, defineQtiAssessmentItemPlayer } from "./player-element.js";
2
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwCA,OAAO,EACL,wCAAwC,EACxC,4CAA4C,EAC5C,mCAAmC,EACnC,wCAAwC,EACxC,yCAAyC,EACzC,0CAA0C,EAC1C,uCAAuC,EACvC,uCAAuC,EACvC,mCAAmC,EACnC,wCAAwC,EACxC,0CAA0C,GAC3C,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,GAK3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAO3F,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type { QtiAttemptStateV1, QtiCatalogSupportResolution, QtiCatalogSupportResolutionOptions, QtiScoreResult, QtiTextToSpeechTraversal } from "@longsightgroup/qti3-core";
2
+ import type { PlayerMessageCatalog } from "./player-message-catalog.js";
3
+ import type { QtiAssessmentItemPlayer } from "./player-element.js";
4
+ import type { QtiPlayerMessageOverrides } from "./player-message-resolver.js";
5
+ import type { QtiAssessmentItemPlayerEventDetailMap, QtiAssessmentItemPlayerEventName, QtiPlayerFetchXml, QtiPlayerLoadOptions, QtiPlayerResolveAsset, QtiScoreAttemptOptions } from "./player-types.js";
6
+ export type QtiAssessmentItemPlayerAdapterEventPropName = "onReady" | "onResponseChange" | "onStateChange" | "onScore" | "onValidation" | "onSuspend" | "onEndAttempt" | "onPortableCustomMount" | "onDiagnostics" | "onReset" | "onRestore";
7
+ export type QtiAssessmentItemPlayerAdapterPropName = "xml" | "loadOptions" | "languageOfInterface" | "messageCatalog" | "messages" | "onLoadError" | QtiAssessmentItemPlayerAdapterEventPropName;
8
+ export type QtiAssessmentItemPlayerAdapterEventCallback<T extends QtiAssessmentItemPlayerEventName> = (detail: QtiAssessmentItemPlayerEventDetailMap[T]) => void;
9
+ export type QtiAssessmentItemPlayerAdapterEventHandlerProps = {
10
+ [K in (typeof qtiAssessmentItemPlayerAdapterEventEntries)[number] as K[1]]?: QtiAssessmentItemPlayerAdapterEventCallback<K[0]>;
11
+ };
12
+ export interface QtiAssessmentItemPlayerAdapterProps extends QtiAssessmentItemPlayerAdapterEventHandlerProps {
13
+ /** Already-prepared candidate-safe XML for delivery, or authoring/preview XML in preview tools. */
14
+ xml?: string | undefined;
15
+ loadOptions?: QtiPlayerLoadOptions | undefined;
16
+ languageOfInterface?: string | undefined;
17
+ messageCatalog?: PlayerMessageCatalog | undefined;
18
+ messages?: QtiPlayerMessageOverrides | undefined;
19
+ onLoadError?: ((error: Error) => void) | undefined;
20
+ }
21
+ export interface QtiAssessmentItemPlayerHandle {
22
+ readonly element: QtiAssessmentItemPlayer;
23
+ loadXml(xml: string, options?: QtiPlayerLoadOptions): Promise<void>;
24
+ loadUrl(url: string, options?: QtiPlayerLoadOptions): Promise<void>;
25
+ scoreAttempt(options?: QtiScoreAttemptOptions): QtiScoreResult | undefined;
26
+ restore(state: QtiAttemptStateV1): void;
27
+ suspend(): void;
28
+ endAttempt(options?: QtiScoreAttemptOptions): void;
29
+ reset(): void;
30
+ clearItem(): void;
31
+ serialize(): QtiAttemptStateV1 | undefined;
32
+ getTextToSpeechTraversal(): QtiTextToSpeechTraversal | undefined;
33
+ getCatalogSupportResolution(options?: QtiCatalogSupportResolutionOptions): QtiCatalogSupportResolution | undefined;
34
+ }
35
+ export declare const qtiAssessmentItemPlayerAdapterEventEntries: readonly [readonly ["qti-ready", "onReady"], readonly ["qti-responsechange", "onResponseChange"], readonly ["qti-statechange", "onStateChange"], readonly ["qti-score", "onScore"], readonly ["qti-validation", "onValidation"], readonly ["qti-suspend", "onSuspend"], readonly ["qti-endattempt", "onEndAttempt"], readonly ["qti-portable-custom-mount", "onPortableCustomMount"], readonly ["qti-diagnostics", "onDiagnostics"], readonly ["qti-reset", "onReset"], readonly ["qti-restore", "onRestore"]];
36
+ export declare const qtiAssessmentItemPlayerAdapterPropNames: readonly ["xml", "loadOptions", "languageOfInterface", "messageCatalog", "messages", "onLoadError", ...("onReady" | "onResponseChange" | "onStateChange" | "onScore" | "onValidation" | "onSuspend" | "onEndAttempt" | "onPortableCustomMount" | "onDiagnostics" | "onReset" | "onRestore")[]];
37
+ export declare function isQtiAssessmentItemPlayerAdapterPropName(name: string): boolean;
38
+ export type QtiAssessmentItemPlayerLoadDependencies = readonly [
39
+ string | undefined,
40
+ QtiPlayerLoadOptions["status"] | undefined,
41
+ boolean | undefined,
42
+ boolean | undefined,
43
+ QtiPlayerFetchXml | undefined,
44
+ QtiPlayerResolveAsset | undefined
45
+ ];
46
+ export declare function qtiAssessmentItemPlayerLoadStateKey(state: QtiAttemptStateV1 | undefined): string | undefined;
47
+ export declare function qtiAssessmentItemPlayerLoadDependencies(loadOptions: QtiPlayerLoadOptions | undefined): QtiAssessmentItemPlayerLoadDependencies;
48
+ export declare function bindQtiAssessmentItemPlayerAdapterEvents(element: QtiAssessmentItemPlayer, getProps: () => QtiAssessmentItemPlayerAdapterProps): () => void;
49
+ export declare function syncQtiAssessmentItemPlayerAdapterChrome(element: QtiAssessmentItemPlayer, props: Pick<QtiAssessmentItemPlayerAdapterProps, "languageOfInterface" | "messageCatalog" | "messages">): void;
50
+ /** @deprecated Use {@link syncQtiAssessmentItemPlayerAdapterChrome}. */
51
+ export declare const syncQtiAssessmentItemPlayerAdapterMessages: typeof syncQtiAssessmentItemPlayerAdapterChrome;
52
+ export interface QtiAssessmentItemPlayerAdapterLoadSyncInput {
53
+ xml?: string | undefined;
54
+ loadOptions?: QtiPlayerLoadOptions | undefined;
55
+ onLoadError?: ((error: Error) => void) | undefined;
56
+ }
57
+ export declare function createQtiAssessmentItemPlayerAdapterLoadSync(): {
58
+ run(element: QtiAssessmentItemPlayer, input: QtiAssessmentItemPlayerAdapterLoadSyncInput): () => void;
59
+ };
60
+ export declare function createQtiAssessmentItemPlayerHandle(getElement: () => QtiAssessmentItemPlayer | null): QtiAssessmentItemPlayerHandle;
61
+ export declare function normalizeQtiAssessmentItemPlayerLoadError(error: unknown): Error;
62
+ //# sourceMappingURL=player-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-adapter.d.ts","sourceRoot":"","sources":["../src/player-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ export const qtiAssessmentItemPlayerAdapterEventEntries = [
2
+ ["qti-ready", "onReady"],
3
+ ["qti-responsechange", "onResponseChange"],
4
+ ["qti-statechange", "onStateChange"],
5
+ ["qti-score", "onScore"],
6
+ ["qti-validation", "onValidation"],
7
+ ["qti-suspend", "onSuspend"],
8
+ ["qti-endattempt", "onEndAttempt"],
9
+ ["qti-portable-custom-mount", "onPortableCustomMount"],
10
+ ["qti-diagnostics", "onDiagnostics"],
11
+ ["qti-reset", "onReset"],
12
+ ["qti-restore", "onRestore"],
13
+ ];
14
+ export const qtiAssessmentItemPlayerAdapterPropNames = [
15
+ "xml",
16
+ "loadOptions",
17
+ "languageOfInterface",
18
+ "messageCatalog",
19
+ "messages",
20
+ "onLoadError",
21
+ ...qtiAssessmentItemPlayerAdapterEventEntries.map((entry) => entry[1]),
22
+ ];
23
+ const qtiAssessmentItemPlayerAdapterPropNameSet = new Set(qtiAssessmentItemPlayerAdapterPropNames);
24
+ export function isQtiAssessmentItemPlayerAdapterPropName(name) {
25
+ return qtiAssessmentItemPlayerAdapterPropNameSet.has(name);
26
+ }
27
+ export function qtiAssessmentItemPlayerLoadStateKey(state) {
28
+ if (!state)
29
+ return undefined;
30
+ // JSON key order follows insertion order; in-place mutation without reload is not detected.
31
+ return JSON.stringify(state);
32
+ }
33
+ export function qtiAssessmentItemPlayerLoadDependencies(loadOptions) {
34
+ return [
35
+ qtiAssessmentItemPlayerLoadStateKey(loadOptions?.state),
36
+ loadOptions?.status,
37
+ loadOptions?.sessionControl?.validateResponses,
38
+ loadOptions?.sessionControl?.showFeedback,
39
+ loadOptions?.fetchXml,
40
+ loadOptions?.resolveAsset,
41
+ ];
42
+ }
43
+ export function bindQtiAssessmentItemPlayerAdapterEvents(element, getProps) {
44
+ const removers = qtiAssessmentItemPlayerAdapterEventEntries.map(([eventName, propName]) => {
45
+ const listener = (event) => {
46
+ const callback = getProps()[propName];
47
+ callback?.(event.detail);
48
+ };
49
+ element.addEventListener(eventName, listener);
50
+ return () => element.removeEventListener(eventName, listener);
51
+ });
52
+ return () => {
53
+ for (const remove of removers)
54
+ remove();
55
+ };
56
+ }
57
+ export function syncQtiAssessmentItemPlayerAdapterChrome(element, props) {
58
+ element.languageOfInterface = props.languageOfInterface;
59
+ element.messageCatalog = props.messageCatalog;
60
+ element.messages = props.messages;
61
+ }
62
+ /** @deprecated Use {@link syncQtiAssessmentItemPlayerAdapterChrome}. */
63
+ export const syncQtiAssessmentItemPlayerAdapterMessages = syncQtiAssessmentItemPlayerAdapterChrome;
64
+ export function createQtiAssessmentItemPlayerAdapterLoadSync() {
65
+ let loadSequence = 0;
66
+ return {
67
+ run(element, input) {
68
+ if (input.xml === undefined) {
69
+ loadSequence += 1;
70
+ element.clearItem();
71
+ return () => { };
72
+ }
73
+ let active = true;
74
+ const sequence = (loadSequence += 1);
75
+ void element
76
+ .loadXml(input.xml, input.loadOptions)
77
+ .then(() => {
78
+ if (!active || sequence !== loadSequence)
79
+ return;
80
+ })
81
+ .catch((error) => {
82
+ if (!active || sequence !== loadSequence)
83
+ return;
84
+ input.onLoadError?.(normalizeQtiAssessmentItemPlayerLoadError(error));
85
+ });
86
+ return () => {
87
+ active = false;
88
+ };
89
+ },
90
+ };
91
+ }
92
+ export function createQtiAssessmentItemPlayerHandle(getElement) {
93
+ return {
94
+ get element() {
95
+ return requiredElement(getElement);
96
+ },
97
+ loadXml: (xml, options) => requiredElement(getElement).loadXml(xml, options),
98
+ loadUrl: (url, options) => requiredElement(getElement).loadUrl(url, options),
99
+ scoreAttempt: (options) => requiredElement(getElement).scoreAttempt(options),
100
+ restore: (state) => requiredElement(getElement).restore(state),
101
+ suspend: () => requiredElement(getElement).suspend(),
102
+ endAttempt: (options) => requiredElement(getElement).endAttempt(options),
103
+ reset: () => requiredElement(getElement).reset(),
104
+ clearItem: () => requiredElement(getElement).clearItem(),
105
+ serialize: () => requiredElement(getElement).serialize(),
106
+ getTextToSpeechTraversal: () => requiredElement(getElement).getTextToSpeechTraversal(),
107
+ getCatalogSupportResolution: (options) => requiredElement(getElement).getCatalogSupportResolution(options),
108
+ };
109
+ }
110
+ export function normalizeQtiAssessmentItemPlayerLoadError(error) {
111
+ return error instanceof Error ? error : new Error(String(error));
112
+ }
113
+ function requiredElement(getElement) {
114
+ const element = getElement();
115
+ if (!element)
116
+ throw new Error("QTI assessment item player element is not mounted.");
117
+ return element;
118
+ }
119
+ //# sourceMappingURL=player-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-adapter.js","sourceRoot":"","sources":["../src/player-adapter.ts"],"names":[],"mappings":"AA8EA,MAAM,CAAC,MAAM,0CAA0C,GAAG;IACxD,CAAC,WAAW,EAAE,SAAS,CAAC;IACxB,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;IAC1C,CAAC,iBAAiB,EAAE,eAAe,CAAC;IACpC,CAAC,WAAW,EAAE,SAAS,CAAC;IACxB,CAAC,gBAAgB,EAAE,cAAc,CAAC;IAClC,CAAC,aAAa,EAAE,WAAW,CAAC;IAC5B,CAAC,gBAAgB,EAAE,cAAc,CAAC;IAClC,CAAC,2BAA2B,EAAE,uBAAuB,CAAC;IACtD,CAAC,iBAAiB,EAAE,eAAe,CAAC;IACpC,CAAC,WAAW,EAAE,SAAS,CAAC;IACxB,CAAC,aAAa,EAAE,WAAW,CAAC;CAI1B,CAAC;AAEL,MAAM,CAAC,MAAM,uCAAuC,GAAG;IACrD,KAAK;IACL,aAAa;IACb,qBAAqB;IACrB,gBAAgB;IAChB,UAAU;IACV,aAAa;IACb,GAAG,0CAA0C,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CACF,CAAC;AAEvE,MAAM,yCAAyC,GAAG,IAAI,GAAG,CACvD,uCAAuC,CACxC,CAAC;AAEF,MAAM,UAAU,wCAAwC,CAAC,IAAY;IACnE,OAAO,yCAAyC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC7D,CAAC;AAWD,MAAM,UAAU,mCAAmC,CACjD,KAAoC;IAEpC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,4FAA4F;IAC5F,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,uCAAuC,CACrD,WAA6C;IAE7C,OAAO;QACL,mCAAmC,CAAC,WAAW,EAAE,KAAK,CAAC;QACvD,WAAW,EAAE,MAAM;QACnB,WAAW,EAAE,cAAc,EAAE,iBAAiB;QAC9C,WAAW,EAAE,cAAc,EAAE,YAAY;QACzC,WAAW,EAAE,QAAQ;QACrB,WAAW,EAAE,YAAY;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wCAAwC,CACtD,OAAgC,EAChC,QAAmD;IAEnD,MAAM,QAAQ,GAAG,0CAA0C,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE;QACxF,MAAM,QAAQ,GAAG,CAAC,KAAY,EAAE,EAAE;YAChC,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC,QAAQ,CAEvB,CAAC;YACd,QAAQ,EAAE,CACP,KAA8E,CAAC,MAAM,CACvF,CAAC;QACJ,CAAC,CAAC;QACF,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,EAAE;QACV,KAAK,MAAM,MAAM,IAAI,QAAQ;YAAE,MAAM,EAAE,CAAC;IAC1C,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wCAAwC,CACtD,OAAgC,EAChC,KAGC;IAED,OAAO,CAAC,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;IACxD,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;IAC9C,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;AACpC,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,0CAA0C,GAAG,wCAAwC,CAAC;AAQnG,MAAM,UAAU,4CAA4C;IAM1D,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,OAAO;QACL,GAAG,CAAC,OAAO,EAAE,KAAK;YAChB,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC5B,YAAY,IAAI,CAAC,CAAC;gBAClB,OAAO,CAAC,SAAS,EAAE,CAAC;gBACpB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;YAClB,CAAC;YAED,IAAI,MAAM,GAAG,IAAI,CAAC;YAClB,MAAM,QAAQ,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;YACrC,KAAK,OAAO;iBACT,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC;iBACrC,IAAI,CAAC,GAAG,EAAE;gBACT,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,YAAY;oBAAE,OAAO;YACnD,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxB,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,YAAY;oBAAE,OAAO;gBACjD,KAAK,CAAC,WAAW,EAAE,CAAC,yCAAyC,CAAC,KAAK,CAAC,CAAC,CAAC;YACxE,CAAC,CAAC,CAAC;YAEL,OAAO,GAAG,EAAE;gBACV,MAAM,GAAG,KAAK,CAAC;YACjB,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,UAAgD;IAEhD,OAAO;QACL,IAAI,OAAO;YACT,OAAO,eAAe,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC;QAC5E,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC;QAC5E,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC;QAC5E,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QAC9D,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;QACpD,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;QACxE,KAAK,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE;QAChD,SAAS,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE;QACxD,SAAS,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE;QACxD,wBAAwB,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,wBAAwB,EAAE;QACtF,2BAA2B,EAAE,CAAC,OAAO,EAAE,EAAE,CACvC,eAAe,CAAC,UAAU,CAAC,CAAC,2BAA2B,CAAC,OAAO,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yCAAyC,CAAC,KAAc;IACtE,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,eAAe,CACtB,UAAgD;IAEhD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACpF,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** True when dev warnings are enabled (non-production Node, or browser without NODE_ENV). */
2
+ export declare function playerDevWarningsEnabled(): boolean;
3
+ export declare function warnPlayerMessageOnce(code: string, message: string): void;
4
+ //# sourceMappingURL=player-dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-dev.d.ts","sourceRoot":"","sources":["../src/player-dev.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,wBAAgB,wBAAwB,IAAI,OAAO,CAIlD;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIzE"}
@@ -0,0 +1,14 @@
1
+ /** True when dev warnings are enabled (non-production Node, or browser without NODE_ENV). */
2
+ export function playerDevWarningsEnabled() {
3
+ const nodeEnv = globalThis.process?.env
4
+ ?.NODE_ENV;
5
+ return nodeEnv !== "production";
6
+ }
7
+ const warnedKeys = new Set();
8
+ export function warnPlayerMessageOnce(code, message) {
9
+ if (!playerDevWarningsEnabled() || warnedKeys.has(code))
10
+ return;
11
+ warnedKeys.add(code);
12
+ console.warn(`[qti3-player] ${message}`);
13
+ }
14
+ //# sourceMappingURL=player-dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-dev.js","sourceRoot":"","sources":["../src/player-dev.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,MAAM,UAAU,wBAAwB;IACtC,MAAM,OAAO,GAAI,UAA4D,CAAC,OAAO,EAAE,GAAG;QACxF,EAAE,QAAQ,CAAC;IACb,OAAO,OAAO,KAAK,YAAY,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;AAErC,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,OAAe;IACjE,IAAI,CAAC,wBAAwB,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAChE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAC;AAC3C,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import { type QtiAttemptStateV1, type QtiScoreResult, type QtiCatalogSupportResolution, type QtiCatalogSupportResolutionOptions, type QtiTextToSpeechTraversal } from "@longsightgroup/qti3-core";
2
- import type { QtiPlayerLoadOptions, QtiPlayerMessageOverrides, QtiScoreAttemptOptions } from "./player-types.js";
2
+ import type { PlayerMessageCatalog } from "./player-message-catalog.js";
3
+ import type { QtiPlayerMessageOverrides } from "./player-message-resolver.js";
4
+ import type { QtiPlayerLoadOptions, QtiScoreAttemptOptions } from "./player-types.js";
3
5
  declare const HTMLElementBase: typeof HTMLElement;
4
6
  export declare class QtiAssessmentItemPlayer extends HTMLElementBase {
5
7
  static get observedAttributes(): string[];
@@ -9,17 +11,28 @@ export declare class QtiAssessmentItemPlayer extends HTMLElementBase {
9
11
  private validationMessages;
10
12
  private authoringDiagnostics;
11
13
  private languageOfInterfaceOverride;
14
+ private messageCatalogOverride;
12
15
  private messageOverrides;
16
+ private resolvedMessagesCache;
13
17
  private sessionControl;
18
+ private loadGeneration;
14
19
  get languageOfInterface(): string;
15
20
  set languageOfInterface(value: string | undefined);
16
21
  get locale(): string;
17
22
  set locale(value: string | undefined);
18
23
  get messages(): QtiPlayerMessageOverrides;
19
24
  set messages(value: QtiPlayerMessageOverrides | undefined);
25
+ get messageCatalog(): PlayerMessageCatalog | undefined;
26
+ set messageCatalog(value: PlayerMessageCatalog | undefined);
20
27
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
28
+ private invalidatePlayerMessages;
29
+ /** Clears the loaded item. Does not emit player events; declarative hosts control this via `xml`. */
30
+ clearItem(): void;
21
31
  loadXml(xml: string, options?: QtiPlayerLoadOptions): Promise<void>;
22
32
  loadUrl(url: string, options?: QtiPlayerLoadOptions): Promise<void>;
33
+ private beginLoad;
34
+ private isCurrentLoad;
35
+ private applyLoadedXml;
23
36
  scoreAttempt(options?: QtiScoreAttemptOptions): QtiScoreResult | undefined;
24
37
  reset(): void;
25
38
  restore(state: QtiAttemptStateV1): void;
@@ -1 +1 @@
1
- {"version":3,"file":"player-element.d.ts","sourceRoot":"","sources":["../src/player-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,iBAAiB,EAMtB,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,wBAAwB,EAE9B,MAAM,2BAA2B,CAAC;AA6BnC,OAAO,KAAK,EAGV,oBAAoB,EACpB,yBAAyB,EAGzB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAQ3B,QAAA,MAAM,eAAe,EAAE,OAAO,WAOO,CAAC;AAEtC,qBAAa,uBAAwB,SAAQ,eAAe;IAC1D,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAExC;IAED,OAAO,CAAC,aAAa,CAAC,CAAc;IACpC,OAAO,CAAC,OAAO,CAAC,CAAiB;IACjC,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,2BAA2B,CAAqB;IACxD,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,cAAc,CAGpB;IAEF,IAAI,mBAAmB,IAAI,MAAM,CAOhC;IAED,IAAI,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAGhD;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAEnC;IAED,IAAI,QAAQ,IAAI,yBAAyB,CAExC;IAED,IAAI,QAAQ,CAAC,KAAK,EAAE,yBAAyB,GAAG,SAAS,EAGxD;IAED,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAOxF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCvE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7E,YAAY,CAAC,OAAO,GAAE,sBAA2B,GAAG,cAAc,GAAG,SAAS;IA8B9E,KAAK,IAAI,IAAI;IAUb,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAqBvC,OAAO,IAAI,IAAI;IASf,UAAU,CAAC,OAAO,GAAE,sBAA2B,GAAG,IAAI;IAgBtD,SAAS,IAAI,iBAAiB,GAAG,SAAS;IAU1C,wBAAwB,IAAI,wBAAwB,GAAG,SAAS;IAKhE,2BAA2B,CACzB,OAAO,GAAE,kCAAuC,GAC/C,2BAA2B,GAAG,SAAS;IAK1C,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,MAAM;IAcd,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,4BAA4B;IAuBpC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,yBAAyB;IAIjC,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,cAAc;CASvB;AAED,wBAAgB,6BAA6B,IAAI,IAAI,CAIpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,4BAA4B,EAAE,uBAAuB,CAAC;KACvD;CACF"}
1
+ {"version":3,"file":"player-element.d.ts","sourceRoot":"","sources":["../src/player-element.ts"],"names":[],"mappings":"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"}