@pie-players/pie-default-tool-loaders 0.3.73 → 0.3.75
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.
- package/README.md +56 -58
- package/dist/calculator-providers/CortexToolProvider.d.ts +12 -0
- package/dist/calculator-providers/CortexToolProvider.js +31 -0
- package/dist/calculator-providers/DesmosToolProvider.d.ts +13 -0
- package/dist/calculator-providers/DesmosToolProvider.js +31 -0
- package/dist/calculator-providers/GeoGebraToolProvider.d.ts +15 -0
- package/dist/calculator-providers/GeoGebraToolProvider.js +31 -0
- package/dist/calculator-providers/LazyCalculatorToolProvider.d.ts +34 -0
- package/dist/calculator-providers/LazyCalculatorToolProvider.js +95 -0
- package/dist/content-alternates.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/packaged-capability-composition.d.ts +17 -49
- package/dist/packaged-capability-composition.js +61 -262
- package/dist/registrations/accessibility-tools.d.ts +1 -5
- package/dist/registrations/accessibility-tools.js +6 -41
- package/dist/registrations/audio-transcript.d.ts +1 -1
- package/dist/registrations/audio-transcript.js +0 -1
- package/dist/registrations/calculator.d.ts +2 -6
- package/dist/registrations/calculator.js +18 -73
- package/dist/registrations/dictionary-tools.d.ts +6 -5
- package/dist/registrations/dictionary-tools.js +23 -27
- package/dist/registrations/interaction-tools.d.ts +1 -7
- package/dist/registrations/interaction-tools.js +24 -28
- package/dist/registrations/measurement-tools.d.ts +1 -5
- package/dist/registrations/measurement-tools.js +1 -19
- package/dist/registrations/overlay-element-cache.d.ts +23 -0
- package/dist/registrations/overlay-element-cache.js +48 -0
- package/dist/registrations/overlay-toolbar-render.d.ts +3 -10
- package/dist/registrations/overlay-toolbar-render.js +5 -8
- package/dist/registrations/selection-actions.d.ts +1 -1
- package/dist/registrations/selection-actions.js +1 -1
- package/dist/registrations/subject-specific-tools.d.ts +3 -8
- package/dist/registrations/subject-specific-tools.js +10 -26
- package/dist/registrations/tts.d.ts +1 -6
- package/dist/registrations/tts.js +41 -90
- package/package.json +24 -21
- package/dist/packaged-tool-registry.d.ts +0 -2
- package/dist/packaged-tool-registry.js +0 -1
- package/dist/tool-placement.d.ts +0 -1
- package/dist/tool-placement.js +0 -1
- package/dist/tool-tag-map.d.ts +0 -1
- package/dist/tool-tag-map.js +0 -1
- package/dist/universal-supports.d.ts +0 -1
- package/dist/universal-supports.js +0 -1
|
@@ -2,49 +2,26 @@
|
|
|
2
2
|
* The one authored description of PIE's packaged capability composition.
|
|
3
3
|
*
|
|
4
4
|
* Registrations describe what a capability can do. This module owns the
|
|
5
|
-
* deployment decisions around them: element tags, lazy module
|
|
6
|
-
* placement
|
|
5
|
+
* deployment decisions around them: element tags, lazy module loaders, the
|
|
6
|
+
* section-player placement preset and the explicit universal-support policy.
|
|
7
7
|
* Public constants are projections of this composition so adding a capability
|
|
8
8
|
* cannot leave a second hand-maintained catalogue silently behind.
|
|
9
9
|
*/
|
|
10
|
-
import { ToolRegistry, } from "@pie-players/pie-assessment-toolkit/tools/
|
|
10
|
+
import { ToolRegistry, } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
11
11
|
import { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
12
12
|
import { audioTranscriptRegistration } from "./registrations/audio-transcript.js";
|
|
13
|
-
import { calculatorToolRegistration
|
|
13
|
+
import { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
14
14
|
import { dictionaryToolRegistration, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
15
15
|
import { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
16
16
|
import { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
17
17
|
import { graphToolRegistration, periodicTableToolRegistration, } from "./registrations/subject-specific-tools.js";
|
|
18
18
|
import { ttsToolRegistration } from "./registrations/tts.js";
|
|
19
19
|
const loadSideEffectModule = (load) => load().then(() => undefined);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
return loadSideEffectModule(load);
|
|
27
|
-
}
|
|
28
|
-
const loadDesmosCalculatorModule = () => loadCalculatorElement("pie-tool-calculator", () => import("@pie-players/pie-tool-calculator-shared/calculator-element"));
|
|
29
|
-
const loadGeoGebraCalculatorModule = () => loadCalculatorElement("pie-tool-calculator-geogebra", () => import("@pie-players/pie-tool-calculator-geogebra"));
|
|
30
|
-
const loadCortexCalculatorModule = () => loadCalculatorElement("pie-tool-calculator-cortex", () => import("@pie-players/pie-tool-calculator-cortex"));
|
|
31
|
-
const CALCULATOR_DELIVERY = {
|
|
32
|
-
"calculator-desmos": {
|
|
33
|
-
tagName: "pie-tool-calculator",
|
|
34
|
-
loadModule: loadDesmosCalculatorModule,
|
|
35
|
-
},
|
|
36
|
-
"calculator-geogebra": {
|
|
37
|
-
tagName: "pie-tool-calculator-geogebra",
|
|
38
|
-
loadModule: loadGeoGebraCalculatorModule,
|
|
39
|
-
},
|
|
40
|
-
"calculator-cortex": {
|
|
41
|
-
tagName: "pie-tool-calculator-cortex",
|
|
42
|
-
loadModule: loadCortexCalculatorModule,
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
function resolveCalculatorDelivery(config) {
|
|
46
|
-
return CALCULATOR_DELIVERY[resolveCalculatorProviderId(config)];
|
|
47
|
-
}
|
|
20
|
+
// One element serves every calculator provider; the toolkit picks the provider
|
|
21
|
+
// from `tools.providers.calculator` when the element mounts.
|
|
22
|
+
const loadCalculatorModule = () => globalThis.customElements?.get("pie-tool-calculator")
|
|
23
|
+
? Promise.resolve()
|
|
24
|
+
: loadSideEffectModule(() => import("@pie-players/pie-tool-calculator-shared/calculator-element"));
|
|
48
25
|
const loadTtsModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-tts-inline"));
|
|
49
26
|
const loadRulerModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-ruler"));
|
|
50
27
|
const loadProtractorModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-protractor"));
|
|
@@ -59,133 +36,89 @@ const loadPictureDictionaryModule = () => loadSideEffectModule(() => import("@pi
|
|
|
59
36
|
const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
60
37
|
{
|
|
61
38
|
registration: calculatorToolRegistration,
|
|
62
|
-
tagName:
|
|
63
|
-
loadModule:
|
|
64
|
-
loaderTargets: ["item", "section"],
|
|
65
|
-
placementOrder: { element: 10 },
|
|
39
|
+
tagName: "pie-tool-calculator",
|
|
40
|
+
loadModule: loadCalculatorModule,
|
|
66
41
|
preferredPlacementOrder: { item: 10 },
|
|
67
|
-
|
|
68
|
-
universalSupportIds: ["calculator", "graphingCalculator"],
|
|
42
|
+
universal: true,
|
|
69
43
|
},
|
|
70
44
|
{
|
|
71
45
|
registration: ttsToolRegistration,
|
|
72
|
-
tagName: "pie-tool-
|
|
46
|
+
tagName: "pie-tool-tts-inline",
|
|
73
47
|
loadModule: loadTtsModule,
|
|
74
|
-
loaderTargets: ["item"],
|
|
75
|
-
placementOrder: { item: 10, passage: 10, rubric: 10, element: 30 },
|
|
76
48
|
preferredPlacementOrder: { item: 20, passage: 10 },
|
|
77
|
-
|
|
78
|
-
universalSupportIds: ["textToSpeech", "readAloud"],
|
|
49
|
+
universal: true,
|
|
79
50
|
},
|
|
80
51
|
{
|
|
81
52
|
registration: rulerToolRegistration,
|
|
82
53
|
tagName: "pie-tool-ruler",
|
|
83
54
|
loadModule: loadRulerModule,
|
|
84
|
-
loaderTargets: ["section"],
|
|
85
|
-
placementOrder: { element: 40 },
|
|
86
55
|
preferredPlacementOrder: { section: 50 },
|
|
87
|
-
|
|
88
|
-
universalSupportIds: ["ruler"],
|
|
56
|
+
universal: true,
|
|
89
57
|
},
|
|
90
58
|
{
|
|
91
59
|
registration: protractorToolRegistration,
|
|
92
60
|
tagName: "pie-tool-protractor",
|
|
93
61
|
loadModule: loadProtractorModule,
|
|
94
|
-
loaderTargets: ["section"],
|
|
95
|
-
placementOrder: { element: 50 },
|
|
96
62
|
preferredPlacementOrder: { section: 60 },
|
|
97
|
-
|
|
98
|
-
universalSupportIds: ["protractor"],
|
|
63
|
+
universal: true,
|
|
99
64
|
},
|
|
100
65
|
{
|
|
101
66
|
registration: answerEliminatorToolRegistration,
|
|
102
67
|
tagName: "pie-tool-answer-eliminator",
|
|
103
68
|
loadModule: loadAnswerEliminatorModule,
|
|
104
|
-
loaderTargets: ["item"],
|
|
105
|
-
placementOrder: { element: 20 },
|
|
106
69
|
preferredPlacementOrder: { item: 30 },
|
|
107
|
-
|
|
108
|
-
universalSupportIds: ["answerMasking", "answerEliminator", "strikethrough"],
|
|
70
|
+
universal: true,
|
|
109
71
|
},
|
|
110
72
|
{
|
|
111
73
|
registration: lineReaderToolRegistration,
|
|
112
74
|
tagName: "pie-tool-line-reader",
|
|
113
75
|
loadModule: loadLineReaderModule,
|
|
114
|
-
loaderTargets: ["section"],
|
|
115
|
-
placementOrder: { passage: 40, rubric: 40 },
|
|
116
76
|
preferredPlacementOrder: { section: 40 },
|
|
117
|
-
|
|
118
|
-
universalSupportIds: ["readingMask", "readingGuide", "readingRuler"],
|
|
77
|
+
universal: true,
|
|
119
78
|
},
|
|
120
79
|
{
|
|
121
80
|
registration: themeToolRegistration,
|
|
122
81
|
tagName: "pie-tool-theme",
|
|
123
82
|
loadModule: loadThemeModule,
|
|
124
|
-
loaderTargets: ["item"],
|
|
125
|
-
placementOrder: { assessment: 10, section: 10 },
|
|
126
83
|
preferredPlacementOrder: { section: 10 },
|
|
127
|
-
|
|
128
|
-
universalSupportIds: [
|
|
129
|
-
"highContrastDisplay",
|
|
130
|
-
"colorContrast",
|
|
131
|
-
"invertColors",
|
|
132
|
-
"theme",
|
|
133
|
-
],
|
|
84
|
+
universal: true,
|
|
134
85
|
},
|
|
135
86
|
{
|
|
136
87
|
registration: annotationToolbarRegistration,
|
|
137
88
|
tagName: "pie-tool-annotation-toolbar",
|
|
138
89
|
loadModule: loadAnnotationToolbarModule,
|
|
139
|
-
loaderTargets: ["item"],
|
|
140
|
-
placementOrder: { item: 30, passage: 30, rubric: 30, element: 70 },
|
|
141
90
|
preferredPlacementOrder: { item: 40, passage: 20 },
|
|
142
|
-
|
|
143
|
-
// The last three came from the `highlighter` capability, which mounted this
|
|
144
|
-
// same element behind a second identically-labelled button. Kept here so a
|
|
145
|
-
// profile granted one of the older ids still gets highlighting.
|
|
146
|
-
universalSupportIds: ["highlighting", "annotations"],
|
|
91
|
+
universal: true,
|
|
147
92
|
},
|
|
148
93
|
{
|
|
149
94
|
registration: graphToolRegistration,
|
|
150
95
|
tagName: "pie-tool-graph",
|
|
151
96
|
loadModule: loadGraphModule,
|
|
152
|
-
loaderTargets: ["section"],
|
|
153
|
-
placementOrder: { item: 40, element: 80 },
|
|
154
97
|
preferredPlacementOrder: { section: 20 },
|
|
155
|
-
|
|
156
|
-
universalSupportIds: ["graph"],
|
|
98
|
+
universal: true,
|
|
157
99
|
},
|
|
158
100
|
{
|
|
159
101
|
registration: periodicTableToolRegistration,
|
|
160
102
|
tagName: "pie-tool-periodic-table",
|
|
161
103
|
loadModule: loadPeriodicTableModule,
|
|
162
|
-
loaderTargets: ["section"],
|
|
163
|
-
placementOrder: { item: 50, element: 90 },
|
|
164
104
|
preferredPlacementOrder: { section: 30 },
|
|
165
|
-
|
|
166
|
-
universalSupportIds: ["periodicTable"],
|
|
105
|
+
universal: true,
|
|
167
106
|
},
|
|
168
107
|
{
|
|
169
108
|
registration: dictionaryToolRegistration,
|
|
170
109
|
tagName: "pie-tool-dictionary",
|
|
171
110
|
loadModule: loadDictionaryModule,
|
|
172
|
-
loaderTargets: ["section"],
|
|
173
|
-
placementOrder: { item: 60, element: 100 },
|
|
174
111
|
preferredPlacementOrder: { section: 70 },
|
|
175
|
-
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
universalSupportIds: [],
|
|
112
|
+
// A dictionary is a granted accommodation, and on a vocabulary item it is
|
|
113
|
+
// construct-relevant, so it is never universal.
|
|
114
|
+
universal: false,
|
|
179
115
|
},
|
|
180
116
|
{
|
|
181
117
|
registration: pictureDictionaryToolRegistration,
|
|
182
118
|
tagName: "pie-tool-picture-dictionary",
|
|
183
119
|
loadModule: loadPictureDictionaryModule,
|
|
184
|
-
loaderTargets: ["section"],
|
|
185
|
-
placementOrder: { item: 70, element: 110 },
|
|
186
120
|
preferredPlacementOrder: { section: 80 },
|
|
187
|
-
|
|
188
|
-
universalSupportIds: [],
|
|
121
|
+
universal: false,
|
|
189
122
|
},
|
|
190
123
|
// The Spanish variants render the same elements under their own capability ids, so a
|
|
191
124
|
// programme can grant a Spanish gloss beside the content-following dictionary or
|
|
@@ -194,35 +127,21 @@ const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
|
194
127
|
registration: spanishDictionaryToolRegistration,
|
|
195
128
|
tagName: "pie-tool-dictionary",
|
|
196
129
|
loadModule: loadDictionaryModule,
|
|
197
|
-
loaderTargets: ["section"],
|
|
198
|
-
placementOrder: { item: 80, element: 120 },
|
|
199
130
|
preferredPlacementOrder: { section: 90 },
|
|
200
|
-
|
|
201
|
-
universalSupportIds: [],
|
|
131
|
+
universal: false,
|
|
202
132
|
},
|
|
203
133
|
{
|
|
204
134
|
registration: spanishPictureDictionaryToolRegistration,
|
|
205
135
|
tagName: "pie-tool-picture-dictionary",
|
|
206
136
|
loadModule: loadPictureDictionaryModule,
|
|
207
|
-
loaderTargets: ["section"],
|
|
208
|
-
placementOrder: { item: 90, element: 130 },
|
|
209
137
|
preferredPlacementOrder: { section: 100 },
|
|
210
|
-
|
|
211
|
-
universalSupportIds: [],
|
|
138
|
+
universal: false,
|
|
212
139
|
},
|
|
213
140
|
{
|
|
214
141
|
registration: audioTranscriptRegistration,
|
|
215
|
-
|
|
142
|
+
universal: false,
|
|
216
143
|
},
|
|
217
144
|
];
|
|
218
|
-
const PACKAGED_PLACEMENT_LEVELS = [
|
|
219
|
-
"assessment",
|
|
220
|
-
"section",
|
|
221
|
-
"item",
|
|
222
|
-
"passage",
|
|
223
|
-
"rubric",
|
|
224
|
-
"element",
|
|
225
|
-
];
|
|
226
145
|
const PREFERRED_PLACEMENT_LEVELS = ["section", "item", "passage"];
|
|
227
146
|
function assertUniqueWeights(definitions, levels, read, field) {
|
|
228
147
|
for (const level of levels) {
|
|
@@ -243,8 +162,6 @@ function assertUniqueWeights(definitions, levels, read, field) {
|
|
|
243
162
|
}
|
|
244
163
|
function assertComposition(definitions) {
|
|
245
164
|
const toolIds = new Set();
|
|
246
|
-
const universalSupportIds = new Set();
|
|
247
|
-
const toolbarOrders = new Set();
|
|
248
165
|
for (const definition of definitions) {
|
|
249
166
|
const { registration } = definition;
|
|
250
167
|
if (!registration.toolId.trim()) {
|
|
@@ -258,9 +175,6 @@ function assertComposition(definitions) {
|
|
|
258
175
|
if (isRegion) {
|
|
259
176
|
if (definition.tagName !== undefined ||
|
|
260
177
|
definition.loadModule !== undefined ||
|
|
261
|
-
definition.loaderTargets !== undefined ||
|
|
262
|
-
definition.toolbarOrder !== undefined ||
|
|
263
|
-
Object.keys(definition.placementOrder ?? {}).length > 0 ||
|
|
264
178
|
Object.keys(definition.preferredPlacementOrder ?? {}).length > 0) {
|
|
265
179
|
throw new Error(`Invalid packaged capability "${registration.toolId}": a region capability is surface-hosted and cannot declare element delivery or toolbar placement.`);
|
|
266
180
|
}
|
|
@@ -269,44 +183,12 @@ function assertComposition(definitions) {
|
|
|
269
183
|
if (!definition.tagName?.includes("-")) {
|
|
270
184
|
throw new Error(`Invalid packaged capability "${registration.toolId}": element-backed capabilities need a custom-element tag.`);
|
|
271
185
|
}
|
|
272
|
-
if (typeof definition.loadModule !== "function"
|
|
273
|
-
|
|
274
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": element-backed capabilities need a lazy loader and at least one bootstrap target.`);
|
|
275
|
-
}
|
|
276
|
-
if (new Set(definition.loaderTargets).size !==
|
|
277
|
-
definition.loaderTargets.length) {
|
|
278
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": loader bootstrap targets must be unique.`);
|
|
186
|
+
if (typeof definition.loadModule !== "function") {
|
|
187
|
+
throw new Error(`Invalid packaged capability "${registration.toolId}": element-backed capabilities need a lazy loader.`);
|
|
279
188
|
}
|
|
280
|
-
if (definition.toolbarOrder === undefined) {
|
|
281
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": toolbar capabilities need an order.`);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (definition.toolbarOrder !== undefined) {
|
|
285
|
-
if (!Number.isSafeInteger(definition.toolbarOrder) ||
|
|
286
|
-
definition.toolbarOrder < 0) {
|
|
287
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": toolbar order must be a non-negative integer.`);
|
|
288
|
-
}
|
|
289
|
-
if (toolbarOrders.has(definition.toolbarOrder)) {
|
|
290
|
-
throw new Error(`Invalid packaged capability composition: duplicate toolbar order ${definition.toolbarOrder}.`);
|
|
291
|
-
}
|
|
292
|
-
toolbarOrders.add(definition.toolbarOrder);
|
|
293
189
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
definition.universalSupportIds.length > 0) {
|
|
297
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": content-dependent support ids cannot be universally granted.`);
|
|
298
|
-
}
|
|
299
|
-
for (const supportId of definition.universalSupportIds) {
|
|
300
|
-
if (!supportId.trim()) {
|
|
301
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": universal support ids must be non-empty.`);
|
|
302
|
-
}
|
|
303
|
-
if (!registrationSupportIds.has(supportId)) {
|
|
304
|
-
throw new Error(`Invalid packaged capability "${registration.toolId}": universal support id "${supportId}" is not declared by its registration.`);
|
|
305
|
-
}
|
|
306
|
-
if (universalSupportIds.has(supportId)) {
|
|
307
|
-
throw new Error(`Invalid packaged capability composition: universal support id "${supportId}" has more than one owner.`);
|
|
308
|
-
}
|
|
309
|
-
universalSupportIds.add(supportId);
|
|
190
|
+
if (registration.requiresAuthoredContent && definition.universal) {
|
|
191
|
+
throw new Error(`Invalid packaged capability "${registration.toolId}": a content-dependent capability cannot be universally granted.`);
|
|
310
192
|
}
|
|
311
193
|
for (const level of PREFERRED_PLACEMENT_LEVELS) {
|
|
312
194
|
if (definition.preferredPlacementOrder?.[level] !== undefined &&
|
|
@@ -315,7 +197,6 @@ function assertComposition(definitions) {
|
|
|
315
197
|
}
|
|
316
198
|
}
|
|
317
199
|
}
|
|
318
|
-
assertUniqueWeights(definitions, PACKAGED_PLACEMENT_LEVELS, (definition) => definition.placementOrder, "placementOrder");
|
|
319
200
|
assertUniqueWeights(definitions, PREFERRED_PLACEMENT_LEVELS, (definition) => definition.preferredPlacementOrder, "preferredPlacementOrder");
|
|
320
201
|
}
|
|
321
202
|
function orderedToolIds(definitions, level, read) {
|
|
@@ -331,12 +212,8 @@ class PackagedCapabilityComposition {
|
|
|
331
212
|
definitions;
|
|
332
213
|
registrations;
|
|
333
214
|
toolTagMap;
|
|
334
|
-
|
|
335
|
-
sectionModuleLoaders;
|
|
336
|
-
defaultModuleLoaders;
|
|
337
|
-
placement;
|
|
215
|
+
moduleLoaders;
|
|
338
216
|
preferredPlacement;
|
|
339
|
-
toolbarOrder;
|
|
340
217
|
universalSupportIds;
|
|
341
218
|
constructor(definitions) {
|
|
342
219
|
this.definitions = definitions;
|
|
@@ -344,34 +221,20 @@ class PackagedCapabilityComposition {
|
|
|
344
221
|
this.toolTagMap = Object.freeze(Object.fromEntries(definitions.flatMap((definition) => definition.tagName
|
|
345
222
|
? [[definition.registration.toolId, definition.tagName]]
|
|
346
223
|
: [])));
|
|
347
|
-
this.
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
224
|
+
this.moduleLoaders = Object.freeze(Object.fromEntries(definitions.flatMap((definition) => definition.loadModule
|
|
225
|
+
? [[definition.registration.toolId, definition.loadModule]]
|
|
226
|
+
: [])));
|
|
227
|
+
const preferredIds = (level) => Object.freeze(orderedToolIds(definitions, level, ({ preferredPlacementOrder }) => preferredPlacementOrder));
|
|
228
|
+
this.preferredPlacement = Object.freeze({
|
|
229
|
+
section: preferredIds("section"),
|
|
230
|
+
item: preferredIds("item"),
|
|
231
|
+
passage: preferredIds("passage"),
|
|
352
232
|
});
|
|
353
|
-
this.placement = Object.freeze(Object.fromEntries(PACKAGED_PLACEMENT_LEVELS.map((level) => [
|
|
354
|
-
level,
|
|
355
|
-
Object.freeze(orderedToolIds(definitions, level, (definition) => definition.placementOrder)),
|
|
356
|
-
])));
|
|
357
|
-
this.preferredPlacement = Object.freeze(Object.fromEntries(PREFERRED_PLACEMENT_LEVELS.map((level) => [
|
|
358
|
-
level,
|
|
359
|
-
Object.freeze(orderedToolIds(definitions, level, (definition) => definition.preferredPlacementOrder)),
|
|
360
|
-
])));
|
|
361
|
-
this.toolbarOrder = Object.freeze(definitions
|
|
362
|
-
.filter((definition) => definition.toolbarOrder !== undefined)
|
|
363
|
-
.slice()
|
|
364
|
-
.sort((left, right) => left.toolbarOrder - right.toolbarOrder)
|
|
365
|
-
.map(({ registration }) => registration.toolId));
|
|
366
233
|
this.universalSupportIds = Object.freeze(definitions
|
|
367
|
-
.
|
|
234
|
+
.filter((definition) => definition.universal)
|
|
235
|
+
.map(({ registration }) => registration.toolId)
|
|
368
236
|
.sort());
|
|
369
237
|
}
|
|
370
|
-
projectModuleLoaders(target) {
|
|
371
|
-
return Object.freeze(Object.fromEntries(this.definitions.flatMap((definition) => definition.loadModule && definition.loaderTargets?.includes(target)
|
|
372
|
-
? [[definition.registration.toolId, definition.loadModule]]
|
|
373
|
-
: [])));
|
|
374
|
-
}
|
|
375
238
|
selectRegistrations(toolIds) {
|
|
376
239
|
// Preserve the established fail-soft host behavior: no selection means all,
|
|
377
240
|
// and unknown ids are ignored rather than preventing known tools from loading.
|
|
@@ -380,46 +243,23 @@ class PackagedCapabilityComposition {
|
|
|
380
243
|
const selected = new Set(toolIds);
|
|
381
244
|
return this.registrations.filter(({ toolId }) => selected.has(toolId));
|
|
382
245
|
}
|
|
383
|
-
registerTools(registry, options = {}) {
|
|
384
|
-
const applyOverrides = options.applyOverrides ??
|
|
385
|
-
((registration) => registration);
|
|
386
|
-
for (const registration of this.selectRegistrations(options.toolIds)) {
|
|
387
|
-
registry.register(applyOverrides(registration));
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
246
|
createRegistry(options = {}) {
|
|
391
247
|
const registry = new ToolRegistry();
|
|
392
|
-
this.
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
});
|
|
248
|
+
for (const registration of this.selectRegistrations(options.toolIds)) {
|
|
249
|
+
registry.register(options.overrides?.[registration.toolId] ?? registration);
|
|
250
|
+
}
|
|
396
251
|
// Loader installation remains opt-in. Some hosts preload tool elements or
|
|
397
252
|
// provide their own tags; silently adding package loads here would change
|
|
398
253
|
// their bundle/runtime behavior.
|
|
399
254
|
if (options.toolModuleLoaders &&
|
|
400
255
|
Object.keys(options.toolModuleLoaders).length > 0) {
|
|
401
|
-
|
|
402
|
-
const calculatorDelivery = resolveCalculatorDelivery(options.calculatorProviderConfig);
|
|
403
|
-
// A host using the packaged default map gets a coherent provider-specific
|
|
404
|
-
// loader. A genuinely custom calculator loader remains the host's override.
|
|
405
|
-
if (options.calculatorProviderConfig &&
|
|
406
|
-
toolModuleLoaders.calculator === this.defaultModuleLoaders.calculator) {
|
|
407
|
-
toolModuleLoaders.calculator = calculatorDelivery.loadModule;
|
|
408
|
-
}
|
|
409
|
-
registry.setToolModuleLoaders(toolModuleLoaders);
|
|
256
|
+
registry.setToolModuleLoaders({ ...options.toolModuleLoaders });
|
|
410
257
|
}
|
|
411
|
-
const calculatorTagMap = options.calculatorProviderConfig
|
|
412
|
-
? {
|
|
413
|
-
calculator: resolveCalculatorDelivery(options.calculatorProviderConfig).tagName,
|
|
414
|
-
}
|
|
415
|
-
: {};
|
|
416
258
|
registry.setComponentOverrides({
|
|
417
259
|
toolTagMap: {
|
|
418
260
|
...this.toolTagMap,
|
|
419
|
-
...calculatorTagMap,
|
|
420
261
|
...(options.toolTagMap ?? {}),
|
|
421
262
|
},
|
|
422
|
-
toolComponentFactory: options.toolComponentFactory,
|
|
423
263
|
toolComponentFactories: options.toolComponentFactories,
|
|
424
264
|
});
|
|
425
265
|
return registry;
|
|
@@ -428,7 +268,6 @@ class PackagedCapabilityComposition {
|
|
|
428
268
|
return {
|
|
429
269
|
supports: [...this.universalSupportIds],
|
|
430
270
|
prohibitedSupports: [],
|
|
431
|
-
activateAtInit: [],
|
|
432
271
|
};
|
|
433
272
|
}
|
|
434
273
|
}
|
|
@@ -450,71 +289,31 @@ export const PACKAGED_TOOL_REGISTRATIONS = [
|
|
|
450
289
|
export const PACKAGED_TOOL_TAG_MAP = {
|
|
451
290
|
...packagedCapabilityComposition.toolTagMap,
|
|
452
291
|
};
|
|
453
|
-
export const ITEM_TOOL_MODULE_LOADERS = {
|
|
454
|
-
...packagedCapabilityComposition.itemModuleLoaders,
|
|
455
|
-
};
|
|
456
|
-
export const SECTION_TOOL_MODULE_LOADERS = {
|
|
457
|
-
...packagedCapabilityComposition.sectionModuleLoaders,
|
|
458
|
-
};
|
|
459
292
|
export const DEFAULT_TOOL_MODULE_LOADERS = {
|
|
460
|
-
...packagedCapabilityComposition.
|
|
461
|
-
};
|
|
462
|
-
/** Build the packaged loader map for a selected calculator provider. */
|
|
463
|
-
export function createDefaultToolModuleLoaders(options = {}) {
|
|
464
|
-
return {
|
|
465
|
-
...DEFAULT_TOOL_MODULE_LOADERS,
|
|
466
|
-
calculator: resolveCalculatorDelivery(options.calculatorProviderConfig)
|
|
467
|
-
.loadModule,
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
/** Build the section-bootstrap loader subset for a selected calculator provider. */
|
|
471
|
-
export function createSectionToolModuleLoaders(options = {}) {
|
|
472
|
-
return {
|
|
473
|
-
...SECTION_TOOL_MODULE_LOADERS,
|
|
474
|
-
calculator: resolveCalculatorDelivery(options.calculatorProviderConfig)
|
|
475
|
-
.loadModule,
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
export const PACKAGED_TOOL_PLACEMENT = {
|
|
479
|
-
assessment: [...packagedCapabilityComposition.placement.assessment],
|
|
480
|
-
section: [...packagedCapabilityComposition.placement.section],
|
|
481
|
-
item: [...packagedCapabilityComposition.placement.item],
|
|
482
|
-
passage: [...packagedCapabilityComposition.placement.passage],
|
|
483
|
-
rubric: [...packagedCapabilityComposition.placement.rubric],
|
|
484
|
-
element: [...packagedCapabilityComposition.placement.element],
|
|
293
|
+
...packagedCapabilityComposition.moduleLoaders,
|
|
485
294
|
};
|
|
486
295
|
export const SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT = {
|
|
487
296
|
section: [...packagedCapabilityComposition.preferredPlacement.section],
|
|
488
297
|
item: [...packagedCapabilityComposition.preferredPlacement.item],
|
|
489
298
|
passage: [...packagedCapabilityComposition.preferredPlacement.passage],
|
|
490
299
|
};
|
|
491
|
-
export const PACKAGED_TOOL_ORDER = [
|
|
492
|
-
...packagedCapabilityComposition.toolbarOrder,
|
|
493
|
-
];
|
|
494
|
-
export const UNIVERSAL_SUPPORTS_PRESET = packagedCapabilityComposition.universalSupportIds;
|
|
495
|
-
/** Register packaged PIE capabilities onto an existing registry. */
|
|
496
|
-
export function registerPackagedTools(registry, options = {}) {
|
|
497
|
-
packagedCapabilityComposition.registerTools(registry, options);
|
|
498
|
-
}
|
|
499
300
|
/** Create a registry holding the packaged PIE capabilities. */
|
|
500
301
|
export function createPackagedToolRegistry(options = {}) {
|
|
501
302
|
return packagedCapabilityComposition.createRegistry(options);
|
|
502
303
|
}
|
|
503
|
-
/**
|
|
304
|
+
/**
|
|
305
|
+
* A fresh profile granting the packaged set's universal capabilities, sorted by
|
|
306
|
+
* tool id. Which capabilities are universal is program policy declared on each
|
|
307
|
+
* definition; registry membership never implies it.
|
|
308
|
+
*/
|
|
504
309
|
export function createUniversalPersonalNeedsProfile() {
|
|
505
310
|
return packagedCapabilityComposition.createUniversalPersonalNeedsProfile();
|
|
506
311
|
}
|
|
507
|
-
/**
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
}
|
|
514
|
-
/** Register only the section-bootstrap loader subset, then host overrides. */
|
|
515
|
-
export function registerSectionToolModuleLoaders(registry, options = {}) {
|
|
516
|
-
registry.setToolModuleLoaders({
|
|
517
|
-
...createSectionToolModuleLoaders(options),
|
|
518
|
-
...(options.loaders ?? {}),
|
|
519
|
-
});
|
|
312
|
+
/**
|
|
313
|
+
* A fresh profile granting and prohibiting nothing. The toolkit ships no
|
|
314
|
+
* populated default: a deployment's universal set is program policy, which
|
|
315
|
+
* `createUniversalPersonalNeedsProfile` carries as data for hosts that adopt it.
|
|
316
|
+
*/
|
|
317
|
+
export function createEmptyPersonalNeedsProfile() {
|
|
318
|
+
return { supports: [], prohibitedSupports: [] };
|
|
520
319
|
}
|
|
@@ -5,12 +5,8 @@
|
|
|
5
5
|
* - Line Reader (reading guide)
|
|
6
6
|
* - Color Scheme (theme/contrast)
|
|
7
7
|
* - Annotation Toolbar (text highlighting)
|
|
8
|
-
*
|
|
9
|
-
* Maps to QTI 3.0 standard access features from:
|
|
10
|
-
* - visual category: highContrastDisplay, colorContrast
|
|
11
|
-
* - reading category: readingMask, readingGuide, highlighting
|
|
12
8
|
*/
|
|
13
|
-
import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/
|
|
9
|
+
import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
14
10
|
/**
|
|
15
11
|
* Line Reader tool registration
|
|
16
12
|
*
|
|
@@ -5,14 +5,9 @@
|
|
|
5
5
|
* - Line Reader (reading guide)
|
|
6
6
|
* - Color Scheme (theme/contrast)
|
|
7
7
|
* - Annotation Toolbar (text highlighting)
|
|
8
|
-
*
|
|
9
|
-
* Maps to QTI 3.0 standard access features from:
|
|
10
|
-
* - visual category: highContrastDisplay, colorContrast
|
|
11
|
-
* - reading category: readingMask, readingGuide, highlighting
|
|
12
8
|
*/
|
|
13
|
-
import { hasReadableText } from "@pie-players/pie-assessment-toolkit/tools/
|
|
14
|
-
import {
|
|
15
|
-
import { applyOverlaySurface, createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/internal";
|
|
9
|
+
import { hasReadableText } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
10
|
+
import { resolveToolTag, } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
16
11
|
import { buildSelectionActions } from "./selection-actions.js";
|
|
17
12
|
import { renderOverlayToolbar } from "./overlay-toolbar-render.js";
|
|
18
13
|
/**
|
|
@@ -30,13 +25,6 @@ export const lineReaderToolRegistration = {
|
|
|
30
25
|
icon: "bars-3",
|
|
31
26
|
// Line reader appears where there's text to read
|
|
32
27
|
supportedLevels: ["section", "passage", "rubric", "item"],
|
|
33
|
-
// PNP support IDs
|
|
34
|
-
// Maps to QTI 3.0 standard features: readingMask, readingGuide, readingRuler
|
|
35
|
-
pnpSupportIds: [
|
|
36
|
-
"readingMask", // QTI 3.0 standard (reading.readingMask)
|
|
37
|
-
"readingGuide", // QTI 3.0 standard (reading.readingGuide)
|
|
38
|
-
"readingRuler", // QTI 3.0 standard (reading.readingRuler)
|
|
39
|
-
],
|
|
40
28
|
/**
|
|
41
29
|
* Pass 2: Line reader is relevant when readable text is present
|
|
42
30
|
*/
|
|
@@ -46,7 +34,6 @@ export const lineReaderToolRegistration = {
|
|
|
46
34
|
renderToolbar(context, toolbarContext) {
|
|
47
35
|
return renderOverlayToolbar(this, context, toolbarContext, {
|
|
48
36
|
surface: "frameless",
|
|
49
|
-
handsOverCoordinator: true,
|
|
50
37
|
});
|
|
51
38
|
},
|
|
52
39
|
};
|
|
@@ -65,14 +52,6 @@ export const themeToolRegistration = {
|
|
|
65
52
|
icon: "swatch",
|
|
66
53
|
// Color scheme is assessment-wide
|
|
67
54
|
supportedLevels: ["assessment", "section"],
|
|
68
|
-
// PNP support IDs
|
|
69
|
-
// Maps to QTI 3.0 standard features: highContrastDisplay, colorContrast, invertColors
|
|
70
|
-
pnpSupportIds: [
|
|
71
|
-
"highContrastDisplay", // QTI 3.0 standard (visual.highContrastDisplay)
|
|
72
|
-
"colorContrast", // QTI 3.0 standard (visual.colorContrast)
|
|
73
|
-
"invertColors", // QTI 3.0 standard (visual.invertColors)
|
|
74
|
-
"theme", // Canonical id, and this registration's toolId
|
|
75
|
-
],
|
|
76
55
|
/**
|
|
77
56
|
* Pass 2: Color scheme is always relevant when allowed
|
|
78
57
|
*/
|
|
@@ -88,7 +67,6 @@ export const themeToolRegistration = {
|
|
|
88
67
|
minWidth: 420,
|
|
89
68
|
minHeight: 300,
|
|
90
69
|
},
|
|
91
|
-
handsOverCoordinator: true,
|
|
92
70
|
});
|
|
93
71
|
},
|
|
94
72
|
};
|
|
@@ -118,12 +96,6 @@ export const annotationToolbarRegistration = {
|
|
|
118
96
|
surfaces: ["section-overlay"],
|
|
119
97
|
// Annotation appears where there's text content
|
|
120
98
|
supportedLevels: ["passage", "rubric", "item", "element"],
|
|
121
|
-
// PNP support IDs
|
|
122
|
-
// Maps to QTI 3.0 standard features: highlighting, annotations
|
|
123
|
-
pnpSupportIds: [
|
|
124
|
-
"highlighting", // QTI 3.0 standard (cognitive.highlighting / reading.wordHighlighting)
|
|
125
|
-
"annotations", // QTI 3.0 standard (cognitive.annotations)
|
|
126
|
-
],
|
|
127
99
|
/**
|
|
128
100
|
* Pass 2: Annotation is relevant when readable text is present
|
|
129
101
|
*/
|
|
@@ -146,16 +118,11 @@ export const annotationToolbarRegistration = {
|
|
|
146
118
|
return null;
|
|
147
119
|
}
|
|
148
120
|
const element = document.createElement(tagName);
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
// `updateAssessment(...)`
|
|
152
|
-
// remounting — closing over the render-time services would leave the gateway
|
|
153
|
-
// highlighting into the previous session's coordinator.
|
|
121
|
+
// The gateway reads its services from the toolkit runtime context. What it
|
|
122
|
+
// takes from here is the action list, rebuilt from the current services on
|
|
123
|
+
// every sync so a mid-session `updateAssessment(...)` reaches it.
|
|
154
124
|
const applyServices = (current) => {
|
|
155
125
|
element.enabled = true;
|
|
156
|
-
element.ttsService = current.services.ttsService;
|
|
157
|
-
element.highlightCoordinator =
|
|
158
|
-
current.services.toolkitCoordinator?.highlightCoordinator ?? null;
|
|
159
126
|
// The second door onto the dictionaries. The gateway renders these and
|
|
160
127
|
// knows nothing of what they open; the pairing is composition's, which is
|
|
161
128
|
// why the list is built in `selection-actions.ts` and not here.
|
|
@@ -165,8 +132,6 @@ export const annotationToolbarRegistration = {
|
|
|
165
132
|
return { element, sync: applyServices };
|
|
166
133
|
},
|
|
167
134
|
renderToolbar(context, toolbarContext) {
|
|
168
|
-
return renderOverlayToolbar(this, context, toolbarContext
|
|
169
|
-
handsOverCoordinator: true,
|
|
170
|
-
});
|
|
135
|
+
return renderOverlayToolbar(this, context, toolbarContext);
|
|
171
136
|
},
|
|
172
137
|
};
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* absent from the universal preset — a content-dependent support never belongs in
|
|
36
36
|
* a wholesale grant.
|
|
37
37
|
*/
|
|
38
|
-
import type { ToolContentDependencyContext, ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/
|
|
38
|
+
import type { ToolContentDependencyContext, ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
39
39
|
/** QTI 3.0 / AfA support id gating an audio transcript. */
|
|
40
40
|
export declare const AUDIO_TRANSCRIPT_FEATURE_ID = "transcript";
|
|
41
41
|
/** Catalog type carrying the transcript text. */
|
|
@@ -147,7 +147,6 @@ export const audioTranscriptRegistration = {
|
|
|
147
147
|
nameKey: "tools.audioTranscript.name",
|
|
148
148
|
descriptionKey: "tools.audioTranscript.description",
|
|
149
149
|
supportedLevels: ["item", "passage"],
|
|
150
|
-
pnpSupportIds: [AUDIO_TRANSCRIPT_FEATURE_ID],
|
|
151
150
|
// No button to press: a transcript is either authored-visible, or granted and
|
|
152
151
|
// present, or absent. `region` is the activation for a capability with no
|
|
153
152
|
// toolbar presence, and tools-config validation reports a `tools.placement`
|