@pie-players/pie-default-tool-loaders 0.3.67 → 0.3.68
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/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/packaged-capability-composition.d.ts +6 -6
- package/dist/packaged-capability-composition.js +59 -11
- package/dist/registrations/accessibility-tools.js +28 -105
- package/dist/registrations/audio-transcript.js +7 -1
- package/dist/registrations/calculator.js +40 -17
- package/dist/registrations/dictionary-tools.d.ts +75 -0
- package/dist/registrations/dictionary-tools.js +235 -0
- package/dist/registrations/interaction-tools.d.ts +0 -7
- package/dist/registrations/interaction-tools.js +4 -60
- package/dist/registrations/measurement-tools.js +13 -62
- package/dist/registrations/overlay-toolbar-render.d.ts +43 -0
- package/dist/registrations/overlay-toolbar-render.js +75 -0
- package/dist/registrations/selection-actions.d.ts +24 -0
- package/dist/registrations/selection-actions.js +73 -0
- package/dist/registrations/subject-specific-tools.js +21 -82
- package/dist/registrations/tts.js +2 -0
- package/package.json +16 -14
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ export { CONTENT_ALTERNATE_REGISTRATIONS } from "./content-alternates.js";
|
|
|
4
4
|
export { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
5
5
|
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration, resolveAudioTranscript, type ResolvedAudioTranscript, } from "./registrations/audio-transcript.js";
|
|
6
6
|
export { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
7
|
-
export {
|
|
7
|
+
export { createDictionaryToolRegistration, createPictureDictionaryToolRegistration, dictionaryToolRegistration, type DictionaryVariantOptions, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
8
|
+
export { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
8
9
|
export { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
9
10
|
export { graphToolRegistration, periodicTableToolRegistration, } from "./registrations/subject-specific-tools.js";
|
|
10
11
|
export { ttsToolRegistration } from "./registrations/tts.js";
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,8 @@ export { CONTENT_ALTERNATE_REGISTRATIONS } from "./content-alternates.js";
|
|
|
7
7
|
export { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
8
8
|
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration, resolveAudioTranscript, } from "./registrations/audio-transcript.js";
|
|
9
9
|
export { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
10
|
-
export {
|
|
10
|
+
export { createDictionaryToolRegistration, createPictureDictionaryToolRegistration, dictionaryToolRegistration, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
11
|
+
export { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
11
12
|
export { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
12
13
|
export { graphToolRegistration, periodicTableToolRegistration, } from "./registrations/subject-specific-tools.js";
|
|
13
14
|
export { ttsToolRegistration } from "./registrations/tts.js";
|
|
@@ -41,7 +41,7 @@ export type RegisterDefaultToolModuleLoadersOptions = {
|
|
|
41
41
|
* that prevents an otherwise usable assessment from rendering.
|
|
42
42
|
*/
|
|
43
43
|
export declare function assertPackagedCapabilityComposition(): void;
|
|
44
|
-
export declare const PACKAGED_TOOL_REGISTRATIONS: readonly [ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration];
|
|
44
|
+
export declare const PACKAGED_TOOL_REGISTRATIONS: readonly [ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration, ToolRegistration];
|
|
45
45
|
export declare const PACKAGED_TOOL_TAG_MAP: ToolTagMap;
|
|
46
46
|
export declare const ITEM_TOOL_MODULE_LOADERS: Record<string, ToolModuleLoader>;
|
|
47
47
|
export declare const SECTION_TOOL_MODULE_LOADERS: Record<string, ToolModuleLoader>;
|
|
@@ -49,17 +49,17 @@ export declare const DEFAULT_TOOL_MODULE_LOADERS: Record<string, ToolModuleLoade
|
|
|
49
49
|
export declare const PACKAGED_TOOL_PLACEMENT: {
|
|
50
50
|
readonly assessment: readonly ["theme"];
|
|
51
51
|
readonly section: readonly ["theme"];
|
|
52
|
-
readonly item: readonly ["textToSpeech", "
|
|
53
|
-
readonly passage: readonly ["textToSpeech", "
|
|
54
|
-
readonly rubric: readonly ["textToSpeech", "
|
|
55
|
-
readonly element: readonly ["calculator", "answerEliminator", "textToSpeech", "ruler", "protractor", "
|
|
52
|
+
readonly item: readonly ["textToSpeech", "annotationToolbar", "graph", "periodicTable", "dictionary", "pictureDictionary", "dictionarySpanish", "pictureDictionarySpanish"];
|
|
53
|
+
readonly passage: readonly ["textToSpeech", "annotationToolbar", "lineReader"];
|
|
54
|
+
readonly rubric: readonly ["textToSpeech", "annotationToolbar", "lineReader"];
|
|
55
|
+
readonly element: readonly ["calculator", "answerEliminator", "textToSpeech", "ruler", "protractor", "annotationToolbar", "graph", "periodicTable", "dictionary", "pictureDictionary", "dictionarySpanish", "pictureDictionarySpanish"];
|
|
56
56
|
};
|
|
57
57
|
export declare const SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT: {
|
|
58
58
|
section: string[];
|
|
59
59
|
item: string[];
|
|
60
60
|
passage: string[];
|
|
61
61
|
};
|
|
62
|
-
export declare const PACKAGED_TOOL_ORDER: readonly ["theme", "calculator", "textToSpeech", "lineReader", "annotationToolbar", "
|
|
62
|
+
export declare const PACKAGED_TOOL_ORDER: readonly ["theme", "calculator", "textToSpeech", "lineReader", "annotationToolbar", "answerEliminator", "ruler", "protractor", "graph", "periodicTable", "dictionary", "pictureDictionary", "dictionarySpanish", "pictureDictionarySpanish"];
|
|
63
63
|
export declare const UNIVERSAL_SUPPORTS_PRESET: readonly string[];
|
|
64
64
|
/** Register packaged PIE capabilities onto an existing registry. */
|
|
65
65
|
export declare function registerPackagedTools(registry: ToolRegistry, options?: RegisterPackagedToolsOptions): void;
|
|
@@ -11,7 +11,8 @@ import { ToolRegistry, } from "@pie-players/pie-assessment-toolkit/tools/interna
|
|
|
11
11
|
import { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
12
12
|
import { audioTranscriptRegistration } from "./registrations/audio-transcript.js";
|
|
13
13
|
import { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
14
|
-
import {
|
|
14
|
+
import { dictionaryToolRegistration, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
15
|
+
import { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
15
16
|
import { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
16
17
|
import { graphToolRegistration, periodicTableToolRegistration, } from "./registrations/subject-specific-tools.js";
|
|
17
18
|
import { ttsToolRegistration } from "./registrations/tts.js";
|
|
@@ -33,6 +34,8 @@ const loadLineReaderModule = () => loadSideEffectModule(() => import("@pie-playe
|
|
|
33
34
|
const loadThemeModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-theme"));
|
|
34
35
|
const loadGraphModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-graph"));
|
|
35
36
|
const loadPeriodicTableModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-periodic-table"));
|
|
37
|
+
const loadDictionaryModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-dictionary"));
|
|
38
|
+
const loadPictureDictionaryModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-picture-dictionary"));
|
|
36
39
|
const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
37
40
|
{
|
|
38
41
|
registration: calculatorToolRegistration,
|
|
@@ -94,15 +97,6 @@ const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
|
94
97
|
"choiceMasking",
|
|
95
98
|
],
|
|
96
99
|
},
|
|
97
|
-
{
|
|
98
|
-
registration: highlighterToolRegistration,
|
|
99
|
-
tagName: "pie-tool-annotation-toolbar",
|
|
100
|
-
loadModule: loadAnnotationToolbarModule,
|
|
101
|
-
loaderTargets: ["item"],
|
|
102
|
-
placementOrder: { item: 20, passage: 20, rubric: 20, element: 60 },
|
|
103
|
-
toolbarOrder: 60,
|
|
104
|
-
universalSupportIds: ["highlighter", "textHighlight", "annotation"],
|
|
105
|
-
},
|
|
106
100
|
{
|
|
107
101
|
registration: lineReaderToolRegistration,
|
|
108
102
|
tagName: "pie-tool-line-reader",
|
|
@@ -144,7 +138,16 @@ const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
|
144
138
|
placementOrder: { item: 30, passage: 30, rubric: 30, element: 70 },
|
|
145
139
|
preferredPlacementOrder: { item: 40, passage: 20 },
|
|
146
140
|
toolbarOrder: 50,
|
|
147
|
-
|
|
141
|
+
// The last three came from the `highlighter` capability, which mounted this
|
|
142
|
+
// same element behind a second identically-labelled button. Kept here so a
|
|
143
|
+
// profile granted one of the older ids still gets highlighting.
|
|
144
|
+
universalSupportIds: [
|
|
145
|
+
"highlighting",
|
|
146
|
+
"annotations",
|
|
147
|
+
"highlighter",
|
|
148
|
+
"textHighlight",
|
|
149
|
+
"annotation",
|
|
150
|
+
],
|
|
148
151
|
},
|
|
149
152
|
{
|
|
150
153
|
registration: graphToolRegistration,
|
|
@@ -170,6 +173,51 @@ const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
|
170
173
|
"elementReference",
|
|
171
174
|
],
|
|
172
175
|
},
|
|
176
|
+
{
|
|
177
|
+
registration: dictionaryToolRegistration,
|
|
178
|
+
tagName: "pie-tool-dictionary",
|
|
179
|
+
loadModule: loadDictionaryModule,
|
|
180
|
+
loaderTargets: ["section"],
|
|
181
|
+
placementOrder: { item: 60, element: 100 },
|
|
182
|
+
preferredPlacementOrder: { section: 70 },
|
|
183
|
+
toolbarOrder: 120,
|
|
184
|
+
// Deliberately empty: a dictionary is a granted accommodation, and on a
|
|
185
|
+
// vocabulary item it is construct-relevant, so it is never universal.
|
|
186
|
+
universalSupportIds: [],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
registration: pictureDictionaryToolRegistration,
|
|
190
|
+
tagName: "pie-tool-picture-dictionary",
|
|
191
|
+
loadModule: loadPictureDictionaryModule,
|
|
192
|
+
loaderTargets: ["section"],
|
|
193
|
+
placementOrder: { item: 70, element: 110 },
|
|
194
|
+
preferredPlacementOrder: { section: 80 },
|
|
195
|
+
toolbarOrder: 130,
|
|
196
|
+
universalSupportIds: [],
|
|
197
|
+
},
|
|
198
|
+
// The Spanish variants render the same elements under their own capability ids, so a
|
|
199
|
+
// programme can grant a Spanish gloss beside the content-following dictionary or
|
|
200
|
+
// instead of it. Ordered after both, since English-content delivery is the common case.
|
|
201
|
+
{
|
|
202
|
+
registration: spanishDictionaryToolRegistration,
|
|
203
|
+
tagName: "pie-tool-dictionary",
|
|
204
|
+
loadModule: loadDictionaryModule,
|
|
205
|
+
loaderTargets: ["section"],
|
|
206
|
+
placementOrder: { item: 80, element: 120 },
|
|
207
|
+
preferredPlacementOrder: { section: 90 },
|
|
208
|
+
toolbarOrder: 140,
|
|
209
|
+
universalSupportIds: [],
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
registration: spanishPictureDictionaryToolRegistration,
|
|
213
|
+
tagName: "pie-tool-picture-dictionary",
|
|
214
|
+
loadModule: loadPictureDictionaryModule,
|
|
215
|
+
loaderTargets: ["section"],
|
|
216
|
+
placementOrder: { item: 90, element: 130 },
|
|
217
|
+
preferredPlacementOrder: { section: 100 },
|
|
218
|
+
toolbarOrder: 150,
|
|
219
|
+
universalSupportIds: [],
|
|
220
|
+
},
|
|
173
221
|
{
|
|
174
222
|
registration: audioTranscriptRegistration,
|
|
175
223
|
universalSupportIds: [],
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
import { hasReadableText } from "@pie-players/pie-assessment-toolkit/tools/internal";
|
|
14
14
|
import { createToolElement, resolveToolTag, } from "@pie-players/pie-assessment-toolkit/tools/internal";
|
|
15
15
|
import { applyOverlaySurface, createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/internal";
|
|
16
|
+
import { buildSelectionActions } from "./selection-actions.js";
|
|
17
|
+
import { renderOverlayToolbar } from "./overlay-toolbar-render.js";
|
|
16
18
|
/**
|
|
17
19
|
* Line Reader tool registration
|
|
18
20
|
*
|
|
@@ -23,6 +25,8 @@ export const lineReaderToolRegistration = {
|
|
|
23
25
|
toolId: "lineReader",
|
|
24
26
|
name: "Line Reader",
|
|
25
27
|
description: "Reading guide overlay",
|
|
28
|
+
nameKey: "tools.lineReader.name",
|
|
29
|
+
descriptionKey: "tools.lineReader.description",
|
|
26
30
|
icon: "bars-3",
|
|
27
31
|
// Line reader appears where there's text to read
|
|
28
32
|
supportedLevels: ["section", "passage", "rubric", "item"],
|
|
@@ -42,37 +46,10 @@ export const lineReaderToolRegistration = {
|
|
|
42
46
|
return hasReadableText(context);
|
|
43
47
|
},
|
|
44
48
|
renderToolbar(context, toolbarContext) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
50
|
-
disabled: false,
|
|
51
|
-
ariaLabel: "Line reader - Reading guide",
|
|
52
|
-
tooltip: "Line Reader",
|
|
53
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
54
|
-
active: visibility.isActive(),
|
|
55
|
-
};
|
|
56
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
57
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
58
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
59
|
-
applyOverlaySurface(overlay, "frameless");
|
|
60
|
-
return {
|
|
61
|
-
toolId: this.toolId,
|
|
62
|
-
button,
|
|
63
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
64
|
-
sync: () => {
|
|
65
|
-
syncButtonAndOverlayVisibility({
|
|
66
|
-
button,
|
|
67
|
-
overlay,
|
|
68
|
-
isActive: visibility.isActive,
|
|
69
|
-
});
|
|
70
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
71
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
subscribeActive: visibility.subscribeActive,
|
|
75
|
-
};
|
|
49
|
+
return renderOverlayToolbar(this, context, toolbarContext, {
|
|
50
|
+
surface: "frameless",
|
|
51
|
+
handsOverCoordinator: true,
|
|
52
|
+
});
|
|
76
53
|
},
|
|
77
54
|
};
|
|
78
55
|
/**
|
|
@@ -85,6 +62,8 @@ export const themeToolRegistration = {
|
|
|
85
62
|
toolId: "theme",
|
|
86
63
|
name: "Theme",
|
|
87
64
|
description: "Accessible themes and contrast",
|
|
65
|
+
nameKey: "tools.theme.name",
|
|
66
|
+
descriptionKey: "tools.theme.description",
|
|
88
67
|
icon: "swatch",
|
|
89
68
|
// Color scheme is assessment-wide
|
|
90
69
|
supportedLevels: ["assessment", "section"],
|
|
@@ -105,51 +84,16 @@ export const themeToolRegistration = {
|
|
|
105
84
|
return true; // Always show if allowed by orchestrator
|
|
106
85
|
},
|
|
107
86
|
renderToolbar(context, toolbarContext) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
tooltip: "Theme",
|
|
116
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
117
|
-
active: visibility.isActive(),
|
|
118
|
-
};
|
|
119
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
120
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
121
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
122
|
-
return {
|
|
123
|
-
toolId: this.toolId,
|
|
124
|
-
button,
|
|
125
|
-
elements: [
|
|
126
|
-
{
|
|
127
|
-
element: overlay,
|
|
128
|
-
mount: "after-buttons",
|
|
129
|
-
shell: {
|
|
130
|
-
title: this.name,
|
|
131
|
-
draggable: true,
|
|
132
|
-
resizable: false,
|
|
133
|
-
closeable: true,
|
|
134
|
-
initialWidth: 520,
|
|
135
|
-
initialHeight: 380,
|
|
136
|
-
minWidth: 420,
|
|
137
|
-
minHeight: 300,
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
sync: () => {
|
|
142
|
-
syncButtonAndOverlayVisibility({
|
|
143
|
-
button,
|
|
144
|
-
overlay,
|
|
145
|
-
isActive: visibility.isActive,
|
|
146
|
-
});
|
|
147
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
148
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
149
|
-
}
|
|
87
|
+
return renderOverlayToolbar(this, context, toolbarContext, {
|
|
88
|
+
shell: {
|
|
89
|
+
resizable: false,
|
|
90
|
+
initialWidth: 520,
|
|
91
|
+
initialHeight: 380,
|
|
92
|
+
minWidth: 420,
|
|
93
|
+
minHeight: 300,
|
|
150
94
|
},
|
|
151
|
-
|
|
152
|
-
};
|
|
95
|
+
handsOverCoordinator: true,
|
|
96
|
+
});
|
|
153
97
|
},
|
|
154
98
|
};
|
|
155
99
|
/**
|
|
@@ -162,6 +106,8 @@ export const annotationToolbarRegistration = {
|
|
|
162
106
|
toolId: "annotationToolbar",
|
|
163
107
|
name: "Highlighter",
|
|
164
108
|
description: "Highlight and annotate text",
|
|
109
|
+
nameKey: "tools.annotationToolbar.name",
|
|
110
|
+
descriptionKey: "tools.annotationToolbar.description",
|
|
165
111
|
icon: "highlighter",
|
|
166
112
|
activation: "selection-gateway",
|
|
167
113
|
singletonScope: "section",
|
|
@@ -217,40 +163,17 @@ export const annotationToolbarRegistration = {
|
|
|
217
163
|
element.ttsService = current.services.ttsService;
|
|
218
164
|
element.highlightCoordinator =
|
|
219
165
|
current.services.toolkitCoordinator?.highlightCoordinator ?? null;
|
|
166
|
+
// The second door onto the dictionaries. The gateway renders these and
|
|
167
|
+
// knows nothing of what they open; the pairing is composition's, which is
|
|
168
|
+
// why the list is built in `selection-actions.ts` and not here.
|
|
169
|
+
element.selectionActions = buildSelectionActions(current.services);
|
|
220
170
|
};
|
|
221
171
|
applyServices(context);
|
|
222
172
|
return { element, sync: applyServices };
|
|
223
173
|
},
|
|
224
174
|
renderToolbar(context, toolbarContext) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
label: this.name,
|
|
229
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
230
|
-
disabled: false,
|
|
231
|
-
ariaLabel: "Annotation toolbar - Highlight text",
|
|
232
|
-
tooltip: "Highlight",
|
|
233
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
234
|
-
active: visibility.isActive(),
|
|
235
|
-
};
|
|
236
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
237
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
238
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
239
|
-
return {
|
|
240
|
-
toolId: this.toolId,
|
|
241
|
-
button,
|
|
242
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
243
|
-
sync: () => {
|
|
244
|
-
syncButtonAndOverlayVisibility({
|
|
245
|
-
button,
|
|
246
|
-
overlay,
|
|
247
|
-
isActive: visibility.isActive,
|
|
248
|
-
});
|
|
249
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
250
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
subscribeActive: visibility.subscribeActive,
|
|
254
|
-
};
|
|
175
|
+
return renderOverlayToolbar(this, context, toolbarContext, {
|
|
176
|
+
handsOverCoordinator: true,
|
|
177
|
+
});
|
|
255
178
|
},
|
|
256
179
|
};
|
|
@@ -144,6 +144,8 @@ export const audioTranscriptRegistration = {
|
|
|
144
144
|
toolId: AUDIO_TRANSCRIPT_FEATURE_ID,
|
|
145
145
|
name: "Audio Transcript",
|
|
146
146
|
description: "Text of an audio prompt, read before the content it transcribes",
|
|
147
|
+
nameKey: "tools.audioTranscript.name",
|
|
148
|
+
descriptionKey: "tools.audioTranscript.description",
|
|
147
149
|
supportedLevels: ["item", "passage"],
|
|
148
150
|
pnpSupportIds: [AUDIO_TRANSCRIPT_FEATURE_ID],
|
|
149
151
|
// No button to press: a transcript is either authored-visible, or granted and
|
|
@@ -173,7 +175,11 @@ export const audioTranscriptRegistration = {
|
|
|
173
175
|
applyTranscript(region, transcript);
|
|
174
176
|
return {
|
|
175
177
|
element: region,
|
|
176
|
-
|
|
178
|
+
// `AUDIO_TRANSCRIPT_REGION_LABEL` stays the English source and the
|
|
179
|
+
// exported constant tests address; the catalog supplies the rendered
|
|
180
|
+
// label when a host published a provider.
|
|
181
|
+
ariaLabel: context.services.i18n?.t("tools.audioTranscript.regionA11y") ??
|
|
182
|
+
AUDIO_TRANSCRIPT_REGION_LABEL,
|
|
177
183
|
// Reads the context it is handed, never the one captured above: on a
|
|
178
184
|
// re-resolve the host's context carries the current card, and a learner must
|
|
179
185
|
// not keep reading the previous item's transcript.
|
|
@@ -61,13 +61,21 @@ function getCalculatorRenderParams(toolbarContext) {
|
|
|
61
61
|
return {
|
|
62
62
|
calculatorType,
|
|
63
63
|
availableTypes,
|
|
64
|
-
displayName: calculatorType
|
|
65
|
-
? "Scientific Calculator"
|
|
66
|
-
: calculatorType === "basic"
|
|
67
|
-
? "Basic Calculator"
|
|
68
|
-
: "Calculator",
|
|
64
|
+
displayName: toolbarContext.i18n.t(CALCULATOR_NAME_KEYS[calculatorType ?? "untyped"]),
|
|
69
65
|
};
|
|
70
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* The calculator's displayed name, per host-declared type.
|
|
69
|
+
*
|
|
70
|
+
* `untyped` keeps the pre-adoption behaviour of naming the scientific
|
|
71
|
+
* calculator, which is what the toolbar has always announced when the host
|
|
72
|
+
* declares no type.
|
|
73
|
+
*/
|
|
74
|
+
const CALCULATOR_NAME_KEYS = {
|
|
75
|
+
basic: "tools.calculator.nameBasic",
|
|
76
|
+
scientific: "tools.calculator.nameScientific",
|
|
77
|
+
untyped: "tools.calculator.name",
|
|
78
|
+
};
|
|
71
79
|
function applyCalculatorParamsToElement(element, calculatorType, availableTypes) {
|
|
72
80
|
const calculatorElement = element;
|
|
73
81
|
if (calculatorType) {
|
|
@@ -97,6 +105,8 @@ export const calculatorToolRegistration = {
|
|
|
97
105
|
toolId: "calculator",
|
|
98
106
|
name: "Calculator",
|
|
99
107
|
description: "Multi-type calculator (basic, scientific, graphing)",
|
|
108
|
+
nameKey: "tools.calculator.name",
|
|
109
|
+
descriptionKey: "tools.calculator.description",
|
|
100
110
|
icon: "calculator",
|
|
101
111
|
provider: {
|
|
102
112
|
getProviderId: (config) => typeof config?.provider?.id === "string" && config.provider.id.length > 0
|
|
@@ -154,18 +164,20 @@ export const calculatorToolRegistration = {
|
|
|
154
164
|
overlay.setAttribute("tool-id", fullToolId);
|
|
155
165
|
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
156
166
|
applyCalculatorParamsToElement(overlay, calculatorType, availableTypes);
|
|
157
|
-
const openLabel = calculatorType === null
|
|
158
|
-
? "Open scientific calculator"
|
|
159
|
-
: `Open ${displayName.toLowerCase()}`;
|
|
160
|
-
const closeLabel = calculatorType === null
|
|
161
|
-
? "Close scientific calculator"
|
|
162
|
-
: `Close ${displayName.toLowerCase()}`;
|
|
163
167
|
const button = {
|
|
164
168
|
toolId: this.toolId,
|
|
165
169
|
label: displayName,
|
|
166
170
|
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
171
|
+
// Routes this button through <nds-icon-button> where the host enables NDS
|
|
172
|
+
// icons. Declared here because which capabilities render in the host's
|
|
173
|
+
// design system is a composition decision; the toolbar used to map it from
|
|
174
|
+
// the `calculator` toolId, which put a capability name in the generic core.
|
|
175
|
+
faIconName: "calculator",
|
|
167
176
|
disabled: false,
|
|
168
|
-
|
|
177
|
+
// The name stays put across open and closed. The toolbar mirrors
|
|
178
|
+
// `active` onto the button as `aria-pressed`, so the state is already
|
|
179
|
+
// exposed; a name that also swapped to "Close …" would contradict it.
|
|
180
|
+
ariaLabel: displayName,
|
|
169
181
|
tooltip: displayName,
|
|
170
182
|
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
171
183
|
active: toolbarContext.isToolVisible(fullToolId),
|
|
@@ -181,7 +193,9 @@ export const calculatorToolRegistration = {
|
|
|
181
193
|
element: overlay,
|
|
182
194
|
mount: "after-buttons",
|
|
183
195
|
shell: {
|
|
184
|
-
|
|
196
|
+
// The variant name the button already carries — "Basic Calculator",
|
|
197
|
+
// not the registration's generic one.
|
|
198
|
+
title: displayName,
|
|
185
199
|
draggable: true,
|
|
186
200
|
resizable: true,
|
|
187
201
|
closeable: true,
|
|
@@ -191,6 +205,13 @@ export const calculatorToolRegistration = {
|
|
|
191
205
|
minHeight: 420,
|
|
192
206
|
initialAlign: "bottom-right",
|
|
193
207
|
initialMargin: 16,
|
|
208
|
+
// Header controls in the host's design system, and the layout that
|
|
209
|
+
// goes with them.
|
|
210
|
+
ndsHeaderControls: true,
|
|
211
|
+
// A learner reads the question while using the calculator, so Tab and
|
|
212
|
+
// Shift+Tab cross between the page and the shell instead of cycling
|
|
213
|
+
// inside it.
|
|
214
|
+
pageTabOrder: true,
|
|
194
215
|
content: {
|
|
195
216
|
overflowY: "auto",
|
|
196
217
|
preserveMinHeight: true,
|
|
@@ -203,10 +224,12 @@ export const calculatorToolRegistration = {
|
|
|
203
224
|
const active = toolbarContext.isToolVisible(fullToolId);
|
|
204
225
|
button.active = active;
|
|
205
226
|
button.label = displayName;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
227
|
+
// Static across the toggle. The previous `Close ${name.toLowerCase()}`
|
|
228
|
+
// was a hardcoded English template built by lowercasing a localized
|
|
229
|
+
// noun — "Close rekenmachine" under nl-NL — and it is the state
|
|
230
|
+
// `aria-pressed` already carries.
|
|
231
|
+
button.ariaLabel = displayName;
|
|
232
|
+
button.tooltip = displayName;
|
|
210
233
|
if (lastVisibleState !== active) {
|
|
211
234
|
overlay.visible = active;
|
|
212
235
|
lastVisibleState = active;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dictionary Tool Registrations
|
|
3
|
+
*
|
|
4
|
+
* Word lookup and picture (symbol) lookup, each a floating panel opened from the
|
|
5
|
+
* toolbar.
|
|
6
|
+
*
|
|
7
|
+
* Neither declares a universal support id. A dictionary is a granted accommodation,
|
|
8
|
+
* not a universal affordance: on a vocabulary item it is construct-relevant, so
|
|
9
|
+
* handing it to every learner by default would change what the item measures. A
|
|
10
|
+
* programme grants it through the PNP like any other accommodation.
|
|
11
|
+
*
|
|
12
|
+
* Both panels also accept a `term` from whatever selection affordance a host offers,
|
|
13
|
+
* but neither depends on one. A sighted keyboard-only learner cannot originate a text
|
|
14
|
+
* selection in non-editable content — Chromium does not extend one with Shift+Arrow
|
|
15
|
+
* there without caret browsing, an OS toggle absent on mobile — so a selection-only
|
|
16
|
+
* dictionary is unreachable for them. The panel's own field is the keyboard route.
|
|
17
|
+
*/
|
|
18
|
+
import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
|
|
19
|
+
/**
|
|
20
|
+
* What distinguishes one dictionary capability from another.
|
|
21
|
+
*
|
|
22
|
+
* A dictionary's language belongs to the learner, not to the content: the learner who
|
|
23
|
+
* needs a Spanish gloss is reading an English passage. So a deployment that offers two
|
|
24
|
+
* languages at once composes two capabilities, each granted on its own through the PNP,
|
|
25
|
+
* rather than one capability that follows whatever the section was authored in. That is
|
|
26
|
+
* also how the delivery systems PIE is measured against ship it — English Dictionary and
|
|
27
|
+
* Spanish Dictionary as two entries a programme grants separately.
|
|
28
|
+
*
|
|
29
|
+
* Catalog keys are derived from `toolId` (`tools.<toolId>.name` and so on), which holds for
|
|
30
|
+
* every packaged variant. A host composing a variant against its own catalog passes
|
|
31
|
+
* `messageKeyPrefix`; a key that does not resolve falls back to `name` and `description`,
|
|
32
|
+
* so a host catalog that lacks one is a plain label rather than a broken button.
|
|
33
|
+
*/
|
|
34
|
+
export interface DictionaryVariantOptions {
|
|
35
|
+
/** Capability id, unique per language. Defaults to the base tool's id. */
|
|
36
|
+
toolId?: string;
|
|
37
|
+
name?: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
/** Catalog prefix for this variant's strings. Defaults to `tools.<toolId>`. */
|
|
40
|
+
messageKeyPrefix?: string;
|
|
41
|
+
/** PNP ids that grant this variant. A language variant needs its own. */
|
|
42
|
+
pnpSupportIds?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* The corpus language this capability looks words up in, as a BCP-47 tag.
|
|
45
|
+
*
|
|
46
|
+
* Sent with every lookup, outranking the toolbar's content-alternate language and
|
|
47
|
+
* outranked by a language the host names in this tool's render params. Absent on the
|
|
48
|
+
* base capabilities, which follow the content.
|
|
49
|
+
*/
|
|
50
|
+
lookupLanguage?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Dictionary tool registration
|
|
54
|
+
*
|
|
55
|
+
* Word lookup from a host-supplied service, in one language. Call this again with another
|
|
56
|
+
* `toolId`, `pnpSupportIds` and `lookupLanguage` to offer a second language beside it.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createDictionaryToolRegistration(options?: DictionaryVariantOptions): ToolRegistration;
|
|
59
|
+
/** The content-following dictionary every deployment gets. */
|
|
60
|
+
export declare const dictionaryToolRegistration: ToolRegistration;
|
|
61
|
+
/**
|
|
62
|
+
* Picture Dictionary tool registration
|
|
63
|
+
*
|
|
64
|
+
* Symbol or picture lookup from a host-supplied service. Sized wider than the word
|
|
65
|
+
* dictionary because its results are a grid rather than a column of text.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createPictureDictionaryToolRegistration(options?: DictionaryVariantOptions): ToolRegistration;
|
|
68
|
+
/** The content-following picture dictionary every deployment gets. */
|
|
69
|
+
export declare const pictureDictionaryToolRegistration: ToolRegistration;
|
|
70
|
+
/**
|
|
71
|
+
* Spanish variants, packaged because a Spanish gloss for English content is a named
|
|
72
|
+
* accommodation rather than a hypothetical. Neither appears unless a PNP grants it.
|
|
73
|
+
*/
|
|
74
|
+
export declare const spanishDictionaryToolRegistration: ToolRegistration;
|
|
75
|
+
export declare const spanishPictureDictionaryToolRegistration: ToolRegistration;
|