@pie-players/pie-default-tool-loaders 1.0.0-beta.6 → 1.0.0-beta.8
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/dist/afa-profile.d.ts +4 -0
- package/dist/afa-profile.js +4 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -2
- package/dist/registrations/audio-transcript.d.ts +0 -7
- package/dist/registrations/audio-transcript.js +1 -7
- package/dist/registrations/interaction-tools.d.ts +14 -1
- package/dist/registrations/interaction-tools.js +91 -23
- package/package.json +22 -22
package/dist/afa-profile.d.ts
CHANGED
|
@@ -43,6 +43,10 @@ export interface AfaPnpRecord {
|
|
|
43
43
|
language?: string;
|
|
44
44
|
[setting: string]: unknown;
|
|
45
45
|
};
|
|
46
|
+
"item-translation"?: {
|
|
47
|
+
language?: string;
|
|
48
|
+
[setting: string]: unknown;
|
|
49
|
+
};
|
|
46
50
|
/** One selection: the amount for all content, or for text and non-text apart. */
|
|
47
51
|
magnification?: {
|
|
48
52
|
"all-content"?: AfaZoomAmount;
|
package/dist/afa-profile.js
CHANGED
|
@@ -118,6 +118,10 @@ export function createPersonalNeedsProfileFromAfa(record) {
|
|
|
118
118
|
if (typeof signLang === "string" && signLang.length > 0) {
|
|
119
119
|
toolParameters.signLanguage = { signLang };
|
|
120
120
|
}
|
|
121
|
+
const translationLang = record["item-translation"]?.language;
|
|
122
|
+
if (typeof translationLang === "string" && translationLang.length > 0) {
|
|
123
|
+
toolParameters.itemTranslation = { language: translationLang };
|
|
124
|
+
}
|
|
121
125
|
const zoom = magnifierZoom(record.magnification);
|
|
122
126
|
if (zoom !== undefined && zoom > 1) {
|
|
123
127
|
toolParameters.magnification = { zoom };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ export { createEmptyPersonalNeedsProfile, createPackagedToolRegistry, createUniv
|
|
|
3
3
|
export { type AfaFeatureSet, type AfaPnpRecord, type AfaSpoken, type AfaZoomAmount, createPersonalNeedsProfileFromAfa, } from "./afa-profile.js";
|
|
4
4
|
export { CONTENT_ALTERNATE_REGISTRATIONS } from "./content-alternates.js";
|
|
5
5
|
export { annotationToolbarRegistration, lineReaderToolRegistration, magnificationToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
6
|
-
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration,
|
|
6
|
+
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration, resolveAudioTranscript, type ResolvedAudioTranscript, } from "./registrations/audio-transcript.js";
|
|
7
|
+
export { CONTENT_LEAD_SURFACE } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
7
8
|
export { type CalculatorProviderDefinition, type CalculatorRegistrationOptions, calculatorToolRegistration, createCalculatorToolRegistration, } from "./registrations/calculator.js";
|
|
8
9
|
export { createDictionaryToolRegistration, createPictureDictionaryToolRegistration, dictionaryToolRegistration, type DictionaryVariantOptions, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
9
|
-
export { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
10
|
+
export { type AnswerEliminatorToolConfig, answerEliminatorToolRegistration, } from "./registrations/interaction-tools.js";
|
|
10
11
|
export { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
11
12
|
export { graphToolRegistration, periodicTableToolRegistration, } from "./registrations/subject-specific-tools.js";
|
|
12
13
|
export { ttsToolRegistration } from "./registrations/tts.js";
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,13 @@ export { CONTENT_ALTERNATE_REGISTRATIONS } from "./content-alternates.js";
|
|
|
7
7
|
// Individual registrations, for a host composing a subset rather than the whole
|
|
8
8
|
// packaged set.
|
|
9
9
|
export { annotationToolbarRegistration, lineReaderToolRegistration, magnificationToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
10
|
-
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration,
|
|
10
|
+
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration, resolveAudioTranscript, } from "./registrations/audio-transcript.js";
|
|
11
|
+
// The canonical surface ids live in the toolkit; re-exported so the packaged
|
|
12
|
+
// set's surface stays unchanged.
|
|
13
|
+
export { CONTENT_LEAD_SURFACE } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
11
14
|
export { calculatorToolRegistration, createCalculatorToolRegistration, } from "./registrations/calculator.js";
|
|
12
15
|
export { createDictionaryToolRegistration, createPictureDictionaryToolRegistration, dictionaryToolRegistration, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
13
|
-
export { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
16
|
+
export { answerEliminatorToolRegistration, } from "./registrations/interaction-tools.js";
|
|
14
17
|
export { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
15
18
|
export { graphToolRegistration, periodicTableToolRegistration, } from "./registrations/subject-specific-tools.js";
|
|
16
19
|
export { ttsToolRegistration } from "./registrations/tts.js";
|
|
@@ -66,11 +66,4 @@ export interface ResolvedAudioTranscript {
|
|
|
66
66
|
* transcript is in the language of the audio it transcribes, one per prompt.
|
|
67
67
|
*/
|
|
68
68
|
export declare function resolveAudioTranscript(context: ToolContentDependencyContext): ResolvedAudioTranscript | null;
|
|
69
|
-
/**
|
|
70
|
-
* Host surface this capability fills: the full-width slot above a card's content.
|
|
71
|
-
*
|
|
72
|
-
* Item cards and passage cards open the same surface, so declaring it once
|
|
73
|
-
* reaches both — a passage can carry an audio prompt as an item can.
|
|
74
|
-
*/
|
|
75
|
-
export declare const CONTENT_LEAD_SURFACE = "content-lead";
|
|
76
69
|
export declare const audioTranscriptRegistration: ToolRegistration;
|
|
@@ -35,6 +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 { CONTENT_LEAD_SURFACE } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
38
39
|
import { toLanguageTag } from "@pie-players/pie-players-shared/i18n/language-tags";
|
|
39
40
|
/** QTI 3.0 / AfA support id gating an audio transcript. */
|
|
40
41
|
export const AUDIO_TRANSCRIPT_FEATURE_ID = "transcript";
|
|
@@ -103,13 +104,6 @@ export function resolveAudioTranscript(context) {
|
|
|
103
104
|
// and being asked anyway is the price of also serving the authored case.
|
|
104
105
|
return context.granted ? firstOnGrant : null;
|
|
105
106
|
}
|
|
106
|
-
/**
|
|
107
|
-
* Host surface this capability fills: the full-width slot above a card's content.
|
|
108
|
-
*
|
|
109
|
-
* Item cards and passage cards open the same surface, so declaring it once
|
|
110
|
-
* reaches both — a passage can carry an audio prompt as an item can.
|
|
111
|
-
*/
|
|
112
|
-
export const CONTENT_LEAD_SURFACE = "content-lead";
|
|
113
107
|
/**
|
|
114
108
|
* A labelled region holding the transcript text.
|
|
115
109
|
*
|
|
@@ -4,7 +4,20 @@
|
|
|
4
4
|
* Registers tools for interacting with question content:
|
|
5
5
|
* - Answer Eliminator (strike through answer choices)
|
|
6
6
|
*/
|
|
7
|
-
import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
7
|
+
import type { ToolProviderConfig, ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
8
|
+
/**
|
|
9
|
+
* The answer eliminator's `tools.providers.answerEliminator` entry.
|
|
10
|
+
*/
|
|
11
|
+
export interface AnswerEliminatorToolConfig extends ToolProviderConfig {
|
|
12
|
+
/**
|
|
13
|
+
* The elements the eliminator acts on, by the name `<name>` of their
|
|
14
|
+
* `@pie-element/<name>` package, such as `["multiple-choice"]`. An element
|
|
15
|
+
* must also support answer masking. Omitted, every element that supports it
|
|
16
|
+
* takes the eliminator; empty, none does. A host lists the elements whose
|
|
17
|
+
* support it has vetted.
|
|
18
|
+
*/
|
|
19
|
+
elements?: readonly string[];
|
|
20
|
+
}
|
|
8
21
|
/**
|
|
9
22
|
* Answer Eliminator tool registration
|
|
10
23
|
*
|
|
@@ -19,24 +19,84 @@ const ANSWER_MASKING = "answer-masking";
|
|
|
19
19
|
* its supports is decided by its declaration, these two included.
|
|
20
20
|
*/
|
|
21
21
|
const UNDECLARED_ANSWER_MASKING_ELEMENTS = new Set(["multiple-choice", "ebsr"]);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
// tag, or any tag the item's `elements` map binds to `@pie-element/multiple-choice`.
|
|
25
|
-
function isUndeclaredAnswerMaskingElement(tag, packageSpec) {
|
|
26
|
-
const name = tag
|
|
22
|
+
function elementName(tag) {
|
|
23
|
+
return tag
|
|
27
24
|
.toLowerCase()
|
|
28
25
|
.replace(/--version-[0-9a-z-]+$/, "")
|
|
29
26
|
.replace(/^pie-(element-)?/, "");
|
|
30
|
-
if (UNDECLARED_ANSWER_MASKING_ELEMENTS.has(name))
|
|
31
|
-
return true;
|
|
32
|
-
const packageName = packageSpec?.match(/^@pie-element\/([^@]+)/)?.[1];
|
|
33
|
-
return !!packageName && UNDECLARED_ANSWER_MASKING_ELEMENTS.has(packageName);
|
|
34
27
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
// Content names one element several ways: `multiple-choice`,
|
|
29
|
+
// `pie-multiple-choice`, `pie-element-multiple-choice`, a runtime `--version-*`
|
|
30
|
+
// tag, or any tag the item's `elements` map binds to `@pie-element/multiple-choice`.
|
|
31
|
+
function elementNames(tag, packageSpec) {
|
|
32
|
+
const names = [elementName(tag)];
|
|
33
|
+
const packageName = pieElementPackageName(packageSpec);
|
|
34
|
+
if (packageName)
|
|
35
|
+
names.push(packageName);
|
|
36
|
+
return names;
|
|
37
|
+
}
|
|
38
|
+
function pieElementPackageName(packageSpec) {
|
|
39
|
+
return packageSpec?.match(/^@pie-element\/([^@]+)/)?.[1]?.toLowerCase() ?? null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The name an `elements` list matches: the `@pie-element/<name>` package the
|
|
43
|
+
* item binds the tag to, else the tag's own name. A tag bound to another
|
|
44
|
+
* package matches no name, whatever the tag says.
|
|
45
|
+
*/
|
|
46
|
+
function listedName(tag, packageSpec) {
|
|
47
|
+
return packageSpec ? pieElementPackageName(packageSpec) : elementName(tag);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The element names `config.elements` allows, or `null` for every element. An
|
|
51
|
+
* `elements` that is not a list allows none: validation reports it, and an
|
|
52
|
+
* element a host has not vetted stays without the eliminator.
|
|
53
|
+
*/
|
|
54
|
+
function allowedElementNames(config) {
|
|
55
|
+
const elements = config
|
|
56
|
+
?.elements;
|
|
57
|
+
if (elements === undefined)
|
|
58
|
+
return null;
|
|
59
|
+
if (!Array.isArray(elements))
|
|
60
|
+
return new Set();
|
|
61
|
+
return new Set(elements
|
|
62
|
+
.filter((name) => typeof name === "string")
|
|
63
|
+
.map(elementName));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The model ids of the context's elements that support answer masking and the
|
|
67
|
+
* host config allows.
|
|
68
|
+
*/
|
|
69
|
+
function answerMaskingElementIds(context, config) {
|
|
70
|
+
const allowed = allowedElementNames(config);
|
|
71
|
+
return elementSupports(context)
|
|
72
|
+
.filter(({ supports, tag, packageSpec }) => {
|
|
73
|
+
if (allowed) {
|
|
74
|
+
const name = listedName(tag, packageSpec);
|
|
75
|
+
if (name === null || !allowed.has(name))
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return supports
|
|
79
|
+
? supports.includes(ANSWER_MASKING)
|
|
80
|
+
: elementNames(tag, packageSpec).some((name) => UNDECLARED_ANSWER_MASKING_ELEMENTS.has(name));
|
|
81
|
+
})
|
|
82
|
+
.flatMap(({ elementId }) => (elementId ? [elementId] : []));
|
|
83
|
+
}
|
|
84
|
+
function validateAnswerEliminatorConfig(config) {
|
|
85
|
+
const { elements } = config;
|
|
86
|
+
if (elements === undefined)
|
|
87
|
+
return [];
|
|
88
|
+
if (Array.isArray(elements) &&
|
|
89
|
+
elements.every((name) => typeof name === "string" && name.trim() !== "")) {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
return [
|
|
93
|
+
{
|
|
94
|
+
code: "tools.invalidProviderConfig",
|
|
95
|
+
severity: "error",
|
|
96
|
+
path: "providers.answerEliminator.elements",
|
|
97
|
+
message: '`elements` must be a list of element names, such as ["multiple-choice"].',
|
|
98
|
+
},
|
|
99
|
+
];
|
|
40
100
|
}
|
|
41
101
|
/** The state-store key of each PIE element in the item, by model id. */
|
|
42
102
|
function resolveElementStateKeys(context, toolbarContext) {
|
|
@@ -67,23 +127,25 @@ export const answerEliminatorToolRegistration = {
|
|
|
67
127
|
descriptionKey: "tools.answerEliminator.description",
|
|
68
128
|
icon: "strikethrough",
|
|
69
129
|
supportedLevels: ["item"],
|
|
130
|
+
validateConfig: validateAnswerEliminatorConfig,
|
|
70
131
|
/**
|
|
71
132
|
* Pass 2: relevant where an element supports answer masking. An element
|
|
72
133
|
* declares it on its class, and the answer eliminator's README says what the
|
|
73
134
|
* element then supplies.
|
|
74
135
|
*/
|
|
75
136
|
isVisibleInContext(context) {
|
|
76
|
-
return
|
|
137
|
+
return answerMaskingElementIds(context, null).length > 0;
|
|
77
138
|
},
|
|
78
139
|
/**
|
|
79
|
-
* Pass 3: the same question, asked as a capability
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* answer
|
|
140
|
+
* Pass 3: the same question, asked as a capability and narrowed to the
|
|
141
|
+
* elements the host config allows. Elimination controls are rendered per
|
|
142
|
+
* choice, so an item none of whose allowed elements supports answer masking
|
|
143
|
+
* gives this tool nothing to act on. Answering the relevance gate alone left
|
|
144
|
+
* the button on such items for any learner whose profile grants answer
|
|
145
|
+
* masking.
|
|
84
146
|
*/
|
|
85
|
-
isApplicableToContent(context) {
|
|
86
|
-
return
|
|
147
|
+
isApplicableToContent(context, config) {
|
|
148
|
+
return answerMaskingElementIds(context, config).length > 0;
|
|
87
149
|
},
|
|
88
150
|
renderToolbar(context, toolbarContext) {
|
|
89
151
|
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
@@ -94,7 +156,7 @@ export const answerEliminatorToolRegistration = {
|
|
|
94
156
|
const button = {
|
|
95
157
|
toolId: this.toolId,
|
|
96
158
|
label: this.name,
|
|
97
|
-
icon:
|
|
159
|
+
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
98
160
|
disabled: false,
|
|
99
161
|
ariaLabel: toolbarContext.i18n.t("tools.answerEliminator.buttonA11y"),
|
|
100
162
|
tooltip: toolbarContext.i18n.t("tools.answerEliminator.tooltip"),
|
|
@@ -112,6 +174,12 @@ export const answerEliminatorToolRegistration = {
|
|
|
112
174
|
isActive: visibility.isActive,
|
|
113
175
|
});
|
|
114
176
|
overlay.elementStateKeys = resolveElementStateKeys(context, toolbarContext);
|
|
177
|
+
const config = toolbarContext.toolkitCoordinator?.getToolConfig(this.toolId) ??
|
|
178
|
+
null;
|
|
179
|
+
overlay.elementIds =
|
|
180
|
+
allowedElementNames(config) === null
|
|
181
|
+
? undefined
|
|
182
|
+
: answerMaskingElementIds(context, config);
|
|
115
183
|
},
|
|
116
184
|
subscribeActive: visibility.subscribeActive,
|
|
117
185
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-players/pie-default-tool-loaders",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Composition layer for the packaged PIE assessment tools: registrations, tag map, placement preset, universal and empty profiles, and lazy module loaders",
|
|
6
6
|
"repository": {
|
|
@@ -33,29 +33,29 @@
|
|
|
33
33
|
"test": "bun test"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pie-players/pie-assessment-toolkit": "1.0.0-beta.
|
|
37
|
-
"@pie-players/pie-calculator": "1.0.0-beta.
|
|
38
|
-
"@pie-players/pie-calculator-desmos": "1.0.0-beta.
|
|
39
|
-
"@pie-players/pie-calculator-geogebra": "1.0.0-beta.
|
|
40
|
-
"@pie-players/pie-players-shared": "1.0.0-beta.
|
|
41
|
-
"@pie-players/pie-tool-annotation-toolbar": "1.0.0-beta.
|
|
42
|
-
"@pie-players/pie-tool-answer-eliminator": "1.0.0-beta.
|
|
43
|
-
"@pie-players/pie-tool-calculator-shared": "1.0.0-beta.
|
|
44
|
-
"@pie-players/pie-tool-dictionary": "1.0.0-beta.
|
|
45
|
-
"@pie-players/pie-tool-graph": "1.0.0-beta.
|
|
46
|
-
"@pie-players/pie-tool-line-reader": "1.0.0-beta.
|
|
47
|
-
"@pie-players/pie-tool-magnifier": "1.0.0-beta.
|
|
48
|
-
"@pie-players/pie-tool-periodic-table": "1.0.0-beta.
|
|
49
|
-
"@pie-players/pie-tool-picture-dictionary": "1.0.0-beta.
|
|
50
|
-
"@pie-players/pie-tool-protractor": "1.0.0-beta.
|
|
51
|
-
"@pie-players/pie-tool-ruler": "1.0.0-beta.
|
|
52
|
-
"@pie-players/pie-tool-theme": "1.0.0-beta.
|
|
53
|
-
"@pie-players/pie-tool-tts-inline": "1.0.0-beta.
|
|
54
|
-
"@pie-players/tts-client-server": "1.0.0-beta.
|
|
36
|
+
"@pie-players/pie-assessment-toolkit": "1.0.0-beta.8",
|
|
37
|
+
"@pie-players/pie-calculator": "1.0.0-beta.8",
|
|
38
|
+
"@pie-players/pie-calculator-desmos": "1.0.0-beta.8",
|
|
39
|
+
"@pie-players/pie-calculator-geogebra": "1.0.0-beta.8",
|
|
40
|
+
"@pie-players/pie-players-shared": "1.0.0-beta.8",
|
|
41
|
+
"@pie-players/pie-tool-annotation-toolbar": "1.0.0-beta.8",
|
|
42
|
+
"@pie-players/pie-tool-answer-eliminator": "1.0.0-beta.8",
|
|
43
|
+
"@pie-players/pie-tool-calculator-shared": "1.0.0-beta.8",
|
|
44
|
+
"@pie-players/pie-tool-dictionary": "1.0.0-beta.8",
|
|
45
|
+
"@pie-players/pie-tool-graph": "1.0.0-beta.8",
|
|
46
|
+
"@pie-players/pie-tool-line-reader": "1.0.0-beta.8",
|
|
47
|
+
"@pie-players/pie-tool-magnifier": "1.0.0-beta.8",
|
|
48
|
+
"@pie-players/pie-tool-periodic-table": "1.0.0-beta.8",
|
|
49
|
+
"@pie-players/pie-tool-picture-dictionary": "1.0.0-beta.8",
|
|
50
|
+
"@pie-players/pie-tool-protractor": "1.0.0-beta.8",
|
|
51
|
+
"@pie-players/pie-tool-ruler": "1.0.0-beta.8",
|
|
52
|
+
"@pie-players/pie-tool-theme": "1.0.0-beta.8",
|
|
53
|
+
"@pie-players/pie-tool-tts-inline": "1.0.0-beta.8",
|
|
54
|
+
"@pie-players/tts-client-server": "1.0.0-beta.8"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@biomejs/biome": "^2.
|
|
58
|
-
"@happy-dom/global-registrator": "^
|
|
57
|
+
"@biomejs/biome": "^2.6.4",
|
|
58
|
+
"@happy-dom/global-registrator": "^21.0.4",
|
|
59
59
|
"typescript": "^5.9.3"
|
|
60
60
|
},
|
|
61
61
|
"homepage": "https://github.com/pie-framework/pie-players/tree/master/packages/default-tool-loaders#readme",
|