@pie-players/pie-assessment-toolkit 0.3.64 → 0.3.65
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 +45 -17
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +6 -6
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-cckwpz6c.js +51 -0
- package/dist/components/chunks/ItemToolBar-pryf0rtz.js +22 -0
- package/dist/index.d.ts +5 -6
- package/dist/index.js +9 -4
- package/dist/runtime/composition-emit-scheduler.d.ts +78 -0
- package/dist/runtime/composition-emit-scheduler.js +154 -0
- package/dist/runtime/core/engine-resolver.d.ts +1 -1
- package/dist/services/ToolRegistry.d.ts +218 -8
- package/dist/services/ToolRegistry.js +124 -8
- package/dist/services/ToolkitCoordinator.d.ts +2 -1
- package/dist/services/ToolkitCoordinator.js +23 -6
- package/dist/services/createDefaultToolRegistry.d.ts +25 -58
- package/dist/services/createDefaultToolRegistry.js +24 -104
- package/dist/services/defaultPersonalNeedsProfile.d.ts +16 -14
- package/dist/services/defaultPersonalNeedsProfile.js +17 -38
- package/dist/services/pnp-standard-features.d.ts +1 -1
- package/dist/services/tool-config-defaults.d.ts +7 -23
- package/dist/services/tool-config-defaults.js +7 -46
- package/dist/services/tool-config-validation.d.ts +1 -1
- package/dist/services/tool-config-validation.js +44 -4
- package/dist/services/tts/browser-provider.js +2 -1
- package/dist/services/tts-runtime-config.js +7 -2
- package/dist/tools/internal.d.ts +34 -0
- package/dist/tools/internal.js +33 -0
- package/dist/tools/tool-tag-map.d.ts +15 -3
- package/dist/tools/tool-tag-map.js +21 -18
- package/package.json +14 -10
- package/dist/components/chunks/ItemToolBar-3cppre9r.js +0 -51
- package/dist/components/chunks/ItemToolBar-7rq2gj8b.js +0 -22
- package/dist/services/sign-language-cards.d.ts +0 -82
- package/dist/services/sign-language-cards.js +0 -133
- package/dist/tools/registrations/accessibility-tools.d.ts +0 -34
- package/dist/tools/registrations/accessibility-tools.js +0 -217
- package/dist/tools/registrations/calculator.d.ts +0 -20
- package/dist/tools/registrations/calculator.js +0 -228
- package/dist/tools/registrations/interaction-tools.d.ts +0 -27
- package/dist/tools/registrations/interaction-tools.js +0 -143
- package/dist/tools/registrations/measurement-tools.d.ts +0 -24
- package/dist/tools/registrations/measurement-tools.js +0 -130
- package/dist/tools/registrations/subject-specific-tools.d.ts +0 -27
- package/dist/tools/registrations/subject-specific-tools.js +0 -158
- package/dist/tools/registrations/tts.d.ts +0 -21
- package/dist/tools/registrations/tts.js +0 -184
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Calculator Tool Registration
|
|
3
|
-
*
|
|
4
|
-
* Registers the calculator tool with support for multiple calculator types
|
|
5
|
-
* (basic, scientific, graphing) via Desmos provider.
|
|
6
|
-
*
|
|
7
|
-
* Maps to QTI 3.0 standard access features:
|
|
8
|
-
* - calculator (cognitive support)
|
|
9
|
-
* - graphingCalculator (assessment tool)
|
|
10
|
-
*/
|
|
11
|
-
import { hasMathContent } from "../../services/tool-context.js";
|
|
12
|
-
import { createScopedToolId } from "../../services/tool-instance-id.js";
|
|
13
|
-
import { DesmosToolProvider } from "../../services/tool-providers/index.js";
|
|
14
|
-
import { createToolElement } from "../tool-tag-map.js";
|
|
15
|
-
// The toolbar parent re-derives `renderedTools` whenever item state changes
|
|
16
|
-
// (e.g. the learner answers a question and `effectiveItem`/`renderContext`
|
|
17
|
-
// recompute). Calculator initialization is expensive (Desmos boot, container
|
|
18
|
-
// mount), so we cache the overlay element by coordinator + scoped tool id.
|
|
19
|
-
// Reusing the same element keeps `mountContent` a no-op and avoids tearing
|
|
20
|
-
// down and re-initializing the calculator on every re-render.
|
|
21
|
-
const overlayElementCache = new WeakMap();
|
|
22
|
-
function getCachedOverlay(coordinator, fullToolId) {
|
|
23
|
-
if (!coordinator)
|
|
24
|
-
return null;
|
|
25
|
-
const scoped = overlayElementCache.get(coordinator);
|
|
26
|
-
const element = scoped?.get(fullToolId);
|
|
27
|
-
if (!element)
|
|
28
|
-
return null;
|
|
29
|
-
// Svelte custom elements destroy their component when disconnected.
|
|
30
|
-
// A detached cached element is a dead instance — drop it and recreate.
|
|
31
|
-
if (!element.isConnected) {
|
|
32
|
-
scoped?.delete(fullToolId);
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
return element;
|
|
36
|
-
}
|
|
37
|
-
function setCachedOverlay(coordinator, fullToolId, element) {
|
|
38
|
-
if (!coordinator)
|
|
39
|
-
return;
|
|
40
|
-
let scoped = overlayElementCache.get(coordinator);
|
|
41
|
-
if (!scoped) {
|
|
42
|
-
scoped = new Map();
|
|
43
|
-
overlayElementCache.set(coordinator, scoped);
|
|
44
|
-
}
|
|
45
|
-
scoped.set(fullToolId, element);
|
|
46
|
-
}
|
|
47
|
-
function normalizeCalculatorType(value) {
|
|
48
|
-
return value === "basic" || value === "scientific" ? value : null;
|
|
49
|
-
}
|
|
50
|
-
function getCalculatorRenderParams(toolbarContext) {
|
|
51
|
-
const params = toolbarContext.getToolRenderParams?.("calculator") ?? {};
|
|
52
|
-
const calculatorType = normalizeCalculatorType(params.calculatorType);
|
|
53
|
-
const availableTypesRaw = params.availableTypes;
|
|
54
|
-
const availableTypes = Array.isArray(availableTypesRaw)
|
|
55
|
-
? availableTypesRaw
|
|
56
|
-
.map((value) => normalizeCalculatorType(value))
|
|
57
|
-
.filter((value) => value !== null)
|
|
58
|
-
: calculatorType
|
|
59
|
-
? [calculatorType]
|
|
60
|
-
: null;
|
|
61
|
-
return {
|
|
62
|
-
calculatorType,
|
|
63
|
-
availableTypes,
|
|
64
|
-
displayName: calculatorType === "scientific"
|
|
65
|
-
? "Scientific Calculator"
|
|
66
|
-
: calculatorType === "basic"
|
|
67
|
-
? "Basic Calculator"
|
|
68
|
-
: "Calculator",
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function applyCalculatorParamsToElement(element, calculatorType, availableTypes) {
|
|
72
|
-
const calculatorElement = element;
|
|
73
|
-
if (calculatorType) {
|
|
74
|
-
calculatorElement.calculatorType = calculatorType;
|
|
75
|
-
element.setAttribute("calculator-type", calculatorType);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
delete calculatorElement.calculatorType;
|
|
79
|
-
element.removeAttribute("calculator-type");
|
|
80
|
-
}
|
|
81
|
-
if (availableTypes && availableTypes.length > 0) {
|
|
82
|
-
calculatorElement.availableTypes = availableTypes;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
delete calculatorElement.availableTypes;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Calculator tool registration
|
|
90
|
-
*
|
|
91
|
-
* Supports:
|
|
92
|
-
* - Basic, scientific, and graphing calculators via Desmos
|
|
93
|
-
* - Context-aware visibility (shows only when math content is detected)
|
|
94
|
-
* - Item level only
|
|
95
|
-
*/
|
|
96
|
-
export const calculatorToolRegistration = {
|
|
97
|
-
toolId: "calculator",
|
|
98
|
-
name: "Calculator",
|
|
99
|
-
description: "Multi-type calculator (basic, scientific, graphing)",
|
|
100
|
-
icon: "calculator",
|
|
101
|
-
provider: {
|
|
102
|
-
getProviderId: (config) => typeof config?.provider?.id === "string" && config.provider.id.length > 0
|
|
103
|
-
? config.provider.id
|
|
104
|
-
: "calculator-desmos",
|
|
105
|
-
createProvider: () => new DesmosToolProvider(),
|
|
106
|
-
getInitConfig: (config) => config?.provider?.init ?? {},
|
|
107
|
-
getAuthFetcher: (config) => {
|
|
108
|
-
const runtimeAuthFetcher = config?.provider?.runtime?.authFetcher;
|
|
109
|
-
if (typeof runtimeAuthFetcher === "function")
|
|
110
|
-
return runtimeAuthFetcher;
|
|
111
|
-
return async () => {
|
|
112
|
-
const response = await fetch("/api/tools/desmos/auth", {
|
|
113
|
-
method: "GET",
|
|
114
|
-
credentials: "same-origin",
|
|
115
|
-
});
|
|
116
|
-
if (!response.ok) {
|
|
117
|
-
throw new Error(`Failed to fetch Desmos auth config (${response.status})`);
|
|
118
|
-
}
|
|
119
|
-
return (await response.json());
|
|
120
|
-
};
|
|
121
|
-
},
|
|
122
|
-
lazy: true,
|
|
123
|
-
},
|
|
124
|
-
// Calculator is item-level in this player architecture.
|
|
125
|
-
supportedLevels: ["item"],
|
|
126
|
-
// PNP support IDs that enable this tool
|
|
127
|
-
// Maps to QTI 3.0 standard features: calculator, graphingCalculator
|
|
128
|
-
pnpSupportIds: [
|
|
129
|
-
"calculator", // QTI 3.0 standard (cognitive.calculator)
|
|
130
|
-
"graphingCalculator", // QTI 3.0 standard (assessment.graphingCalculator)
|
|
131
|
-
"basicCalculator", // Common variant
|
|
132
|
-
"scientificCalculator", // Common variant
|
|
133
|
-
],
|
|
134
|
-
/**
|
|
135
|
-
* Pass 2: Determine if calculator is relevant in this context
|
|
136
|
-
*
|
|
137
|
-
* Calculator is relevant when context contains mathematical content
|
|
138
|
-
* (MathML, LaTeX, arithmetic markers).
|
|
139
|
-
*/
|
|
140
|
-
isVisibleInContext(context) {
|
|
141
|
-
// Show only when math is present in item content.
|
|
142
|
-
return hasMathContent(context);
|
|
143
|
-
},
|
|
144
|
-
renderToolbar(context, toolbarContext) {
|
|
145
|
-
const { calculatorType, availableTypes, displayName } = getCalculatorRenderParams(toolbarContext);
|
|
146
|
-
const fullToolId = createScopedToolId(this.toolId, toolbarContext.scope.level, toolbarContext.scope.scopeId);
|
|
147
|
-
const componentOverrides = toolbarContext.componentOverrides;
|
|
148
|
-
const cachedOverlay = getCachedOverlay(toolbarContext.toolCoordinator, fullToolId);
|
|
149
|
-
const overlay = (cachedOverlay ??
|
|
150
|
-
createToolElement(this.toolId, context, toolbarContext, componentOverrides));
|
|
151
|
-
if (!cachedOverlay) {
|
|
152
|
-
setCachedOverlay(toolbarContext.toolCoordinator, fullToolId, overlay);
|
|
153
|
-
}
|
|
154
|
-
overlay.setAttribute("tool-id", fullToolId);
|
|
155
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
156
|
-
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
|
-
const button = {
|
|
164
|
-
toolId: this.toolId,
|
|
165
|
-
label: displayName,
|
|
166
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
167
|
-
disabled: false,
|
|
168
|
-
ariaLabel: openLabel,
|
|
169
|
-
tooltip: displayName,
|
|
170
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
171
|
-
active: toolbarContext.isToolVisible(fullToolId),
|
|
172
|
-
};
|
|
173
|
-
let lastVisibleState = button.active;
|
|
174
|
-
if (overlay.visible !== button.active) {
|
|
175
|
-
overlay.visible = button.active;
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
toolId: this.toolId,
|
|
179
|
-
elements: [
|
|
180
|
-
{
|
|
181
|
-
element: overlay,
|
|
182
|
-
mount: "after-buttons",
|
|
183
|
-
shell: {
|
|
184
|
-
title: this.name,
|
|
185
|
-
draggable: true,
|
|
186
|
-
resizable: true,
|
|
187
|
-
closeable: true,
|
|
188
|
-
initialWidth: 380,
|
|
189
|
-
initialHeight: 420,
|
|
190
|
-
minWidth: 380,
|
|
191
|
-
minHeight: 420,
|
|
192
|
-
initialAlign: "bottom-right",
|
|
193
|
-
initialMargin: 16,
|
|
194
|
-
content: {
|
|
195
|
-
overflowY: "auto",
|
|
196
|
-
preserveMinHeight: true,
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
],
|
|
201
|
-
button,
|
|
202
|
-
sync: () => {
|
|
203
|
-
const active = toolbarContext.isToolVisible(fullToolId);
|
|
204
|
-
button.active = active;
|
|
205
|
-
button.label = displayName;
|
|
206
|
-
button.ariaLabel = active ? closeLabel : openLabel;
|
|
207
|
-
button.tooltip = active
|
|
208
|
-
? `Close ${displayName.toLowerCase()}`
|
|
209
|
-
: displayName;
|
|
210
|
-
if (lastVisibleState !== active) {
|
|
211
|
-
overlay.visible = active;
|
|
212
|
-
lastVisibleState = active;
|
|
213
|
-
}
|
|
214
|
-
if (overlay.toolkitCoordinator !== toolbarContext.toolkitCoordinator) {
|
|
215
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
216
|
-
}
|
|
217
|
-
applyCalculatorParamsToElement(overlay, calculatorType, availableTypes);
|
|
218
|
-
},
|
|
219
|
-
subscribeActive: (callback) => {
|
|
220
|
-
if (!toolbarContext.subscribeVisibility)
|
|
221
|
-
return () => { };
|
|
222
|
-
return toolbarContext.subscribeVisibility(() => {
|
|
223
|
-
callback(toolbarContext.isToolVisible(fullToolId));
|
|
224
|
-
});
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
},
|
|
228
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interaction Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers tools for interacting with question content:
|
|
5
|
-
* - Answer Eliminator (strike through answer choices)
|
|
6
|
-
* - Highlighter (highlight text passages)
|
|
7
|
-
*
|
|
8
|
-
* Maps to QTI 3.0 standard access features:
|
|
9
|
-
* - answerMasking (assessment tool)
|
|
10
|
-
* - strikethrough (visual transformation)
|
|
11
|
-
* - highlighting (cognitive/reading support)
|
|
12
|
-
*/
|
|
13
|
-
import type { ToolRegistration } from "../../services/ToolRegistry.js";
|
|
14
|
-
/**
|
|
15
|
-
* Answer Eliminator tool registration
|
|
16
|
-
*
|
|
17
|
-
* Allows students to strike through incorrect answer choices.
|
|
18
|
-
* Only appears on multiple-choice style questions.
|
|
19
|
-
*/
|
|
20
|
-
export declare const answerEliminatorToolRegistration: ToolRegistration;
|
|
21
|
-
/**
|
|
22
|
-
* Highlighter tool registration
|
|
23
|
-
*
|
|
24
|
-
* Allows students to highlight text in passages and questions.
|
|
25
|
-
* Appears on items with readable text content.
|
|
26
|
-
*/
|
|
27
|
-
export declare const highlighterToolRegistration: ToolRegistration;
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interaction Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers tools for interacting with question content:
|
|
5
|
-
* - Answer Eliminator (strike through answer choices)
|
|
6
|
-
* - Highlighter (highlight text passages)
|
|
7
|
-
*
|
|
8
|
-
* Maps to QTI 3.0 standard access features:
|
|
9
|
-
* - answerMasking (assessment tool)
|
|
10
|
-
* - strikethrough (visual transformation)
|
|
11
|
-
* - highlighting (cognitive/reading support)
|
|
12
|
-
*/
|
|
13
|
-
import { hasChoiceInteraction, hasReadableText, } from "../../services/tool-context.js";
|
|
14
|
-
import { createToolElement, } from "../tool-tag-map.js";
|
|
15
|
-
import { createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "./toolbar-registration-helpers.js";
|
|
16
|
-
/**
|
|
17
|
-
* Answer Eliminator tool registration
|
|
18
|
-
*
|
|
19
|
-
* Allows students to strike through incorrect answer choices.
|
|
20
|
-
* Only appears on multiple-choice style questions.
|
|
21
|
-
*/
|
|
22
|
-
export const answerEliminatorToolRegistration = {
|
|
23
|
-
toolId: "answerEliminator",
|
|
24
|
-
name: "Answer Eliminator",
|
|
25
|
-
description: "Strike through answer choices",
|
|
26
|
-
icon: "strikethrough",
|
|
27
|
-
// Answer eliminator appears at item level only
|
|
28
|
-
supportedLevels: ["item"],
|
|
29
|
-
// PNP support IDs
|
|
30
|
-
// Maps to QTI 3.0 standard feature: answerMasking
|
|
31
|
-
pnpSupportIds: [
|
|
32
|
-
"answerMasking", // QTI 3.0 standard (assessment.answerMasking)
|
|
33
|
-
"answerEliminator", // QTI 3.0 standard (assessment.answerEliminator)
|
|
34
|
-
"strikethrough", // Common variant
|
|
35
|
-
"choiceMasking", // Common variant
|
|
36
|
-
],
|
|
37
|
-
/**
|
|
38
|
-
* Pass 2: Answer eliminator is relevant only for choice-based questions
|
|
39
|
-
*/
|
|
40
|
-
isVisibleInContext(context) {
|
|
41
|
-
return hasChoiceInteraction(context);
|
|
42
|
-
},
|
|
43
|
-
renderToolbar(context, toolbarContext) {
|
|
44
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
45
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
46
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
47
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
48
|
-
overlay.setAttribute("strategy", "strikethrough");
|
|
49
|
-
overlay.setAttribute("button-alignment", "inline");
|
|
50
|
-
const button = {
|
|
51
|
-
toolId: this.toolId,
|
|
52
|
-
label: this.name,
|
|
53
|
-
icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true"><path d="M19,3H16.3H7.7H5A2,2 0 0,0 3,5V7.7V16.4V19A2,2 0 0,0 5,21H7.7H16.4H19A2,2 0 0,0 21,19V16.3V7.7V5A2,2 0 0,0 19,3M15.6,17L12,13.4L8.4,17L7,15.6L10.6,12L7,8.4L8.4,7L12,10.6L15.6,7L17,8.4L13.4,12L17,15.6L15.6,17Z"/></svg>',
|
|
54
|
-
disabled: false,
|
|
55
|
-
ariaLabel: "Answer eliminator - Strike through choices",
|
|
56
|
-
tooltip: "Strike Through",
|
|
57
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
58
|
-
active: visibility.isActive(),
|
|
59
|
-
};
|
|
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.toolCoordinator) {
|
|
71
|
-
overlay.coordinator = toolbarContext.toolCoordinator;
|
|
72
|
-
}
|
|
73
|
-
overlay.scopeElement = toolbarContext.getScopeElement?.() || null;
|
|
74
|
-
if (toolbarContext.elementToolStateStore) {
|
|
75
|
-
overlay.elementToolStateStore = toolbarContext.elementToolStateStore;
|
|
76
|
-
}
|
|
77
|
-
const globalElementId = toolbarContext.getGlobalElementId?.();
|
|
78
|
-
if (globalElementId) {
|
|
79
|
-
overlay.globalElementId = globalElementId;
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
subscribeActive: visibility.subscribeActive,
|
|
83
|
-
};
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
/**
|
|
87
|
-
* Highlighter tool registration
|
|
88
|
-
*
|
|
89
|
-
* Allows students to highlight text in passages and questions.
|
|
90
|
-
* Appears on items with readable text content.
|
|
91
|
-
*/
|
|
92
|
-
export const highlighterToolRegistration = {
|
|
93
|
-
toolId: "highlighter",
|
|
94
|
-
name: "Highlighter",
|
|
95
|
-
description: "Highlight text",
|
|
96
|
-
icon: "highlighter",
|
|
97
|
-
activation: "toolbar-toggle",
|
|
98
|
-
// Highlighter appears at passage, rubric, item, and element levels
|
|
99
|
-
supportedLevels: ["passage", "rubric", "item", "element"],
|
|
100
|
-
// PNP support IDs
|
|
101
|
-
pnpSupportIds: ["highlighter", "textHighlight", "annotation"],
|
|
102
|
-
/**
|
|
103
|
-
* Pass 2: Highlighter is relevant when readable text is available
|
|
104
|
-
*/
|
|
105
|
-
isVisibleInContext(context) {
|
|
106
|
-
return hasReadableText(context);
|
|
107
|
-
},
|
|
108
|
-
renderToolbar(context, toolbarContext) {
|
|
109
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
110
|
-
const button = {
|
|
111
|
-
toolId: this.toolId,
|
|
112
|
-
label: this.name,
|
|
113
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
114
|
-
disabled: false,
|
|
115
|
-
ariaLabel: "Highlighter - Highlight text",
|
|
116
|
-
tooltip: "Highlight",
|
|
117
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
118
|
-
active: visibility.isActive(),
|
|
119
|
-
};
|
|
120
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
121
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
122
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
123
|
-
return {
|
|
124
|
-
toolId: this.toolId,
|
|
125
|
-
button,
|
|
126
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
127
|
-
sync: () => {
|
|
128
|
-
syncButtonAndOverlayVisibility({
|
|
129
|
-
button,
|
|
130
|
-
overlay,
|
|
131
|
-
isActive: visibility.isActive,
|
|
132
|
-
onActiveChange: (active) => {
|
|
133
|
-
overlay.enabled = active;
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
if (toolbarContext.ttsService) {
|
|
137
|
-
overlay.ttsService = toolbarContext.ttsService;
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
subscribeActive: visibility.subscribeActive,
|
|
141
|
-
};
|
|
142
|
-
},
|
|
143
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Measurement Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers ruler and protractor tools for on-screen measurements.
|
|
5
|
-
*
|
|
6
|
-
* Maps to QTI 3.0 standard access features:
|
|
7
|
-
* - ruler (assessment tool)
|
|
8
|
-
* - protractor (assessment tool)
|
|
9
|
-
*/
|
|
10
|
-
import type { ToolRegistration } from "../../services/ToolRegistry.js";
|
|
11
|
-
/**
|
|
12
|
-
* Ruler tool registration
|
|
13
|
-
*
|
|
14
|
-
* Provides an on-screen ruler for measuring lengths.
|
|
15
|
-
* Typically appears on geometry or measurement problems.
|
|
16
|
-
*/
|
|
17
|
-
export declare const rulerToolRegistration: ToolRegistration;
|
|
18
|
-
/**
|
|
19
|
-
* Protractor tool registration
|
|
20
|
-
*
|
|
21
|
-
* Provides an on-screen protractor for measuring angles.
|
|
22
|
-
* Typically appears on geometry problems.
|
|
23
|
-
*/
|
|
24
|
-
export declare const protractorToolRegistration: ToolRegistration;
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Measurement Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers ruler and protractor tools for on-screen measurements.
|
|
5
|
-
*
|
|
6
|
-
* Maps to QTI 3.0 standard access features:
|
|
7
|
-
* - ruler (assessment tool)
|
|
8
|
-
* - protractor (assessment tool)
|
|
9
|
-
*/
|
|
10
|
-
import { hasMathContent } from "../../services/tool-context.js";
|
|
11
|
-
import { createToolElement, } from "../tool-tag-map.js";
|
|
12
|
-
import { applyOverlaySurface, createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "./toolbar-registration-helpers.js";
|
|
13
|
-
/**
|
|
14
|
-
* Ruler tool registration
|
|
15
|
-
*
|
|
16
|
-
* Provides an on-screen ruler for measuring lengths.
|
|
17
|
-
* Typically appears on geometry or measurement problems.
|
|
18
|
-
*/
|
|
19
|
-
export const rulerToolRegistration = {
|
|
20
|
-
toolId: "ruler",
|
|
21
|
-
name: "Ruler",
|
|
22
|
-
description: "On-screen ruler for measurements",
|
|
23
|
-
icon: "ruler",
|
|
24
|
-
// Ruler typically appears at section/item/element level
|
|
25
|
-
supportedLevels: ["section", "item", "element"],
|
|
26
|
-
// PNP support IDs
|
|
27
|
-
// Maps to QTI 3.0 standard feature: ruler
|
|
28
|
-
pnpSupportIds: [
|
|
29
|
-
"ruler", // QTI 3.0 standard (assessment.ruler)
|
|
30
|
-
"measurement", // Common variant
|
|
31
|
-
],
|
|
32
|
-
/**
|
|
33
|
-
* Pass 2: Ruler is relevant when math content is present
|
|
34
|
-
*/
|
|
35
|
-
isVisibleInContext(context) {
|
|
36
|
-
return hasMathContent(context);
|
|
37
|
-
},
|
|
38
|
-
renderToolbar(context, toolbarContext) {
|
|
39
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
40
|
-
const button = {
|
|
41
|
-
toolId: this.toolId,
|
|
42
|
-
label: this.name,
|
|
43
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
44
|
-
disabled: false,
|
|
45
|
-
ariaLabel: "Open ruler tool",
|
|
46
|
-
tooltip: "Ruler",
|
|
47
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
48
|
-
active: visibility.isActive(),
|
|
49
|
-
};
|
|
50
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
51
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
52
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
53
|
-
applyOverlaySurface(overlay, "frameless");
|
|
54
|
-
return {
|
|
55
|
-
toolId: this.toolId,
|
|
56
|
-
button,
|
|
57
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
58
|
-
sync: () => {
|
|
59
|
-
syncButtonAndOverlayVisibility({
|
|
60
|
-
button,
|
|
61
|
-
overlay,
|
|
62
|
-
isActive: visibility.isActive,
|
|
63
|
-
});
|
|
64
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
65
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
subscribeActive: visibility.subscribeActive,
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Protractor tool registration
|
|
74
|
-
*
|
|
75
|
-
* Provides an on-screen protractor for measuring angles.
|
|
76
|
-
* Typically appears on geometry problems.
|
|
77
|
-
*/
|
|
78
|
-
export const protractorToolRegistration = {
|
|
79
|
-
toolId: "protractor",
|
|
80
|
-
name: "Protractor",
|
|
81
|
-
description: "On-screen protractor for angle measurements",
|
|
82
|
-
icon: "protractor",
|
|
83
|
-
// Protractor typically appears at section/item/element level
|
|
84
|
-
supportedLevels: ["section", "item", "element"],
|
|
85
|
-
// PNP support IDs
|
|
86
|
-
// Maps to QTI 3.0 standard feature: protractor
|
|
87
|
-
pnpSupportIds: [
|
|
88
|
-
"protractor", // QTI 3.0 standard (assessment.protractor)
|
|
89
|
-
"angleMeasurement", // Common variant
|
|
90
|
-
],
|
|
91
|
-
/**
|
|
92
|
-
* Pass 2: Protractor is relevant when math content is present
|
|
93
|
-
*/
|
|
94
|
-
isVisibleInContext(context) {
|
|
95
|
-
return hasMathContent(context);
|
|
96
|
-
},
|
|
97
|
-
renderToolbar(context, toolbarContext) {
|
|
98
|
-
const visibility = createScopedVisibilityBinding(this.toolId, toolbarContext);
|
|
99
|
-
const button = {
|
|
100
|
-
toolId: this.toolId,
|
|
101
|
-
label: this.name,
|
|
102
|
-
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
103
|
-
disabled: false,
|
|
104
|
-
ariaLabel: "Open protractor tool",
|
|
105
|
-
tooltip: "Protractor",
|
|
106
|
-
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
107
|
-
active: visibility.isActive(),
|
|
108
|
-
};
|
|
109
|
-
const componentOverrides = toolbarContext.componentOverrides ?? {};
|
|
110
|
-
const overlay = createToolElement(this.toolId, context, toolbarContext, componentOverrides);
|
|
111
|
-
overlay.setAttribute("tool-id", visibility.fullToolId);
|
|
112
|
-
applyOverlaySurface(overlay, "frameless");
|
|
113
|
-
return {
|
|
114
|
-
toolId: this.toolId,
|
|
115
|
-
button,
|
|
116
|
-
elements: [{ element: overlay, mount: "after-buttons" }],
|
|
117
|
-
sync: () => {
|
|
118
|
-
syncButtonAndOverlayVisibility({
|
|
119
|
-
button,
|
|
120
|
-
overlay,
|
|
121
|
-
isActive: visibility.isActive,
|
|
122
|
-
});
|
|
123
|
-
if (toolbarContext.toolkitCoordinator) {
|
|
124
|
-
overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
|
|
125
|
-
}
|
|
126
|
-
},
|
|
127
|
-
subscribeActive: visibility.subscribeActive,
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subject-Specific Tools Registrations
|
|
3
|
-
*
|
|
4
|
-
* Registers tools for specific subject areas:
|
|
5
|
-
* - Graph (graphing calculator/coordinate plane)
|
|
6
|
-
* - Periodic Table (chemistry reference)
|
|
7
|
-
*
|
|
8
|
-
* Maps to QTI 3.0 standard access features:
|
|
9
|
-
* - graphingCalculator (assessment tool)
|
|
10
|
-
* - graph (assessment tool)
|
|
11
|
-
* - periodicTable (assessment tool)
|
|
12
|
-
*/
|
|
13
|
-
import type { ToolRegistration } from "../../services/ToolRegistry.js";
|
|
14
|
-
/**
|
|
15
|
-
* Graph tool registration
|
|
16
|
-
*
|
|
17
|
-
* Provides graphing calculator and coordinate plane functionality.
|
|
18
|
-
* Context-smart: appears automatically for math content or when explicitly enabled.
|
|
19
|
-
*/
|
|
20
|
-
export declare const graphToolRegistration: ToolRegistration;
|
|
21
|
-
/**
|
|
22
|
-
* Periodic Table tool registration
|
|
23
|
-
*
|
|
24
|
-
* Provides chemistry periodic table reference.
|
|
25
|
-
* Context-smart: appears automatically for science content or when explicitly enabled.
|
|
26
|
-
*/
|
|
27
|
-
export declare const periodicTableToolRegistration: ToolRegistration;
|