@pie-players/pie-assessment-toolkit 0.2.0

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 (194) hide show
  1. package/README.md +520 -0
  2. package/dist/attempt/TestSession.d.ts +90 -0
  3. package/dist/attempt/TestSession.d.ts.map +1 -0
  4. package/dist/attempt/TestSession.js +174 -0
  5. package/dist/attempt/TestSession.js.map +1 -0
  6. package/dist/core/TypedEventBus.d.ts +48 -0
  7. package/dist/core/TypedEventBus.d.ts.map +1 -0
  8. package/dist/core/TypedEventBus.js +63 -0
  9. package/dist/core/TypedEventBus.js.map +1 -0
  10. package/dist/index.d.ts +37 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +44 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/item-loader.d.ts +45 -0
  15. package/dist/item-loader.d.ts.map +1 -0
  16. package/dist/item-loader.js +62 -0
  17. package/dist/item-loader.js.map +1 -0
  18. package/dist/player/AssessmentPlayer.d.ts +388 -0
  19. package/dist/player/AssessmentPlayer.d.ts.map +1 -0
  20. package/dist/player/AssessmentPlayer.js +965 -0
  21. package/dist/player/AssessmentPlayer.js.map +1 -0
  22. package/dist/player/index.d.ts +17 -0
  23. package/dist/player/index.d.ts.map +1 -0
  24. package/dist/player/index.js +15 -0
  25. package/dist/player/index.js.map +1 -0
  26. package/dist/player/navigation-types.d.ts +63 -0
  27. package/dist/player/navigation-types.d.ts.map +1 -0
  28. package/dist/player/navigation-types.js +7 -0
  29. package/dist/player/navigation-types.js.map +1 -0
  30. package/dist/player/qti-navigation.d.ts +29 -0
  31. package/dist/player/qti-navigation.d.ts.map +1 -0
  32. package/dist/player/qti-navigation.js +160 -0
  33. package/dist/player/qti-navigation.js.map +1 -0
  34. package/dist/reference-layout/index.d.ts +19 -0
  35. package/dist/reference-layout/index.d.ts.map +1 -0
  36. package/dist/reference-layout/index.js +20 -0
  37. package/dist/reference-layout/index.js.map +1 -0
  38. package/dist/services/AccessibilityCatalogResolver.d.ts +141 -0
  39. package/dist/services/AccessibilityCatalogResolver.d.ts.map +1 -0
  40. package/dist/services/AccessibilityCatalogResolver.js +249 -0
  41. package/dist/services/AccessibilityCatalogResolver.js.map +1 -0
  42. package/dist/services/AssessmentAuthoringService.d.ts +60 -0
  43. package/dist/services/AssessmentAuthoringService.d.ts.map +1 -0
  44. package/dist/services/AssessmentAuthoringService.js +183 -0
  45. package/dist/services/AssessmentAuthoringService.js.map +1 -0
  46. package/dist/services/ContextVariableStore.d.ts +114 -0
  47. package/dist/services/ContextVariableStore.d.ts.map +1 -0
  48. package/dist/services/ContextVariableStore.js +207 -0
  49. package/dist/services/ContextVariableStore.js.map +1 -0
  50. package/dist/services/ElementToolStateStore.d.ts +125 -0
  51. package/dist/services/ElementToolStateStore.d.ts.map +1 -0
  52. package/dist/services/ElementToolStateStore.js +200 -0
  53. package/dist/services/ElementToolStateStore.js.map +1 -0
  54. package/dist/services/HighlightCoordinator.d.ts +179 -0
  55. package/dist/services/HighlightCoordinator.d.ts.map +1 -0
  56. package/dist/services/HighlightCoordinator.js +446 -0
  57. package/dist/services/HighlightCoordinator.js.map +1 -0
  58. package/dist/services/I18nService.d.ts +121 -0
  59. package/dist/services/I18nService.d.ts.map +1 -0
  60. package/dist/services/I18nService.js +276 -0
  61. package/dist/services/I18nService.js.map +1 -0
  62. package/dist/services/PNPMapper.d.ts +71 -0
  63. package/dist/services/PNPMapper.d.ts.map +1 -0
  64. package/dist/services/PNPMapper.js +98 -0
  65. package/dist/services/PNPMapper.js.map +1 -0
  66. package/dist/services/PNPToolResolver.d.ts +127 -0
  67. package/dist/services/PNPToolResolver.d.ts.map +1 -0
  68. package/dist/services/PNPToolResolver.js +222 -0
  69. package/dist/services/PNPToolResolver.js.map +1 -0
  70. package/dist/services/SSMLExtractor.d.ts +61 -0
  71. package/dist/services/SSMLExtractor.d.ts.map +1 -0
  72. package/dist/services/SSMLExtractor.js +181 -0
  73. package/dist/services/SSMLExtractor.js.map +1 -0
  74. package/dist/services/TTSService.d.ts +162 -0
  75. package/dist/services/TTSService.d.ts.map +1 -0
  76. package/dist/services/TTSService.js +465 -0
  77. package/dist/services/TTSService.js.map +1 -0
  78. package/dist/services/ThemeProvider.d.ts +95 -0
  79. package/dist/services/ThemeProvider.d.ts.map +1 -0
  80. package/dist/services/ThemeProvider.js +299 -0
  81. package/dist/services/ThemeProvider.js.map +1 -0
  82. package/dist/services/ToolConfigResolver.d.ts +162 -0
  83. package/dist/services/ToolConfigResolver.d.ts.map +1 -0
  84. package/dist/services/ToolConfigResolver.js +230 -0
  85. package/dist/services/ToolConfigResolver.js.map +1 -0
  86. package/dist/services/ToolCoordinator.d.ts +137 -0
  87. package/dist/services/ToolCoordinator.d.ts.map +1 -0
  88. package/dist/services/ToolCoordinator.js +318 -0
  89. package/dist/services/ToolCoordinator.js.map +1 -0
  90. package/dist/services/ToolkitCoordinator.d.ts +188 -0
  91. package/dist/services/ToolkitCoordinator.d.ts.map +1 -0
  92. package/dist/services/ToolkitCoordinator.js +252 -0
  93. package/dist/services/ToolkitCoordinator.js.map +1 -0
  94. package/dist/services/interfaces.d.ts +391 -0
  95. package/dist/services/interfaces.d.ts.map +1 -0
  96. package/dist/services/interfaces.js +12 -0
  97. package/dist/services/interfaces.js.map +1 -0
  98. package/dist/services/tool-providers/DesmosToolProvider.d.ts +103 -0
  99. package/dist/services/tool-providers/DesmosToolProvider.d.ts.map +1 -0
  100. package/dist/services/tool-providers/DesmosToolProvider.js +127 -0
  101. package/dist/services/tool-providers/DesmosToolProvider.js.map +1 -0
  102. package/dist/services/tool-providers/IToolProvider.d.ts +137 -0
  103. package/dist/services/tool-providers/IToolProvider.d.ts.map +1 -0
  104. package/dist/services/tool-providers/IToolProvider.js +13 -0
  105. package/dist/services/tool-providers/IToolProvider.js.map +1 -0
  106. package/dist/services/tool-providers/TIToolProvider.d.ts +107 -0
  107. package/dist/services/tool-providers/TIToolProvider.d.ts.map +1 -0
  108. package/dist/services/tool-providers/TIToolProvider.js +123 -0
  109. package/dist/services/tool-providers/TIToolProvider.js.map +1 -0
  110. package/dist/services/tool-providers/TTSToolProvider.d.ts +143 -0
  111. package/dist/services/tool-providers/TTSToolProvider.d.ts.map +1 -0
  112. package/dist/services/tool-providers/TTSToolProvider.js +168 -0
  113. package/dist/services/tool-providers/TTSToolProvider.js.map +1 -0
  114. package/dist/services/tool-providers/ToolProviderRegistry.d.ts +165 -0
  115. package/dist/services/tool-providers/ToolProviderRegistry.d.ts.map +1 -0
  116. package/dist/services/tool-providers/ToolProviderRegistry.js +240 -0
  117. package/dist/services/tool-providers/ToolProviderRegistry.js.map +1 -0
  118. package/dist/services/tool-providers/index.d.ts +18 -0
  119. package/dist/services/tool-providers/index.d.ts.map +1 -0
  120. package/dist/services/tool-providers/index.js +15 -0
  121. package/dist/services/tool-providers/index.js.map +1 -0
  122. package/dist/services/tts/browser-provider.d.ts +24 -0
  123. package/dist/services/tts/browser-provider.d.ts.map +1 -0
  124. package/dist/services/tts/browser-provider.js +177 -0
  125. package/dist/services/tts/browser-provider.js.map +1 -0
  126. package/dist/services/tts/provider-interface.d.ts +131 -0
  127. package/dist/services/tts/provider-interface.d.ts.map +1 -0
  128. package/dist/services/tts/provider-interface.js +10 -0
  129. package/dist/services/tts/provider-interface.js.map +1 -0
  130. package/dist/tools/calculators/desmos-provider.d.ts +54 -0
  131. package/dist/tools/calculators/desmos-provider.d.ts.map +1 -0
  132. package/dist/tools/calculators/desmos-provider.js +384 -0
  133. package/dist/tools/calculators/desmos-provider.js.map +1 -0
  134. package/dist/tools/calculators/mathjs-provider.d.ts +50 -0
  135. package/dist/tools/calculators/mathjs-provider.d.ts.map +1 -0
  136. package/dist/tools/calculators/mathjs-provider.js +660 -0
  137. package/dist/tools/calculators/mathjs-provider.js.map +1 -0
  138. package/dist/tools/calculators/ti-provider.d.ts +122 -0
  139. package/dist/tools/calculators/ti-provider.d.ts.map +1 -0
  140. package/dist/tools/calculators/ti-provider.js +587 -0
  141. package/dist/tools/calculators/ti-provider.js.map +1 -0
  142. package/dist/tools/client.d.ts +17 -0
  143. package/dist/tools/client.d.ts.map +1 -0
  144. package/dist/tools/client.js +26 -0
  145. package/dist/tools/client.js.map +1 -0
  146. package/dist/tools/index.d.ts +8 -0
  147. package/dist/tools/index.d.ts.map +1 -0
  148. package/dist/tools/index.js +10 -0
  149. package/dist/tools/index.js.map +1 -0
  150. package/dist/tools/library-loader.d.ts +63 -0
  151. package/dist/tools/library-loader.d.ts.map +1 -0
  152. package/dist/tools/library-loader.js +292 -0
  153. package/dist/tools/library-loader.js.map +1 -0
  154. package/dist/tools/response-discovery.d.ts +72 -0
  155. package/dist/tools/response-discovery.d.ts.map +1 -0
  156. package/dist/tools/response-discovery.js +183 -0
  157. package/dist/tools/response-discovery.js.map +1 -0
  158. package/dist/tools/tool-coordinator.d.ts +76 -0
  159. package/dist/tools/tool-coordinator.d.ts.map +1 -0
  160. package/dist/tools/tool-coordinator.js +197 -0
  161. package/dist/tools/tool-coordinator.js.map +1 -0
  162. package/dist/tools/types.d.ts +427 -0
  163. package/dist/tools/types.d.ts.map +1 -0
  164. package/dist/tools/types.js +13 -0
  165. package/dist/tools/types.js.map +1 -0
  166. package/dist/tools/variant-resolver.d.ts +48 -0
  167. package/dist/tools/variant-resolver.d.ts.map +1 -0
  168. package/dist/tools/variant-resolver.js +214 -0
  169. package/dist/tools/variant-resolver.js.map +1 -0
  170. package/dist/types/events.d.ts +157 -0
  171. package/dist/types/events.d.ts.map +1 -0
  172. package/dist/types/events.js +11 -0
  173. package/dist/types/events.js.map +1 -0
  174. package/dist/utils/logger.d.ts +7 -0
  175. package/dist/utils/logger.d.ts.map +1 -0
  176. package/dist/utils/logger.js +11 -0
  177. package/dist/utils/logger.js.map +1 -0
  178. package/package.json +71 -0
  179. package/src/README.md +626 -0
  180. package/src/components/QuestionToolBar.svelte +406 -0
  181. package/src/player/AssessmentLayout.svelte +68 -0
  182. package/src/player/README.md +154 -0
  183. package/src/reference-layout/README.md +135 -0
  184. package/src/reference-layout/ReferenceLayout.svelte +209 -0
  185. package/src/reference-layout/components/AssessmentContent.svelte +259 -0
  186. package/src/reference-layout/components/AssessmentFooter.svelte +89 -0
  187. package/src/reference-layout/components/AssessmentHeader.svelte +250 -0
  188. package/src/reference-layout/components/AssessmentNavigation.svelte +134 -0
  189. package/src/reference-layout/components/AssessmentToolsBar.svelte +176 -0
  190. package/src/reference-layout/components/ItemPanel.svelte +200 -0
  191. package/src/reference-layout/components/NotesPanel.svelte +179 -0
  192. package/src/reference-layout/components/PassagePanel.svelte +76 -0
  193. package/src/tools/README.md +616 -0
  194. package/src/tools/calculators/README.md +395 -0
package/src/README.md ADDED
@@ -0,0 +1,626 @@
1
+ # PIE Assessment Toolkit
2
+
3
+ **Independent, composable services** for coordinating tools, accommodations, and item players in assessment applications.
4
+
5
+ This is not an opinionated framework or monolithic "player" - it's a toolkit that solves specific problems.
6
+
7
+ ## What Does It Solve?
8
+
9
+ - **Tool coordination**: z-index management, visibility state
10
+ - **Accommodation support**: IEP/504 tool configuration logic
11
+ - **TTS + annotation coordination**: Prevent conflicts between highlights
12
+ - **Event communication**: Standard contracts between components
13
+ - **Accessibility theming**: Consistent high-contrast, font sizing
14
+
15
+ ## Architecture Overview
16
+
17
+ See [Tools & Accommodations Architecture](../../../docs/tools-and-accomodations/architecture.md) for complete design documentation.
18
+
19
+ ### Primary Interface: Section Player
20
+
21
+ The **PIE Section Player** (`@pie-players/pie-section-player`) is the primary interface for integrating toolkit services. Pass services as JavaScript properties, and the player handles SSML extraction, catalog lifecycle, and TTS tool rendering automatically.
22
+
23
+ ### Core Principles
24
+
25
+ 1. **Composable Services**: Import only what you need
26
+ 2. **No Framework Lock-in**: Works with any JavaScript framework
27
+ 3. **Product Control**: Products control navigation, persistence, layout, backend
28
+ 4. **Standard Contracts**: Well-defined event types for component communication
29
+ 5. **Section Player Integration**: Seamless integration with the section player for automatic service coordination
30
+
31
+ ## Implementation Status
32
+
33
+ ### ✅ Core Infrastructure
34
+
35
+ - **TypedEventBus**: Type-safe event bus built on native EventTarget
36
+ - **Event Types**: Complete event definitions (player, tools, navigation, state, interaction)
37
+
38
+ ### ✅ Toolkit Services
39
+
40
+ - **ToolCoordinator**: Manages z-index layering and visibility for floating tools
41
+ - **HighlightCoordinator**: Separate highlight layers for TTS (temporary) and annotations (persistent)
42
+ - **TTSService**: Singleton service providing text-to-speech across multiple entry points with QTI 3.0 catalog support
43
+ - **AccessibilityCatalogResolver**: QTI 3.0 accessibility catalog management for SSML, sign language, braille, etc.
44
+ - **SSMLExtractor**: Automatic extraction of embedded `<speak>` tags from content into accessibility catalogs
45
+ - **ThemeProvider**: Consistent accessibility theming across items and tools
46
+ - **ToolConfigResolver**: 3-tier hierarchy for IEP/504 tool configuration
47
+
48
+ ### ✅ Section Player Integration
49
+
50
+ The toolkit integrates seamlessly with the **PIE Section Player**:
51
+
52
+ - **Primary Interface**: Section player is the main integration point
53
+ - **Automatic SSML Extraction**: Extracts embedded `<speak>` tags from passages and items
54
+ - **Catalog Lifecycle**: Manages item-level catalogs automatically (add on load, clear on navigation)
55
+ - **TTS Tool Rendering**: Shows inline TTS buttons in passage/item headers
56
+ - **Service Coordination**: All toolkit services work together automatically
57
+
58
+ **Integration Pattern**:
59
+
60
+ ```javascript
61
+ import {
62
+ TTSService,
63
+ AccessibilityCatalogResolver,
64
+ ToolCoordinator,
65
+ HighlightCoordinator
66
+ } from '@pie-players/pie-assessment-toolkit';
67
+
68
+ // Initialize services
69
+ const ttsService = new TTSService();
70
+ const catalogResolver = new AccessibilityCatalogResolver([], 'en-US');
71
+ // ... initialize other services
72
+
73
+ // Pass to section player
74
+ sectionPlayer.ttsService = ttsService;
75
+ sectionPlayer.catalogResolver = catalogResolver;
76
+ sectionPlayer.section = section;
77
+ ```
78
+
79
+ ### ✅ Reference Implementation (Future)
80
+
81
+ An optional **AssessmentPlayer** reference implementation may be provided for multi-section assessments. It would:
82
+
83
+ - Manage navigation across sections
84
+ - Coordinate section player instances
85
+ - Provide assessment-level state management
86
+ - But delegate to section players for rendering
87
+
88
+ ## Project Structure
89
+
90
+ ```
91
+ assessment-toolkit/
92
+ ├── core/
93
+ │ └── TypedEventBus.ts # Event system
94
+ ├── services/
95
+ │ ├── ToolCoordinator.ts # Z-index, visibility
96
+ │ ├── HighlightCoordinator.ts # TTS + annotation highlights
97
+ │ ├── TTSService.ts # Text-to-speech with catalog support
98
+ │ ├── AccessibilityCatalogResolver.ts # QTI 3.0 catalog management
99
+ │ ├── SSMLExtractor.ts # Automatic SSML extraction
100
+ │ ├── ThemeProvider.ts # Accessibility theming
101
+ │ └── ToolConfigResolver.ts # IEP/504 configuration
102
+ ├── types/
103
+ │ └── events.ts # Event definitions
104
+ ├── player/
105
+ │ ├── README.md # Optional reference patterns
106
+ │ └── navigation-types.ts # Navigation abstractions
107
+ └── index.ts # Public exports
108
+ ```
109
+
110
+ ## Usage Examples
111
+
112
+ ### Minimal Integration (Just Events + Tools)
113
+
114
+ ```typescript
115
+ import {
116
+ TypedEventBus,
117
+ ToolCoordinator,
118
+ type AssessmentToolkitEvents
119
+ } from '$lib/assessment-toolkit';
120
+
121
+ const eventBus = new TypedEventBus<AssessmentToolkitEvents>();
122
+ const toolCoordinator = new ToolCoordinator();
123
+
124
+ // Register tools
125
+ toolCoordinator.registerTool('calculator', 'Calculator', calcElement);
126
+
127
+ // Wire up events
128
+ eventBus.on('player:session-changed', async (e) => {
129
+ await myBackend.save(e.detail.session);
130
+ });
131
+
132
+ eventBus.on('tool:activated', (e) => {
133
+ toolCoordinator.bringToFront(e.target);
134
+ });
135
+ ```
136
+
137
+ ### Advanced Integration (All Services)
138
+
139
+ ```typescript
140
+ import {
141
+ TypedEventBus,
142
+ ToolCoordinator,
143
+ HighlightCoordinator,
144
+ TTSService,
145
+ ThemeProvider,
146
+ ToolConfigResolver,
147
+ type AssessmentToolkitEvents
148
+ } from '$lib/assessment-toolkit';
149
+
150
+ // Initialize services
151
+ const eventBus = new TypedEventBus<AssessmentToolkitEvents>();
152
+ const toolCoordinator = new ToolCoordinator();
153
+ const highlightCoordinator = new HighlightCoordinator();
154
+ const ttsService = TTSService.getInstance();
155
+ const themeProvider = new ThemeProvider();
156
+ const toolResolver = new ToolConfigResolver();
157
+
158
+ // Initialize TTS
159
+ await ttsService.initialize('browser');
160
+ ttsService.setHighlightCoordinator(highlightCoordinator);
161
+
162
+ // Apply accessibility theme
163
+ themeProvider.applyTheme({
164
+ highContrast: true,
165
+ fontSize: 'large'
166
+ });
167
+
168
+ // Resolve tool configuration
169
+ const toolConfig = toolResolver.resolveTool(
170
+ 'calculator',
171
+ itemConfig.tools, // Item level
172
+ rosterConfig.allowances, // Roster level
173
+ studentProfile.accommodations // Student level
174
+ );
175
+
176
+ // Wire up events
177
+ eventBus.on('player:session-changed', async (e) => {
178
+ await myBackend.saveSession(e.detail);
179
+ myAnalytics.track('response', e.detail);
180
+ });
181
+
182
+ eventBus.on('tool:activated', (e) => {
183
+ toolCoordinator.bringToFront(e.target);
184
+ myAnalytics.track('tool-usage', e.detail);
185
+ });
186
+ ```
187
+
188
+ ### Tool Configuration Example
189
+
190
+ ```typescript
191
+ import {
192
+ ToolConfigResolver,
193
+ type ItemToolConfig,
194
+ type RosterToolConfig,
195
+ type StudentAccommodations
196
+ } from '$lib/assessment-toolkit';
197
+
198
+ const resolver = new ToolConfigResolver();
199
+
200
+ // Scenario: Student with IEP requiring TTS and calculator
201
+ const studentProfile: StudentAccommodations = {
202
+ accommodations: ['tts', 'calculator', 'extended-time']
203
+ };
204
+
205
+ // Test blocks dictionary but allows calculator
206
+ const rosterConfig: RosterToolConfig = {
207
+ calculator: "1",
208
+ dictionary: "0"
209
+ };
210
+
211
+ // Current item requires scientific calculator
212
+ const itemConfig: ItemToolConfig = {
213
+ calculator: {
214
+ type: 'scientific',
215
+ required: true
216
+ }
217
+ };
218
+
219
+ // Resolve all tools
220
+ const resolved = resolver.resolveAll({
221
+ itemConfig,
222
+ rosterConfig,
223
+ studentProfile
224
+ });
225
+
226
+ // Result:
227
+ // - calculator: enabled (scientific, required by item)
228
+ // - tts: enabled (student accommodation)
229
+ // - dictionary: disabled (blocked by roster)
230
+ ```
231
+
232
+ ## Integration Patterns
233
+
234
+ ### Pattern 1: Quiz Engine (Advanced - DIY Wiring)
235
+
236
+ Quiz Engine imports services and wires their own way.
237
+
238
+ ```typescript
239
+ class QuizEngineAssessmentPlayer {
240
+ private eventBus = new TypedEventBus<AssessmentToolkitEvents>();
241
+ private toolCoordinator = new ToolCoordinator();
242
+
243
+ constructor() {
244
+ this.setupEventHandlers();
245
+ this.setupQENavigation();
246
+ this.setupQEPersistence();
247
+ }
248
+
249
+ private setupEventHandlers() {
250
+ this.eventBus.on('player:session-changed', async (e) => {
251
+ await this.qeBackend.saveSession(e.detail);
252
+ this.qeAnalytics.track('response', e.detail);
253
+ });
254
+ }
255
+ }
256
+ ```
257
+
258
+ ### Pattern 2: Reference Implementation (Pre-fab)
259
+
260
+ Use the reference implementation with custom navigation.
261
+
262
+ ```typescript
263
+ // Coming soon - reference implementation
264
+ ```
265
+
266
+ ## API Documentation
267
+
268
+ ### TypedEventBus
269
+
270
+ Type-safe event bus built on native EventTarget.
271
+
272
+ ```typescript
273
+ const eventBus = new TypedEventBus<AssessmentToolkitEvents>();
274
+
275
+ // Emit events
276
+ eventBus.emit('player:session-changed', { /* ... */ });
277
+
278
+ // Listen to events
279
+ eventBus.on('player:session-changed', (e) => {
280
+ console.log('Session changed:', e.detail);
281
+ });
282
+
283
+ // One-time listeners
284
+ eventBus.once('player:load-complete', (e) => { /* ... */ });
285
+
286
+ // Remove listeners
287
+ eventBus.off('player:session-changed', handler);
288
+ ```
289
+
290
+ ### ToolCoordinator
291
+
292
+ Manages z-index layering and visibility.
293
+
294
+ ```typescript
295
+ const toolCoordinator = new ToolCoordinator();
296
+
297
+ // Register tools
298
+ toolCoordinator.registerTool('calculator', 'Calculator', element);
299
+
300
+ // Manage visibility
301
+ toolCoordinator.showTool('calculator');
302
+ toolCoordinator.hideTool('calculator');
303
+ toolCoordinator.toggleTool('calculator');
304
+
305
+ // Bring to front
306
+ toolCoordinator.bringToFront(element);
307
+
308
+ // Check state
309
+ const isVisible = toolCoordinator.isToolVisible('calculator');
310
+ ```
311
+
312
+ ### HighlightCoordinator
313
+
314
+ Manages TTS and annotation highlights.
315
+
316
+ ```typescript
317
+ const highlightCoordinator = new HighlightCoordinator();
318
+
319
+ // TTS highlights (temporary)
320
+ highlightCoordinator.highlightTTSWord(textNode, start, end);
321
+ highlightCoordinator.highlightTTSSentence([range1, range2]);
322
+ highlightCoordinator.clearTTS();
323
+
324
+ // Annotation highlights (persistent)
325
+ const id = highlightCoordinator.addAnnotation(range, 'yellow');
326
+ highlightCoordinator.removeAnnotation(id);
327
+ ```
328
+
329
+ ### TTSService
330
+
331
+ Singleton text-to-speech service with QTI 3.0 accessibility catalog support.
332
+
333
+ ```typescript
334
+ import {
335
+ TTSService,
336
+ BrowserTTSProvider,
337
+ AccessibilityCatalogResolver
338
+ } from '@pie-players/pie-assessment-toolkit';
339
+
340
+ const ttsService = new TTSService();
341
+
342
+ // Initialize with provider
343
+ await ttsService.initialize(new BrowserTTSProvider());
344
+
345
+ // Set up catalog resolver for SSML support
346
+ const catalogResolver = new AccessibilityCatalogResolver(
347
+ assessment.accessibilityCatalogs,
348
+ 'en-US'
349
+ );
350
+ ttsService.setCatalogResolver(catalogResolver);
351
+
352
+ // Playback with catalog support
353
+ await ttsService.speak('Read this text', {
354
+ catalogId: 'prompt-001', // Uses pre-authored SSML if available
355
+ language: 'en-US'
356
+ });
357
+
358
+ // Plain text fallback (no catalog)
359
+ await ttsService.speak('Read this text');
360
+
361
+ // Controls
362
+ ttsService.pause();
363
+ ttsService.resume();
364
+ ttsService.stop();
365
+
366
+ // State
367
+ const isPlaying = ttsService.isPlaying();
368
+
369
+ // Dynamic settings updates (for preview/live changes)
370
+ await ttsService.updateSettings({
371
+ rate: 1.5,
372
+ pitch: 1.2,
373
+ voice: 'Matthew'
374
+ });
375
+ ```
376
+
377
+ **Unified Settings UI**: A pre-built settings component is available in `section-demos/src/lib/components/AssessmentToolkitSettings.svelte` that provides a tabbed interface for configuring TTS, highlighting, and other toolkit features. See the component's README for integration details.
378
+
379
+ ### AccessibilityCatalogResolver
380
+
381
+ Manages QTI 3.0 accessibility catalogs (SSML, sign language, braille, simplified language, etc.).
382
+
383
+ ```typescript
384
+ import { AccessibilityCatalogResolver } from '@pie-players/pie-assessment-toolkit';
385
+
386
+ // Initialize with assessment-level catalogs
387
+ const resolver = new AccessibilityCatalogResolver(
388
+ assessment.accessibilityCatalogs,
389
+ 'en-US' // default language
390
+ );
391
+
392
+ // Add item-level catalogs (higher priority)
393
+ resolver.addItemCatalogs(item.accessibilityCatalogs);
394
+
395
+ // Get alternative representation
396
+ const alternative = resolver.getAlternative('prompt-001', {
397
+ type: 'spoken',
398
+ language: 'en-US',
399
+ useFallback: true
400
+ });
401
+
402
+ // Clear item catalogs when navigating away
403
+ resolver.clearItemCatalogs();
404
+
405
+ // Get all alternatives for an identifier
406
+ const alternatives = resolver.getAllAlternatives('prompt-001');
407
+
408
+ // Check availability
409
+ const hasSpoken = resolver.hasCatalog('prompt-001');
410
+ ```
411
+
412
+ ### SSMLExtractor
413
+
414
+ Automatically extracts embedded `<speak>` tags from PIE content and generates QTI 3.0 accessibility catalogs.
415
+
416
+ ```typescript
417
+ import { SSMLExtractor } from '@pie-players/pie-assessment-toolkit';
418
+
419
+ const extractor = new SSMLExtractor();
420
+
421
+ // Extract from item config
422
+ const result = extractor.extractFromItemConfig(item.config);
423
+
424
+ // Result contains:
425
+ // - cleanedConfig: Config with SSML removed, catalog IDs added
426
+ // - catalogs: Generated accessibility catalogs
427
+
428
+ // Update item with cleaned config
429
+ item.config = result.cleanedConfig;
430
+ item.config.extractedCatalogs = result.catalogs;
431
+
432
+ // Register with catalog resolver
433
+ catalogResolver.addItemCatalogs(result.catalogs);
434
+ ```
435
+
436
+ **Example Input:**
437
+ ```typescript
438
+ {
439
+ prompt: `<div>
440
+ <speak>Solve <prosody rate="slow">x squared</prosody>.</speak>
441
+ <p>Solve x² = 0</p>
442
+ </div>`
443
+ }
444
+ ```
445
+
446
+ **Example Output:**
447
+ ```typescript
448
+ {
449
+ // Cleaned config
450
+ prompt: `<div data-catalog-id="auto-prompt-q1-0">
451
+ <p>Solve x² = 0</p>
452
+ </div>`,
453
+
454
+ // Generated catalogs
455
+ extractedCatalogs: [{
456
+ identifier: 'auto-prompt-q1-0',
457
+ cards: [{
458
+ catalog: 'spoken',
459
+ language: 'en-US',
460
+ content: '<speak>Solve <prosody rate="slow">x squared</prosody>.</speak>'
461
+ }]
462
+ }]
463
+ }
464
+ ```
465
+
466
+ **Integration:** Used automatically by section player's ItemRenderer and PassageRenderer components.
467
+
468
+ ### ThemeProvider
469
+
470
+ Accessibility theming.
471
+
472
+ ```typescript
473
+ const themeProvider = new ThemeProvider();
474
+
475
+ // Apply theme
476
+ themeProvider.applyTheme({
477
+ highContrast: true,
478
+ fontSize: 'large',
479
+ backgroundColor: '#000',
480
+ foregroundColor: '#fff'
481
+ });
482
+
483
+ // Quick settings
484
+ themeProvider.setHighContrast(true);
485
+ themeProvider.setFontSize('xlarge');
486
+ ```
487
+
488
+ ### ToolConfigResolver
489
+
490
+ IEP/504 tool configuration.
491
+
492
+ ```typescript
493
+ const resolver = new ToolConfigResolver();
494
+
495
+ // Resolve single tool
496
+ const config = resolver.resolveTool('calculator', itemConfig, rosterConfig, studentProfile);
497
+
498
+ // Resolve all tools
499
+ const allTools = resolver.resolveAll({ itemConfig, rosterConfig, studentProfile });
500
+
501
+ // Helpers
502
+ const enabled = resolver.isToolEnabled('calculator', input);
503
+ const required = resolver.isToolRequired('calculator', input);
504
+ const enabledTools = resolver.getEnabledTools(input);
505
+ ```
506
+
507
+ ## QTI 3.0 Support
508
+
509
+ The toolkit natively supports QTI 3.0 features for standards-compliant assessment delivery.
510
+
511
+ ### Personal Needs Profile (PNP)
512
+
513
+ Student accommodations and IEP/504 support with automatic tool resolution:
514
+
515
+ ```typescript
516
+ import { AssessmentPlayer, PNPToolResolver } from '@pie-players/pie-assessment-toolkit';
517
+
518
+ // QTI 3.0 assessment with PNP
519
+ const assessment = {
520
+ personalNeedsProfile: {
521
+ supports: ['textToSpeech', 'calculator'],
522
+ activateAtInit: ['textToSpeech']
523
+ },
524
+ settings: {
525
+ districtPolicy: {
526
+ blockedTools: [], // District blocks (absolute veto)
527
+ requiredTools: ['ruler'] // District requires
528
+ },
529
+ toolConfigs: {
530
+ calculator: {
531
+ type: 'scientific',
532
+ provider: 'desmos'
533
+ }
534
+ }
535
+ }
536
+ };
537
+
538
+ // Simple initialization - tools automatically resolved
539
+ const player = new AssessmentPlayer({ assessment, loadItem });
540
+
541
+ // Or use PNPToolResolver directly
542
+ const resolver = new PNPToolResolver();
543
+ const tools = resolver.resolveTools(assessment, currentItemRef);
544
+ // Returns: [{ id: 'pie-tool-text-to-speech', enabled: true, ... }, ...]
545
+ ```
546
+
547
+ **Standard PNP Support IDs:**
548
+
549
+ ```typescript
550
+ 'textToSpeech' → 'pie-tool-text-to-speech'
551
+ 'calculator' → 'pie-tool-calculator'
552
+ 'ruler' → 'pie-tool-ruler'
553
+ 'protractor' → 'pie-tool-protractor'
554
+ 'highlighter' → 'pie-tool-annotation-toolbar'
555
+ 'lineReader' → 'pie-tool-line-reader'
556
+ 'magnifier' → 'pie-tool-magnifier'
557
+ 'colorContrast' → 'pie-theme-contrast'
558
+ 'answerMasking' → 'pie-tool-answer-eliminator'
559
+ ```
560
+
561
+ ### Context Declarations
562
+
563
+ Global variables shared across assessment items:
564
+
565
+ ```typescript
566
+ import { AssessmentPlayer, ContextVariableStore } from '@pie-players/pie-assessment-toolkit';
567
+
568
+ // Assessment with context declarations
569
+ const assessment = {
570
+ contextDeclarations: [
571
+ {
572
+ identifier: 'RANDOM_SEED',
573
+ baseType: 'integer',
574
+ cardinality: 'single',
575
+ defaultValue: 42
576
+ },
577
+ {
578
+ identifier: 'DIFFICULTY_LEVEL',
579
+ baseType: 'string',
580
+ cardinality: 'single',
581
+ defaultValue: 'medium'
582
+ }
583
+ ]
584
+ };
585
+
586
+ // Use with AssessmentPlayer
587
+ const player = new AssessmentPlayer({ assessment, loadItem });
588
+
589
+ const seed = player.getContextVariable('RANDOM_SEED');
590
+ player.setContextVariable('DIFFICULTY_LEVEL', 'hard');
591
+
592
+ // Pass to PIE elements
593
+ const context = player.getContextVariables();
594
+ await renderItem(item, session, context);
595
+
596
+ // Or use ContextVariableStore directly
597
+ const store = new ContextVariableStore(assessment.contextDeclarations);
598
+ store.set('RANDOM_SEED', 12345);
599
+ const context = store.toObject();
600
+ ```
601
+
602
+ **Use Cases:**
603
+
604
+ - Cross-item randomization (shared random seeds)
605
+ - Adaptive testing (difficulty adjustment based on performance)
606
+ - Shared configuration (currency symbols, measurement units)
607
+ - Item dependencies (later items react to earlier responses)
608
+
609
+ ### QTI 3.0 Precedence Hierarchy
610
+
611
+ Tool resolution follows this precedence (highest to lowest):
612
+
613
+ ```
614
+ 1. District Block (absolute veto)
615
+ 2. Test Administration Override
616
+ 3. Item Restriction (per-item block)
617
+ 4. Item Requirement (forces enable)
618
+ 5. District Requirement
619
+ 6. PNP Supports (student accommodations)
620
+ ```
621
+
622
+ ## Related Documentation
623
+
624
+ - [Architecture Overview](../../../docs/ARCHITECTURE.md) - Complete system architecture
625
+ - [Assessment Toolkit Architecture](../../../docs/tools-and-accomodations/assessment-player-architecture.md) - Toolkit design
626
+ - [Tools Architecture](../../../docs/tools-and-accomodations/tools-high-level-architecture.md) - Tool coordination