@longsightgroup/qti3-player 0.4.0 → 0.5.4

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 (291) hide show
  1. package/README.md +146 -13
  2. package/dist/content/content-dom.d.ts +11 -0
  3. package/dist/content/content-dom.d.ts.map +1 -0
  4. package/dist/content/content-dom.js +262 -0
  5. package/dist/content/content-dom.js.map +1 -0
  6. package/dist/content/content-renderer.d.ts +17 -0
  7. package/dist/content/content-renderer.d.ts.map +1 -0
  8. package/dist/content/content-renderer.js +82 -0
  9. package/dist/content/content-renderer.js.map +1 -0
  10. package/dist/controls/remove-button.d.ts +3 -0
  11. package/dist/controls/remove-button.d.ts.map +1 -0
  12. package/dist/controls/remove-button.js +12 -0
  13. package/dist/controls/remove-button.js.map +1 -0
  14. package/dist/index.d.ts +13 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +6 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/interactions/choice-interaction.d.ts +4 -0
  19. package/dist/interactions/choice-interaction.d.ts.map +1 -0
  20. package/dist/interactions/choice-interaction.js +81 -0
  21. package/dist/interactions/choice-interaction.js.map +1 -0
  22. package/dist/interactions/drawing-interaction.d.ts +6 -0
  23. package/dist/interactions/drawing-interaction.d.ts.map +1 -0
  24. package/dist/interactions/drawing-interaction.js +401 -0
  25. package/dist/interactions/drawing-interaction.js.map +1 -0
  26. package/dist/interactions/end-attempt-interaction.d.ts +4 -0
  27. package/dist/interactions/end-attempt-interaction.d.ts.map +1 -0
  28. package/dist/interactions/end-attempt-interaction.js +13 -0
  29. package/dist/interactions/end-attempt-interaction.js.map +1 -0
  30. package/dist/interactions/gap-match-interaction.d.ts +4 -0
  31. package/dist/interactions/gap-match-interaction.d.ts.map +1 -0
  32. package/dist/interactions/gap-match-interaction.js +277 -0
  33. package/dist/interactions/gap-match-interaction.js.map +1 -0
  34. package/dist/interactions/graphic-associate-interaction.d.ts +4 -0
  35. package/dist/interactions/graphic-associate-interaction.d.ts.map +1 -0
  36. package/dist/interactions/graphic-associate-interaction.js +297 -0
  37. package/dist/interactions/graphic-associate-interaction.js.map +1 -0
  38. package/dist/interactions/graphic-context.d.ts +3 -0
  39. package/dist/interactions/graphic-context.d.ts.map +1 -0
  40. package/dist/interactions/graphic-context.js +35 -0
  41. package/dist/interactions/graphic-context.js.map +1 -0
  42. package/dist/interactions/hotspot-interaction.d.ts +4 -0
  43. package/dist/interactions/hotspot-interaction.d.ts.map +1 -0
  44. package/dist/interactions/hotspot-interaction.js +68 -0
  45. package/dist/interactions/hotspot-interaction.js.map +1 -0
  46. package/dist/interactions/hottext-interaction.d.ts +3 -0
  47. package/dist/interactions/hottext-interaction.d.ts.map +1 -0
  48. package/dist/interactions/hottext-interaction.js +66 -0
  49. package/dist/interactions/hottext-interaction.js.map +1 -0
  50. package/dist/interactions/inline-choice-interaction.d.ts +4 -0
  51. package/dist/interactions/inline-choice-interaction.d.ts.map +1 -0
  52. package/dist/interactions/inline-choice-interaction.js +31 -0
  53. package/dist/interactions/inline-choice-interaction.js.map +1 -0
  54. package/dist/interactions/inline-controls.d.ts +6 -0
  55. package/dist/interactions/inline-controls.d.ts.map +1 -0
  56. package/dist/interactions/inline-controls.js +15 -0
  57. package/dist/interactions/inline-controls.js.map +1 -0
  58. package/dist/interactions/interaction-diagnostics.d.ts +7 -0
  59. package/dist/interactions/interaction-diagnostics.d.ts.map +1 -0
  60. package/dist/interactions/interaction-diagnostics.js +137 -0
  61. package/dist/interactions/interaction-diagnostics.js.map +1 -0
  62. package/dist/interactions/interaction-dispatch.d.ts +2 -0
  63. package/dist/interactions/interaction-dispatch.d.ts.map +1 -0
  64. package/dist/interactions/interaction-dispatch.js +2 -0
  65. package/dist/interactions/interaction-dispatch.js.map +1 -0
  66. package/dist/interactions/interaction-label.d.ts +4 -0
  67. package/dist/interactions/interaction-label.d.ts.map +1 -0
  68. package/dist/interactions/interaction-label.js +8 -0
  69. package/dist/interactions/interaction-label.js.map +1 -0
  70. package/dist/interactions/interaction-registry.d.ts +24 -0
  71. package/dist/interactions/interaction-registry.d.ts.map +1 -0
  72. package/dist/interactions/interaction-registry.js +138 -0
  73. package/dist/interactions/interaction-registry.js.map +1 -0
  74. package/dist/interactions/match-interaction.d.ts +4 -0
  75. package/dist/interactions/match-interaction.d.ts.map +1 -0
  76. package/dist/interactions/match-interaction.js +188 -0
  77. package/dist/interactions/match-interaction.js.map +1 -0
  78. package/dist/interactions/object-asset.d.ts +8 -0
  79. package/dist/interactions/object-asset.d.ts.map +1 -0
  80. package/dist/interactions/object-asset.js +182 -0
  81. package/dist/interactions/object-asset.js.map +1 -0
  82. package/dist/interactions/pair-interaction.d.ts +4 -0
  83. package/dist/interactions/pair-interaction.d.ts.map +1 -0
  84. package/dist/interactions/pair-interaction.js +125 -0
  85. package/dist/interactions/pair-interaction.js.map +1 -0
  86. package/dist/interactions/point-value.d.ts +16 -0
  87. package/dist/interactions/point-value.d.ts.map +1 -0
  88. package/dist/interactions/point-value.js +37 -0
  89. package/dist/interactions/point-value.js.map +1 -0
  90. package/dist/interactions/portable-custom-interaction.d.ts +16 -0
  91. package/dist/interactions/portable-custom-interaction.d.ts.map +1 -0
  92. package/dist/interactions/portable-custom-interaction.js +97 -0
  93. package/dist/interactions/portable-custom-interaction.js.map +1 -0
  94. package/dist/interactions/position-object-interaction.d.ts +4 -0
  95. package/dist/interactions/position-object-interaction.d.ts.map +1 -0
  96. package/dist/interactions/position-object-interaction.js +177 -0
  97. package/dist/interactions/position-object-interaction.js.map +1 -0
  98. package/dist/interactions/routing.d.ts +5 -0
  99. package/dist/interactions/routing.d.ts.map +1 -0
  100. package/dist/interactions/routing.js +24 -0
  101. package/dist/interactions/routing.js.map +1 -0
  102. package/dist/interactions/select-point-interaction.d.ts +4 -0
  103. package/dist/interactions/select-point-interaction.d.ts.map +1 -0
  104. package/dist/interactions/select-point-interaction.js +166 -0
  105. package/dist/interactions/select-point-interaction.js.map +1 -0
  106. package/dist/interactions/shared.d.ts +12 -0
  107. package/dist/interactions/shared.d.ts.map +1 -0
  108. package/dist/interactions/shared.js +65 -0
  109. package/dist/interactions/shared.js.map +1 -0
  110. package/dist/interactions/text-interaction.d.ts +6 -0
  111. package/dist/interactions/text-interaction.d.ts.map +1 -0
  112. package/dist/interactions/text-interaction.js +110 -0
  113. package/dist/interactions/text-interaction.js.map +1 -0
  114. package/dist/interactions/unsupported-interaction.d.ts +4 -0
  115. package/dist/interactions/unsupported-interaction.d.ts.map +1 -0
  116. package/dist/interactions/unsupported-interaction.js +23 -0
  117. package/dist/interactions/unsupported-interaction.js.map +1 -0
  118. package/dist/interactions/upload-interaction.d.ts +4 -0
  119. package/dist/interactions/upload-interaction.d.ts.map +1 -0
  120. package/dist/interactions/upload-interaction.js +10 -0
  121. package/dist/interactions/upload-interaction.js.map +1 -0
  122. package/dist/player/attempt-availability.d.ts +6 -0
  123. package/dist/player/attempt-availability.d.ts.map +1 -0
  124. package/dist/player/attempt-availability.js +27 -0
  125. package/dist/player/attempt-availability.js.map +1 -0
  126. package/dist/player/content-state.d.ts +19 -0
  127. package/dist/player/content-state.d.ts.map +1 -0
  128. package/dist/player/content-state.js +39 -0
  129. package/dist/player/content-state.js.map +1 -0
  130. package/dist/player/dynamic-body.d.ts +7 -0
  131. package/dist/player/dynamic-body.d.ts.map +1 -0
  132. package/dist/player/dynamic-body.js +28 -0
  133. package/dist/player/dynamic-body.js.map +1 -0
  134. package/dist/player/feedback-panel.d.ts +3 -0
  135. package/dist/player/feedback-panel.d.ts.map +1 -0
  136. package/dist/player/feedback-panel.js +14 -0
  137. package/dist/player/feedback-panel.js.map +1 -0
  138. package/dist/player/fetch-xml.d.ts +2 -0
  139. package/dist/player/fetch-xml.d.ts.map +1 -0
  140. package/dist/player/fetch-xml.js +10 -0
  141. package/dist/player/fetch-xml.js.map +1 -0
  142. package/dist/player/interaction-render.d.ts +14 -0
  143. package/dist/player/interaction-render.d.ts.map +1 -0
  144. package/dist/player/interaction-render.js +51 -0
  145. package/dist/player/interaction-render.js.map +1 -0
  146. package/dist/player/render-shell.d.ts +8 -0
  147. package/dist/player/render-shell.d.ts.map +1 -0
  148. package/dist/player/render-shell.js +37 -0
  149. package/dist/player/render-shell.js.map +1 -0
  150. package/dist/player/resolve-assets.d.ts +3 -0
  151. package/dist/player/resolve-assets.d.ts.map +1 -0
  152. package/dist/player/resolve-assets.js +12 -0
  153. package/dist/player/resolve-assets.js.map +1 -0
  154. package/dist/player/validation-messages.d.ts +17 -0
  155. package/dist/player/validation-messages.d.ts.map +1 -0
  156. package/dist/player/validation-messages.js +33 -0
  157. package/dist/player/validation-messages.js.map +1 -0
  158. package/dist/player-adapter.d.ts +62 -0
  159. package/dist/player-adapter.d.ts.map +1 -0
  160. package/dist/player-adapter.js +119 -0
  161. package/dist/player-adapter.js.map +1 -0
  162. package/dist/player-dev.d.ts +4 -0
  163. package/dist/player-dev.d.ts.map +1 -0
  164. package/dist/player-dev.js +14 -0
  165. package/dist/player-dev.js.map +1 -0
  166. package/dist/player-element.d.ts +14 -1
  167. package/dist/player-element.d.ts.map +1 -1
  168. package/dist/player-element.js +57 -5
  169. package/dist/player-element.js.map +1 -1
  170. package/dist/player-locale.d.ts +8 -3
  171. package/dist/player-locale.d.ts.map +1 -1
  172. package/dist/player-locale.js +16 -175
  173. package/dist/player-locale.js.map +1 -1
  174. package/dist/player-message-catalog-default.d.ts +4 -0
  175. package/dist/player-message-catalog-default.d.ts.map +1 -0
  176. package/dist/player-message-catalog-default.js +118 -0
  177. package/dist/player-message-catalog-default.js.map +1 -0
  178. package/dist/player-message-catalog-validate.d.ts +31 -0
  179. package/dist/player-message-catalog-validate.d.ts.map +1 -0
  180. package/dist/player-message-catalog-validate.js +327 -0
  181. package/dist/player-message-catalog-validate.js.map +1 -0
  182. package/dist/player-message-catalog.d.ts +18 -0
  183. package/dist/player-message-catalog.d.ts.map +1 -0
  184. package/dist/player-message-catalog.js +40 -0
  185. package/dist/player-message-catalog.js.map +1 -0
  186. package/dist/player-message-keys.d.ts +6 -0
  187. package/dist/player-message-keys.d.ts.map +1 -0
  188. package/dist/player-message-keys.js +7 -0
  189. package/dist/player-message-keys.js.map +1 -0
  190. package/dist/player-message-manifest.d.ts +272 -0
  191. package/dist/player-message-manifest.d.ts.map +1 -0
  192. package/dist/player-message-manifest.js +83 -0
  193. package/dist/player-message-manifest.js.map +1 -0
  194. package/dist/player-message-overrides.d.ts +3 -0
  195. package/dist/player-message-overrides.d.ts.map +1 -0
  196. package/dist/player-message-overrides.js +28 -0
  197. package/dist/player-message-overrides.js.map +1 -0
  198. package/dist/player-message-resolver.d.ts +31 -0
  199. package/dist/player-message-resolver.d.ts.map +1 -0
  200. package/dist/player-message-resolver.js +110 -0
  201. package/dist/player-message-resolver.js.map +1 -0
  202. package/dist/player-messages.d.ts +0 -38
  203. package/dist/player-messages.d.ts.map +1 -1
  204. package/dist/player-types.d.ts +12 -2
  205. package/dist/player-types.d.ts.map +1 -1
  206. package/dist/reorder/a11y.d.ts +7 -0
  207. package/dist/reorder/a11y.d.ts.map +1 -0
  208. package/dist/reorder/a11y.js +34 -0
  209. package/dist/reorder/a11y.js.map +1 -0
  210. package/dist/reorder/graphic-order-interaction.d.ts +4 -0
  211. package/dist/reorder/graphic-order-interaction.d.ts.map +1 -0
  212. package/dist/reorder/graphic-order-interaction.js +205 -0
  213. package/dist/reorder/graphic-order-interaction.js.map +1 -0
  214. package/dist/reorder/list-controls.d.ts +22 -0
  215. package/dist/reorder/list-controls.d.ts.map +1 -0
  216. package/dist/reorder/list-controls.js +75 -0
  217. package/dist/reorder/list-controls.js.map +1 -0
  218. package/dist/reorder/order-interaction.d.ts +4 -0
  219. package/dist/reorder/order-interaction.d.ts.map +1 -0
  220. package/dist/reorder/order-interaction.js +54 -0
  221. package/dist/reorder/order-interaction.js.map +1 -0
  222. package/dist/styles/base-styles.d.ts +2 -0
  223. package/dist/styles/base-styles.d.ts.map +1 -0
  224. package/dist/styles/base-styles.js +133 -0
  225. package/dist/styles/base-styles.js.map +1 -0
  226. package/dist/styles/choice-hottext-styles.d.ts +2 -0
  227. package/dist/styles/choice-hottext-styles.d.ts.map +1 -0
  228. package/dist/styles/choice-hottext-styles.js +76 -0
  229. package/dist/styles/choice-hottext-styles.js.map +1 -0
  230. package/dist/styles/control-styles.d.ts +2 -0
  231. package/dist/styles/control-styles.d.ts.map +1 -0
  232. package/dist/styles/control-styles.js +114 -0
  233. package/dist/styles/control-styles.js.map +1 -0
  234. package/dist/styles/drawing-styles.d.ts +2 -0
  235. package/dist/styles/drawing-styles.d.ts.map +1 -0
  236. package/dist/styles/drawing-styles.js +30 -0
  237. package/dist/styles/drawing-styles.js.map +1 -0
  238. package/dist/styles/gap-match-styles.d.ts +2 -0
  239. package/dist/styles/gap-match-styles.d.ts.map +1 -0
  240. package/dist/styles/gap-match-styles.js +33 -0
  241. package/dist/styles/gap-match-styles.js.map +1 -0
  242. package/dist/styles/graphic-styles.d.ts +2 -0
  243. package/dist/styles/graphic-styles.d.ts.map +1 -0
  244. package/dist/styles/graphic-styles.js +289 -0
  245. package/dist/styles/graphic-styles.js.map +1 -0
  246. package/dist/styles/match-pair-styles.d.ts +2 -0
  247. package/dist/styles/match-pair-styles.d.ts.map +1 -0
  248. package/dist/styles/match-pair-styles.js +62 -0
  249. package/dist/styles/match-pair-styles.js.map +1 -0
  250. package/dist/styles/text-slider-styles.d.ts +2 -0
  251. package/dist/styles/text-slider-styles.d.ts.map +1 -0
  252. package/dist/styles/text-slider-styles.js +35 -0
  253. package/dist/styles/text-slider-styles.js.map +1 -0
  254. package/package.json +8 -8
  255. package/src/controls/remove-button.ts +8 -5
  256. package/src/index.ts +61 -5
  257. package/src/interactions/choice-interaction.ts +6 -2
  258. package/src/interactions/drawing-interaction.ts +14 -9
  259. package/src/interactions/end-attempt-interaction.ts +3 -3
  260. package/src/interactions/gap-match-interaction.ts +32 -13
  261. package/src/interactions/graphic-associate-interaction.ts +15 -10
  262. package/src/interactions/hotspot-interaction.ts +10 -6
  263. package/src/interactions/inline-choice-interaction.ts +4 -4
  264. package/src/interactions/interaction-registry.ts +12 -12
  265. package/src/interactions/match-interaction.ts +9 -6
  266. package/src/interactions/pair-interaction.ts +22 -14
  267. package/src/interactions/position-object-interaction.ts +22 -13
  268. package/src/interactions/select-point-interaction.ts +25 -13
  269. package/src/interactions/shared.ts +21 -4
  270. package/src/interactions/text-interaction.ts +14 -4
  271. package/src/interactions/upload-interaction.ts +6 -3
  272. package/src/player/interaction-render.ts +4 -4
  273. package/src/player-adapter.ts +253 -0
  274. package/src/player-dev.ts +14 -0
  275. package/src/player-element.ts +78 -8
  276. package/src/player-locale.ts +28 -199
  277. package/src/player-message-catalog-default.ts +119 -0
  278. package/src/player-message-catalog-validate.ts +425 -0
  279. package/src/player-message-catalog.ts +72 -0
  280. package/src/player-message-keys.ts +12 -0
  281. package/src/player-message-manifest.ts +103 -0
  282. package/src/player-message-overrides.ts +38 -0
  283. package/src/player-message-resolver.ts +205 -0
  284. package/src/player-messages.ts +0 -30
  285. package/src/player-types.ts +15 -4
  286. package/src/reorder/a11y.ts +22 -7
  287. package/src/reorder/graphic-order-interaction.ts +23 -16
  288. package/src/reorder/list-controls.ts +8 -6
  289. package/src/reorder/order-interaction.ts +7 -5
  290. package/src/styles/base-styles.ts +20 -5
  291. package/src/styles/graphic-styles.ts +0 -6
@@ -0,0 +1,289 @@
1
+ export const GRAPHIC_PLAYER_STYLES = `
2
+ .qti3-hotspot-button[data-selected="true"] {
3
+ background: Highlight !important;
4
+ color: HighlightText !important;
5
+ outline: 3px solid Highlight;
6
+ outline-offset: 2px;
7
+ }
8
+
9
+ .qti3-hotspot-button {
10
+ position: absolute;
11
+ inset-inline-start: var(--qti3-graphic-region-inline-start, 0);
12
+ inset-block-start: var(--qti3-graphic-region-block-start, 0);
13
+ inline-size: var(--qti3-graphic-region-inline-size, auto);
14
+ block-size: var(--qti3-graphic-region-block-size, auto);
15
+ display: grid;
16
+ place-items: start;
17
+ padding: 0.25rem;
18
+ border: 2px solid CanvasText;
19
+ background: color-mix(in srgb, Canvas 65%, transparent);
20
+ color: CanvasText;
21
+ font-size: 0.8rem;
22
+ font-weight: 700;
23
+ line-height: 1;
24
+ cursor: pointer;
25
+ }
26
+
27
+ .qti3-hotspot-button[data-shape="circle"] {
28
+ border-radius: 50%;
29
+ }
30
+
31
+ .qti3-graphic-associate-hotspot,
32
+ .qti3-graphic-gap-hotspot,
33
+ .qti3-graphic-order-hotspot {
34
+ position: absolute;
35
+ inset-inline-start: var(--qti3-graphic-region-inline-start, 0);
36
+ inset-block-start: var(--qti3-graphic-region-block-start, 0);
37
+ inline-size: var(--qti3-graphic-region-inline-size, auto);
38
+ block-size: var(--qti3-graphic-region-block-size, auto);
39
+ z-index: 2;
40
+ }
41
+
42
+ .qti3-graphic-associate-hotspot[data-shape="circle"],
43
+ .qti3-graphic-gap-hotspot[data-shape="circle"],
44
+ .qti3-graphic-order-hotspot[data-shape="circle"] {
45
+ border-radius: 50%;
46
+ }
47
+
48
+ .qti3-hotspot.qti-selections-light .qti3-hotspot-button {
49
+ border-color: white;
50
+ color: white;
51
+ background: rgb(0 0 0 / 0.45);
52
+ }
53
+
54
+ .qti3-hotspot.qti-selections-dark .qti3-hotspot-button {
55
+ border-color: black;
56
+ color: black;
57
+ background: rgb(255 255 255 / 0.65);
58
+ }
59
+
60
+ .qti3-hotspot.qti-unselected-hidden
61
+ .qti3-hotspot-button:not([data-selected="true"]):not(:focus):not(:focus-visible) {
62
+ opacity: 0;
63
+ }
64
+
65
+ @supports not (background: color-mix(in srgb, Canvas 65%, transparent)) {
66
+ .qti3-hotspot-button {
67
+ background: Canvas;
68
+ }
69
+ }
70
+
71
+ @media (forced-colors: active) {
72
+ .qti3-hotspot.qti-selections-light .qti3-hotspot-button,
73
+ .qti3-hotspot.qti-selections-dark .qti3-hotspot-button {
74
+ border-color: CanvasText;
75
+ color: CanvasText;
76
+ background: Canvas;
77
+ }
78
+ }
79
+
80
+ .qti3-graphic-surface,
81
+ .qti3-hotspot-surface,
82
+ .qti3-point-surface,
83
+ .qti3-position-object-stage,
84
+ .qti3-graphic-associate-surface,
85
+ .qti3-graphic-gap-match-surface,
86
+ .qti3-graphic-order-surface {
87
+ position: relative;
88
+ border: 1px solid CanvasText;
89
+ background: Canvas;
90
+ overflow: hidden;
91
+ max-inline-size: 100%;
92
+ }
93
+
94
+ .qti3-graphic-associate-surface,
95
+ .qti3-graphic-gap-match-surface,
96
+ .qti3-graphic-order-surface {
97
+ touch-action: manipulation;
98
+ }
99
+
100
+ .qti3-graphic-associate-lines,
101
+ .qti3-graphic-sequence-lines {
102
+ position: absolute;
103
+ inset: 0;
104
+ inline-size: 100%;
105
+ block-size: 100%;
106
+ pointer-events: none;
107
+ z-index: 1;
108
+ }
109
+
110
+ .qti3-graphic-associate-lines line,
111
+ .qti3-graphic-sequence-lines line {
112
+ stroke: Highlight;
113
+ stroke-width: 4;
114
+ stroke-linecap: round;
115
+ vector-effect: non-scaling-stroke;
116
+ }
117
+
118
+ .qti3-graphic-sequence-lines marker path {
119
+ fill: Highlight;
120
+ }
121
+
122
+ .qti3-graphic-associate-hotspot,
123
+ .qti3-graphic-gap-hotspot,
124
+ .qti3-graphic-order-hotspot {
125
+ touch-action: none;
126
+ }
127
+
128
+ .qti3-graphic-gap-match-surface {
129
+ overflow: visible;
130
+ margin-block-end: calc(var(--qti3-graphic-gap-label-block-size, 2rem) + 0.75rem);
131
+ }
132
+
133
+ .qti3-point-surface {
134
+ display: block;
135
+ box-sizing: border-box;
136
+ cursor: crosshair;
137
+ color: CanvasText;
138
+ }
139
+
140
+ .qti3-position-object-stage {
141
+ box-sizing: border-box;
142
+ color: CanvasText;
143
+ touch-action: none;
144
+ overflow: visible;
145
+ margin-block-end: calc(var(--qti3-position-object-marker-block-size, 2rem) + 12px);
146
+ }
147
+
148
+ .qti3-graphic-object-image {
149
+ position: absolute;
150
+ inset: 0;
151
+ inline-size: 100%;
152
+ block-size: 100%;
153
+ object-fit: contain;
154
+ pointer-events: none;
155
+ }
156
+
157
+ .qti3-position-object-marker {
158
+ position: absolute;
159
+ inline-size: var(--qti3-position-object-marker-inline-size, 2rem);
160
+ block-size: var(--qti3-position-object-marker-block-size, 2rem);
161
+ transform: translate(-50%, -50%);
162
+ border: 2px solid CanvasText;
163
+ background: Canvas;
164
+ color: CanvasText;
165
+ padding: 0;
166
+ cursor: grab;
167
+ touch-action: none;
168
+ }
169
+
170
+ .qti3-position-object-marker[data-placed="true"] {
171
+ inset-inline-start: var(--qti3-position-object-marker-inline-start);
172
+ inset-block-start: var(--qti3-position-object-marker-block-start);
173
+ }
174
+
175
+ .qti3-position-object-marker[data-dragging="true"] {
176
+ cursor: grabbing;
177
+ }
178
+
179
+ .qti3-position-object-marker[data-placed="false"] {
180
+ inset-inline-start: var(--qti3-position-object-unplaced-inline-start, 50%);
181
+ inset-block-start: var(--qti3-position-object-unplaced-block-start, calc(100% + 1rem));
182
+ }
183
+
184
+ .qti3-position-object-marker img {
185
+ inline-size: 100%;
186
+ block-size: 100%;
187
+ object-fit: contain;
188
+ pointer-events: none;
189
+ }
190
+
191
+ .qti3-point-marker {
192
+ position: absolute;
193
+ inset-inline-start: var(--qti3-point-marker-inline-start);
194
+ inset-block-start: var(--qti3-point-marker-block-start);
195
+ inline-size: 8px;
196
+ block-size: 8px;
197
+ border: 2px solid CanvasText;
198
+ border-radius: 50%;
199
+ transform: translate(-50%, -50%);
200
+ pointer-events: none;
201
+ }
202
+
203
+ .qti3-point-marker[data-active="true"] {
204
+ outline: 2px solid Highlight;
205
+ outline-offset: 1px;
206
+ }
207
+
208
+ .qti3-graphic-gap-hotspot {
209
+ display: grid;
210
+ place-items: center;
211
+ padding: 0;
212
+ overflow: visible;
213
+ border-style: dashed;
214
+ background: rgb(255 255 255 / 0.08);
215
+ color: CanvasText;
216
+ }
217
+
218
+ .qti3-graphic-gap-hotspot[data-selected="true"] {
219
+ border-style: solid;
220
+ background: color-mix(in srgb, Highlight 18%, Canvas);
221
+ }
222
+
223
+ .qti3-graphic-gap-label {
224
+ position: absolute;
225
+ inset-block-start: calc(100% + 0.2rem);
226
+ inset-inline-start: 50%;
227
+ transform: translateX(-50%);
228
+ box-sizing: border-box;
229
+ inline-size: max-content;
230
+ max-inline-size: min(12rem, calc(100vw - 2rem));
231
+ min-inline-size: 0;
232
+ padding: 0.25rem 0.4rem;
233
+ border: 1px solid CanvasText;
234
+ border-radius: 0.25rem;
235
+ background: Canvas;
236
+ color: CanvasText;
237
+ font-size: 0.75rem;
238
+ font-weight: 700;
239
+ line-height: 1.15;
240
+ overflow-wrap: anywhere;
241
+ pointer-events: none;
242
+ box-shadow: 0 1px 2px rgb(0 0 0 / 0.16);
243
+ text-align: center;
244
+ white-space: normal;
245
+ }
246
+
247
+ @supports not (background: color-mix(in srgb, Highlight 18%, Canvas)) {
248
+ .qti3-graphic-gap-hotspot[data-selected="true"] {
249
+ background: Canvas;
250
+ }
251
+ }
252
+
253
+ .qti3-graphic-order-hotspot {
254
+ display: grid;
255
+ place-items: center;
256
+ gap: 0.15rem;
257
+ text-align: center;
258
+ }
259
+
260
+ .qti3-graphic-order-number {
261
+ display: grid;
262
+ place-items: center;
263
+ min-inline-size: 1.45rem;
264
+ min-block-size: 1.45rem;
265
+ border-radius: 999px;
266
+ background: Highlight;
267
+ color: HighlightText;
268
+ font-weight: 700;
269
+ }
270
+
271
+ .qti3-graphic-order-number:empty {
272
+ display: none;
273
+ }
274
+
275
+ .qti3-graphic-order-list {
276
+ display: grid;
277
+ gap: 0.5rem;
278
+ padding-inline-start: 1.5rem;
279
+ margin-block: 0.5rem 0;
280
+ }
281
+
282
+ .qti3-graphic-order-item {
283
+ display: flex;
284
+ flex-wrap: wrap;
285
+ gap: 0.4rem;
286
+ align-items: center;
287
+ }
288
+ `.trim();
289
+ //# sourceMappingURL=graphic-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphic-styles.js","sourceRoot":"","sources":["../../src/styles/graphic-styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+RpC,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const MATCH_PAIR_PLAYER_STYLES: string;
2
+ //# sourceMappingURL=match-pair-styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-pair-styles.d.ts","sourceRoot":"","sources":["../../src/styles/match-pair-styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,QA4D7B,CAAC"}
@@ -0,0 +1,62 @@
1
+ export const MATCH_PAIR_PLAYER_STYLES = `
2
+ .qti3-pair-selector {
3
+ display: grid;
4
+ gap: 0.75rem;
5
+ grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
6
+ align-items: start;
7
+ }
8
+
9
+ .qti3-match-selector {
10
+ display: grid;
11
+ gap: 1.5rem;
12
+ inline-size: 100%;
13
+ max-inline-size: 72rem;
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ .qti3-match-source-bank,
18
+ .qti3-match-target-bank {
19
+ align-items: stretch;
20
+ }
21
+
22
+ .qti3-token.qti3-match-source {
23
+ border-color: var(--qti3-match-accent);
24
+ background: Canvas;
25
+ color: var(--qti3-match-accent);
26
+ }
27
+
28
+ .qti3-token.qti3-match-target {
29
+ flex: 1 1 9rem;
30
+ min-inline-size: 0;
31
+ max-inline-size: 100%;
32
+ min-block-size: 5rem;
33
+ box-sizing: border-box;
34
+ border-color: var(--qti3-match-target-border);
35
+ background: var(--qti3-match-target-bg);
36
+ color: CanvasText;
37
+ font-weight: 700;
38
+ white-space: normal;
39
+ overflow-wrap: anywhere;
40
+ text-align: center;
41
+ }
42
+
43
+ @media (forced-colors: active) {
44
+ .qti3-token.qti3-match-source {
45
+ border-color: LinkText;
46
+ color: LinkText;
47
+ }
48
+
49
+ .qti3-token.qti3-match-target {
50
+ border-color: GrayText;
51
+ background: ButtonFace;
52
+ color: ButtonText;
53
+ }
54
+ }
55
+
56
+ .qti3-region-label {
57
+ flex-basis: 100%;
58
+ font-size: 0.9rem;
59
+ font-weight: 700;
60
+ }
61
+ `.trim();
62
+ //# sourceMappingURL=match-pair-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-pair-styles.js","sourceRoot":"","sources":["../../src/styles/match-pair-styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4DvC,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const TEXT_SLIDER_PLAYER_STYLES: string;
2
+ //# sourceMappingURL=text-slider-styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-slider-styles.d.ts","sourceRoot":"","sources":["../../src/styles/text-slider-styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,QAiC9B,CAAC"}
@@ -0,0 +1,35 @@
1
+ export const TEXT_SLIDER_PLAYER_STYLES = `
2
+ .qti3-text-response,
3
+ .qti3-slider-response {
4
+ display: grid;
5
+ gap: 0.4rem;
6
+ max-inline-size: 42rem;
7
+ }
8
+
9
+ .qti3-text-input,
10
+ .qti3-textarea {
11
+ inline-size: 100%;
12
+ box-sizing: border-box;
13
+ padding: 0.55rem 0.65rem;
14
+ border: 1px solid CanvasText;
15
+ background: Canvas;
16
+ color: CanvasText;
17
+ }
18
+
19
+ .qti3-textarea {
20
+ min-block-size: 8rem;
21
+ resize: vertical;
22
+ }
23
+
24
+ .qti3-counter,
25
+ .qti3-slider-output {
26
+ margin: 0;
27
+ font-size: 0.9rem;
28
+ }
29
+
30
+ .qti3-slider-response {
31
+ grid-template-columns: minmax(8rem, 1fr) auto;
32
+ align-items: center;
33
+ }
34
+ `.trim();
35
+ //# sourceMappingURL=text-slider-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-slider-styles.js","sourceRoot":"","sources":["../../src/styles/text-slider-styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCxC,CAAC,IAAI,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longsightgroup/qti3-player",
3
- "version": "0.4.0",
3
+ "version": "0.5.4",
4
4
  "description": "Style-neutral web component player for rendering and scoring QTI 3 assessment items.",
5
5
  "keywords": [
6
6
  "assessment",
@@ -25,11 +25,11 @@
25
25
  "directory": "packages/player"
26
26
  },
27
27
  "files": [
28
- "dist/*.d.ts",
29
- "dist/*.d.ts.map",
30
- "dist/*.js",
31
- "dist/*.js.map",
32
- "!dist/*.test.*",
28
+ "dist/**/*.d.ts",
29
+ "dist/**/*.d.ts.map",
30
+ "dist/**/*.js",
31
+ "dist/**/*.js.map",
32
+ "!dist/**/*.test.*",
33
33
  "src/**/*.ts",
34
34
  "!src/**/*.test.ts"
35
35
  ],
@@ -45,8 +45,8 @@
45
45
  "registry": "https://registry.npmjs.org"
46
46
  },
47
47
  "dependencies": {
48
- "@longsightgroup/qti3-core": "0.4.0",
49
- "@longsightgroup/qti3-fixtures": "0.4.0"
48
+ "@longsightgroup/qti3-core": "0.5.4",
49
+ "@longsightgroup/qti3-fixtures": "0.5.4"
50
50
  },
51
51
  "scripts": {}
52
52
  }
@@ -1,13 +1,16 @@
1
1
  import { trashIcon } from "../icons.js";
2
- import type { QtiPlayerMessages } from "../player-messages.js";
2
+ import type { PlayerMessageResolver } from "../player-message-resolver.js";
3
3
 
4
- export function removeButton(label: string | null, messages: QtiPlayerMessages): HTMLButtonElement {
5
- const safeLabel = label?.trim() || messages.remove();
4
+ export function removeButton(
5
+ label: string | null,
6
+ messages: PlayerMessageResolver,
7
+ ): HTMLButtonElement {
8
+ const safeLabel = label?.trim() || messages.message("remove");
6
9
  const button = document.createElement("button");
7
10
  button.type = "button";
8
11
  button.className = "qti3-icon-button qti3-remove-button";
9
- button.title = messages.remove();
10
- button.setAttribute("aria-label", messages.removePair({ label: safeLabel }));
12
+ button.title = messages.message("remove");
13
+ button.setAttribute("aria-label", messages.message("removePair", { label: safeLabel }));
11
14
  button.append(trashIcon());
12
15
  return button;
13
16
  }
package/src/index.ts CHANGED
@@ -1,26 +1,82 @@
1
+ export type { QtiPlayerMovementDirection } from "./player-messages.js";
1
2
  export type {
2
- QtiPlayerAssociationPairLabelParams,
3
- QtiPlayerMessages,
4
- QtiPlayerRemoveMessageParams,
5
- } from "./player-messages.js";
3
+ QtiAttemptStateV1,
4
+ QtiCatalogSupportResolution,
5
+ QtiCatalogSupportResolutionOptions,
6
+ QtiScoreResult,
7
+ QtiTextToSpeechTraversal,
8
+ } from "@longsightgroup/qti3-core";
6
9
  export type {
7
10
  QtiAssessmentItemPlayerCustomEventMap,
8
11
  QtiAssessmentItemPlayerEvent,
9
12
  QtiAssessmentItemPlayerEventDetailMap,
10
13
  QtiAssessmentItemPlayerEventName,
14
+ QtiDiagnosticsEventDetail,
11
15
  QtiEndAttemptEventDetail,
12
16
  QtiPlayerFetchXml,
13
17
  QtiPlayerLoadOptions,
14
- QtiPlayerMessageOverrides,
15
18
  QtiPlayerResolveAsset,
16
19
  QtiPlayerSessionControl,
17
20
  QtiPortableCustomMountEventDetail,
18
21
  QtiReadyEventDetail,
19
22
  QtiResponseChangeEventDetail,
23
+ QtiResetEventDetail,
24
+ QtiRestoreEventDetail,
20
25
  QtiScoreAttemptOptions,
21
26
  QtiScoreEventDetail,
22
27
  QtiStateChangeEventDetail,
23
28
  QtiSuspendEventDetail,
24
29
  QtiValidationEventDetail,
25
30
  } from "./player-types.js";
31
+ export type {
32
+ QtiAssessmentItemPlayerAdapterEventCallback,
33
+ QtiAssessmentItemPlayerAdapterEventHandlerProps,
34
+ QtiAssessmentItemPlayerAdapterEventPropName,
35
+ QtiAssessmentItemPlayerAdapterLoadSyncInput,
36
+ QtiAssessmentItemPlayerAdapterProps,
37
+ QtiAssessmentItemPlayerAdapterPropName,
38
+ QtiAssessmentItemPlayerHandle,
39
+ QtiAssessmentItemPlayerLoadDependencies,
40
+ } from "./player-adapter.js";
41
+ export {
42
+ bindQtiAssessmentItemPlayerAdapterEvents,
43
+ createQtiAssessmentItemPlayerAdapterLoadSync,
44
+ createQtiAssessmentItemPlayerHandle,
45
+ isQtiAssessmentItemPlayerAdapterPropName,
46
+ normalizeQtiAssessmentItemPlayerLoadError,
47
+ qtiAssessmentItemPlayerAdapterEventEntries,
48
+ qtiAssessmentItemPlayerAdapterPropNames,
49
+ qtiAssessmentItemPlayerLoadDependencies,
50
+ qtiAssessmentItemPlayerLoadStateKey,
51
+ syncQtiAssessmentItemPlayerAdapterChrome,
52
+ syncQtiAssessmentItemPlayerAdapterMessages,
53
+ } from "./player-adapter.js";
54
+ export type { PlayerMessageCatalog } from "./player-message-catalog.js";
55
+ export type { PlayerMessageKey, PlayerMessageResolverKind } from "./player-message-manifest.js";
56
+ export { PLAYER_MESSAGE_MANIFEST } from "./player-message-manifest.js";
57
+ export {
58
+ createPlayerMessageResolver,
59
+ defaultPlayerMessageCatalog,
60
+ defaultPlayerMessageResolver,
61
+ extractMessagePlaceholders,
62
+ formatPlayerMessage,
63
+ mergePlayerMessageCatalogs,
64
+ type PlayerMessageOverride,
65
+ type PlayerMessageParams,
66
+ type PlayerMessageResolver,
67
+ type QtiPlayerMessageOverrides,
68
+ } from "./player-message-catalog.js";
69
+ export { PLAYER_MESSAGE_KEYS, PLAYER_MESSAGE_STRING_KEYS } from "./player-message-keys.js";
70
+ export type {
71
+ PlayerMessageCatalogDiagnostic,
72
+ PlayerMessageCatalogDiagnosticCode,
73
+ PlayerMessageCatalogValidationResult,
74
+ ValidatePlayerMessageCatalogOptions,
75
+ } from "./player-message-catalog-validate.js";
76
+ export {
77
+ allowedCatalogPlaceholders,
78
+ requiredCatalogPlaceholders,
79
+ validatePlayerMessageCatalog,
80
+ } from "./player-message-catalog-validate.js";
81
+ export { resolvePlayerMessages } from "./player-locale.js";
26
82
  export { QtiAssessmentItemPlayer, defineQtiAssessmentItemPlayer } from "./player-element.js";
@@ -2,10 +2,10 @@ import type { QtiInteraction, QtiValue } from "@longsightgroup/qti3-core";
2
2
  import {
3
3
  interactionChoices,
4
4
  missingChoicesMessage,
5
- readableType,
6
5
  responseGroup,
7
6
  valueToStrings,
8
7
  } from "../interaction-support.js";
8
+ import type { PlayerMessageResolver } from "../player-message-resolver.js";
9
9
 
10
10
  function choicePresentationLabel(interaction: QtiInteraction, index: number): string {
11
11
  const classNames = new Set((interaction.attributes.class ?? "").split(/\s+/).filter(Boolean));
@@ -28,6 +28,7 @@ export function renderChoice(
28
28
  interaction: QtiInteraction,
29
29
  update: (value: QtiValue) => void,
30
30
  currentValue: QtiValue,
31
+ messages: PlayerMessageResolver,
31
32
  ): HTMLElement {
32
33
  const group = responseGroup("qti3-choice-group");
33
34
 
@@ -37,7 +38,10 @@ export function renderChoice(
37
38
  const list = document.createElement("div");
38
39
  list.className = "qti3-choice-list";
39
40
  list.role = "group";
40
- list.setAttribute("aria-label", `${readableType(interaction.type)} options`);
41
+ list.setAttribute(
42
+ "aria-label",
43
+ messages.message("interactionOptionsList", { type: interaction.type }),
44
+ );
41
45
  const syncSelected = () => {
42
46
  for (const label of list.querySelectorAll<HTMLElement>(".qti3-choice-option")) {
43
47
  const identifier = label.dataset.choiceIdentifier ?? "";
@@ -1,6 +1,6 @@
1
1
  import type { QtiInteraction, QtiObjectAsset, QtiValue } from "@longsightgroup/qti3-core";
2
- import { applyResponsiveGraphicSize, objectIsImage, readableType } from "../interaction-support.js";
3
- import type { QtiPlayerMessages } from "../player-messages.js";
2
+ import { applyResponsiveGraphicSize, objectIsImage } from "../interaction-support.js";
3
+ import type { PlayerMessageResolver } from "../player-message-resolver.js";
4
4
 
5
5
  export const DRAWING_STROKE_COLOR = "#000";
6
6
  export const DRAWING_STROKE_WIDTH = 3;
@@ -9,16 +9,19 @@ export function renderDrawingResponse(
9
9
  interaction: QtiInteraction,
10
10
  update: (value: QtiValue) => void,
11
11
  currentValue: QtiValue,
12
- messages: QtiPlayerMessages,
12
+ messages: PlayerMessageResolver,
13
13
  ): HTMLElement {
14
14
  const group = document.createElement("div");
15
15
  group.role = "group";
16
- group.setAttribute("aria-label", `${readableType(interaction.type)} response`);
16
+ group.setAttribute(
17
+ "aria-label",
18
+ messages.message("interactionDrawingResponse", { type: interaction.type }),
19
+ );
17
20
 
18
21
  const surface = document.createElementNS("http://www.w3.org/2000/svg", "svg");
19
22
  surface.classList.add("qti3-drawing-surface");
20
23
  surface.setAttribute("role", "img");
21
- surface.setAttribute("aria-label", "Drawing response surface");
24
+ surface.setAttribute("aria-label", messages.message("drawingSurface"));
22
25
  surface.setAttribute("tabindex", "0");
23
26
  const width = drawingWidth(interaction);
24
27
  const height = drawingHeight(interaction);
@@ -68,12 +71,14 @@ export function renderDrawingResponse(
68
71
  const count = strokes.length;
69
72
  summary.value = serializeDrawingStrokes(strokes);
70
73
  summary.textContent =
71
- count === 0 ? "No drawing strokes." : `${count} drawing stroke${count === 1 ? "" : "s"}.`;
74
+ count === 0
75
+ ? messages.message("drawingStatusEmpty")
76
+ : messages.message("drawingStatusStrokeCount", { count });
72
77
  surface.setAttribute(
73
78
  "aria-label",
74
79
  count === 0
75
- ? "Drawing response surface, no strokes"
76
- : `Drawing response surface, ${count} stroke${count === 1 ? "" : "s"}`,
80
+ ? messages.message("drawingSurfaceEmpty")
81
+ : messages.message("drawingSurfaceStrokeCount", { count }),
77
82
  );
78
83
  };
79
84
  for (const points of restoredStrokes) {
@@ -127,7 +132,7 @@ export function renderDrawingResponse(
127
132
 
128
133
  const clear = document.createElement("button");
129
134
  clear.type = "button";
130
- clear.textContent = messages.clearDrawing();
135
+ clear.textContent = messages.message("clearDrawing");
131
136
  clear.addEventListener("click", () => {
132
137
  strokes.splice(0, strokes.length);
133
138
  activeStroke = undefined;
@@ -1,16 +1,16 @@
1
1
  import type { QtiInteraction, QtiValue } from "@longsightgroup/qti3-core";
2
- import type { QtiPlayerMessages } from "../player-messages.js";
2
+ import type { PlayerMessageResolver } from "../player-message-resolver.js";
3
3
 
4
4
  export function renderEndAttemptResponse(
5
5
  interaction: QtiInteraction,
6
6
  update: (value: QtiValue) => void,
7
7
  endAttempt: () => void,
8
- messages: QtiPlayerMessages,
8
+ messages: PlayerMessageResolver,
9
9
  ): HTMLElement {
10
10
  const button = document.createElement("button");
11
11
  button.type = "button";
12
12
  button.className = "qti3-end-attempt-button";
13
- button.textContent = interaction.attributes.title ?? messages.endAttempt();
13
+ button.textContent = interaction.attributes.title ?? messages.message("endAttempt");
14
14
  button.addEventListener("click", () => {
15
15
  if (interaction.responseIdentifier) update(true);
16
16
  endAttempt();