@pie-players/pie-default-tool-loaders 1.0.0-beta.3 → 1.0.0-beta.4
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 +54 -14
- package/dist/afa-profile.d.ts +13 -0
- package/dist/afa-profile.js +14 -0
- package/dist/calculator-providers/LazyCalculatorToolProvider.d.ts +32 -18
- package/dist/calculator-providers/LazyCalculatorToolProvider.js +24 -12
- package/dist/calculator-providers/packaged-calculator-providers.d.ts +8 -0
- package/dist/calculator-providers/packaged-calculator-providers.js +26 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/packaged-capability-composition.js +11 -1
- package/dist/registrations/accessibility-tools.d.ts +8 -0
- package/dist/registrations/accessibility-tools.js +38 -0
- package/dist/registrations/calculator.d.ts +16 -5
- package/dist/registrations/calculator.js +171 -176
- package/package.json +20 -20
- package/dist/calculator-providers/CortexToolProvider.d.ts +0 -10
- package/dist/calculator-providers/CortexToolProvider.js +0 -18
- package/dist/calculator-providers/DesmosToolProvider.d.ts +0 -11
- package/dist/calculator-providers/DesmosToolProvider.js +0 -18
- package/dist/calculator-providers/GeoGebraToolProvider.d.ts +0 -13
- package/dist/calculator-providers/GeoGebraToolProvider.js +0 -18
package/README.md
CHANGED
|
@@ -5,9 +5,9 @@ they load, and which of them a program grants to everyone. This README is for
|
|
|
5
5
|
host integrators choosing a tool set and a calculator, and for contributors
|
|
6
6
|
adding a packaged capability.
|
|
7
7
|
|
|
8
|
-
The package owns the concrete `pie-tool-*` dependencies and the
|
|
9
|
-
|
|
10
|
-
stays dependency-light and cycle-safe. Core knows the concepts — support ids,
|
|
8
|
+
The package owns the concrete `pie-tool-*` dependencies and the Desmos and
|
|
9
|
+
GeoGebra calculator adapters (`pie-calculator-desmos` and `-geogebra`), so
|
|
10
|
+
toolkit core stays dependency-light and cycle-safe. Core knows the concepts — support ids,
|
|
11
11
|
placement levels, activation kinds and precedence rules — and no concrete
|
|
12
12
|
capability id. A support id is the tool id a profile grants.
|
|
13
13
|
|
|
@@ -15,6 +15,7 @@ capability id. A support id is the tool id a profile grants.
|
|
|
15
15
|
| --- | --- |
|
|
16
16
|
| `PACKAGED_TOOL_REGISTRATIONS`, `createPackagedToolRegistry` | Which capabilities exist, and their toolbar and surface contracts |
|
|
17
17
|
| `PACKAGED_TOOL_TAG_MAP` | Which custom element each one renders as |
|
|
18
|
+
| `createCalculatorToolRegistration` | Which calculator backends `provider.id` selects among |
|
|
18
19
|
| `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` | Where they appear and in what order |
|
|
19
20
|
| `createUniversalPersonalNeedsProfile`, `createEmptyPersonalNeedsProfile` | Which of them the program grants to everyone, or to no one |
|
|
20
21
|
| `createPersonalNeedsProfileFromAfa` | Which of them a student's AfA PNP 3.0 record grants, prohibits and turns on at start, and with which settings |
|
|
@@ -58,15 +59,8 @@ Desmos is the provider when none is configured, and it needs an API key: pass
|
|
|
58
59
|
it through `provider.runtime.authFetcher`, a `provider.init.proxyEndpoint` that
|
|
59
60
|
returns it, or `provider.init.apiKey` in development
|
|
60
61
|
([Calculator with host auth](../../docs/tools-and-accomodations/tool_provider_system.md#calculator-with-host-auth)).
|
|
61
|
-
Without one the calculator fails to load.
|
|
62
|
-
|
|
63
|
-
`settings` take the `CortexCalculatorSettings` type that
|
|
64
|
-
`@pie-players/pie-calculator-cortex` exports: `angleMode`,
|
|
65
|
-
`calculationPrecision`, `displayPrecision`, `historyLimit`,
|
|
66
|
-
`evaluationTimeLimitMs`, `allowedFunctions`, `allowClipboard`, `messages`,
|
|
67
|
-
`direction` and `graph`. Clipboard blocking follows `restrictedMode`;
|
|
68
|
-
`allowClipboard` alone blocks nothing. The [Cortex README](../calculator-cortex/README.md)
|
|
69
|
-
covers localization, message overrides and the keypad.
|
|
62
|
+
Without one the calculator fails to load. `provider.id: "calculator-geogebra"`
|
|
63
|
+
selects GeoGebra, which needs no key.
|
|
70
64
|
|
|
71
65
|
```ts
|
|
72
66
|
const tools = {
|
|
@@ -82,6 +76,52 @@ const tools = {
|
|
|
82
76
|
};
|
|
83
77
|
```
|
|
84
78
|
|
|
79
|
+
### Adding a backend
|
|
80
|
+
|
|
81
|
+
The packaged registration selects among Desmos and GeoGebra only, because a
|
|
82
|
+
bundler that inlines dynamic imports inlines every backend the registration
|
|
83
|
+
names, selected or not. `createCalculatorToolRegistration({ providers })` builds
|
|
84
|
+
the registration with more backends, keyed by `provider.id`; an id the packaged
|
|
85
|
+
set already holds is replaced. The keyless, offline-capable Cortex calculator,
|
|
86
|
+
which needs no runtime CDN, is composed in this way from
|
|
87
|
+
`@pie-players/pie-calculator-cortex`, which the host installs:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import {
|
|
91
|
+
createCalculatorToolRegistration,
|
|
92
|
+
createPackagedToolRegistry,
|
|
93
|
+
} from "@pie-players/pie-default-tool-loaders";
|
|
94
|
+
|
|
95
|
+
const registry = createPackagedToolRegistry({
|
|
96
|
+
overrides: {
|
|
97
|
+
calculator: createCalculatorToolRegistration({
|
|
98
|
+
providers: {
|
|
99
|
+
"calculator-cortex": {
|
|
100
|
+
providerName: "PIE Open-Source Calculator",
|
|
101
|
+
version: "1",
|
|
102
|
+
requiresAuth: false,
|
|
103
|
+
backend: "cortex",
|
|
104
|
+
load: async () =>
|
|
105
|
+
(await import("@pie-players/pie-calculator-cortex"))
|
|
106
|
+
.CortexCalculatorProvider,
|
|
107
|
+
initializationErrorMessage:
|
|
108
|
+
"Failed to initialize the Cortex calculator provider.",
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`provider.id: "calculator-cortex"` then selects it. Its `settings` take the
|
|
117
|
+
`CortexCalculatorSettings` type that `@pie-players/pie-calculator-cortex`
|
|
118
|
+
exports: `angleMode`, `calculationPrecision`, `displayPrecision`,
|
|
119
|
+
`historyLimit`, `evaluationTimeLimitMs`, `allowedFunctions`, `allowClipboard`,
|
|
120
|
+
`messages`, `direction` and `graph`. Clipboard blocking follows
|
|
121
|
+
`restrictedMode`; `allowClipboard` alone blocks nothing. The
|
|
122
|
+
[Cortex README](../calculator-cortex/README.md) covers localization, message
|
|
123
|
+
overrides and the keypad.
|
|
124
|
+
|
|
85
125
|
## Custom sets
|
|
86
126
|
|
|
87
127
|
A host composing its own set starts from the toolkit's empty `ToolRegistry`,
|
|
@@ -167,8 +207,8 @@ student's AfA PNP 3.0 record, held as JSON keyed by the spec's terms. Features
|
|
|
167
207
|
become support ids in the packaged set's names, the activation sets fill
|
|
168
208
|
`activateAtInit` and `prohibitedSupports`, and the settings the packaged tools
|
|
169
209
|
read become `toolParameters`: read-aloud speed, pitch and volume, the calculator
|
|
170
|
-
type and the
|
|
171
|
-
feature's disposition.
|
|
210
|
+
type, the sign language and the magnifier's starting zoom. The toolkit's PNP
|
|
211
|
+
configuration guide gives each AfA feature's disposition.
|
|
172
212
|
|
|
173
213
|
```ts
|
|
174
214
|
import { createPersonalNeedsProfileFromAfa } from "@pie-players/pie-default-tool-loaders";
|
package/dist/afa-profile.d.ts
CHANGED
|
@@ -28,6 +28,10 @@ export interface AfaSpoken {
|
|
|
28
28
|
}
|
|
29
29
|
/** A set's features: empty elements keyed by feature, or the feature names. */
|
|
30
30
|
export type AfaFeatureSet = Readonly<Record<string, unknown>> | readonly string[];
|
|
31
|
+
/** AfA's `ZoomAmount`: a magnification multiplier. */
|
|
32
|
+
export interface AfaZoomAmount {
|
|
33
|
+
"zoom-amount"?: number;
|
|
34
|
+
}
|
|
31
35
|
/** An AfA PNP 3.0 record in JSON. A feature is present unless absent, `null` or `false`. */
|
|
32
36
|
export interface AfaPnpRecord {
|
|
33
37
|
spoken?: AfaSpoken;
|
|
@@ -39,6 +43,15 @@ export interface AfaPnpRecord {
|
|
|
39
43
|
language?: string;
|
|
40
44
|
[setting: string]: unknown;
|
|
41
45
|
};
|
|
46
|
+
/** One selection: the amount for all content, or for text and non-text apart. */
|
|
47
|
+
magnification?: {
|
|
48
|
+
"all-content"?: AfaZoomAmount;
|
|
49
|
+
selectMagnification?: {
|
|
50
|
+
text?: AfaZoomAmount;
|
|
51
|
+
"non-text"?: AfaZoomAmount;
|
|
52
|
+
};
|
|
53
|
+
[setting: string]: unknown;
|
|
54
|
+
};
|
|
42
55
|
"activate-at-initialization-set"?: AfaFeatureSet;
|
|
43
56
|
"activate-as-option-set"?: AfaFeatureSet;
|
|
44
57
|
"prohibit-set"?: AfaFeatureSet;
|
package/dist/afa-profile.js
CHANGED
|
@@ -70,6 +70,16 @@ function spokenParameters(spoken) {
|
|
|
70
70
|
...(volume !== undefined ? { volume } : {}),
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* The lens's starting zoom. The lens magnifies text and non-text alike, so a
|
|
75
|
+
* record that sets them apart gives the text amount, else the non-text one.
|
|
76
|
+
*/
|
|
77
|
+
function magnifierZoom(magnification) {
|
|
78
|
+
const select = magnification?.selectMagnification;
|
|
79
|
+
return (finiteNumber(magnification?.["all-content"]?.["zoom-amount"]) ??
|
|
80
|
+
finiteNumber(select?.text?.["zoom-amount"]) ??
|
|
81
|
+
finiteNumber(select?.["non-text"]?.["zoom-amount"]));
|
|
82
|
+
}
|
|
73
83
|
/** A fresh profile carrying `record`'s grants, prohibitions and settings, ids sorted. */
|
|
74
84
|
export function createPersonalNeedsProfileFromAfa(record) {
|
|
75
85
|
const spoken = typeof record.spoken === "object" && record.spoken !== null
|
|
@@ -108,6 +118,10 @@ export function createPersonalNeedsProfileFromAfa(record) {
|
|
|
108
118
|
if (typeof signLang === "string" && signLang.length > 0) {
|
|
109
119
|
toolParameters.signLanguage = { signLang };
|
|
110
120
|
}
|
|
121
|
+
const zoom = magnifierZoom(record.magnification);
|
|
122
|
+
if (zoom !== undefined && zoom > 1) {
|
|
123
|
+
toolParameters.magnification = { zoom };
|
|
124
|
+
}
|
|
111
125
|
return {
|
|
112
126
|
supports,
|
|
113
127
|
prohibitedSupports: [...prohibited].sort(),
|
|
@@ -1,33 +1,47 @@
|
|
|
1
1
|
import type { CalculatorProvider, CalculatorProviderInit } from "@pie-players/pie-calculator";
|
|
2
2
|
import type { ToolProviderApi } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
/**
|
|
4
|
+
* One calculator backend, selected by the toolkit's `provider.id`. `load` runs
|
|
5
|
+
* on first use, but a bundler that inlines dynamic imports inlines what it
|
|
6
|
+
* names whether or not the host selects the backend. The packaged set therefore
|
|
7
|
+
* holds only the thin Desmos and GeoGebra adapters, and a host adds any other
|
|
8
|
+
* backend through `createCalculatorToolRegistration`.
|
|
9
|
+
*/
|
|
10
|
+
export interface CalculatorProviderDefinition {
|
|
11
|
+
/** Names the provider in toolkit logs, telemetry and error messages. */
|
|
12
|
+
readonly providerName: string;
|
|
13
|
+
readonly version: string;
|
|
14
|
+
/**
|
|
15
|
+
* Whether the registry merges the result of `provider.runtime.authFetcher`
|
|
16
|
+
* into the configuration `initialize()` receives.
|
|
17
|
+
*/
|
|
18
|
+
readonly requiresAuth: boolean;
|
|
19
|
+
/** The `backend` of library-load telemetry. */
|
|
20
|
+
readonly backend: string;
|
|
21
|
+
/** Loads the adapter's provider class, usually through a dynamic import. */
|
|
22
|
+
readonly load: () => Promise<new () => CalculatorProvider>;
|
|
23
|
+
/** Thrown, with the failure as its cause, when loading or initializing fails. */
|
|
24
|
+
readonly initializationErrorMessage: string;
|
|
12
25
|
}
|
|
13
26
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
27
|
+
* Lazy-module and lifecycle implementation shared by every calculator backend:
|
|
28
|
+
* concurrent initialization is deduplicated, and `destroy()` cancels one in
|
|
29
|
+
* flight.
|
|
16
30
|
*/
|
|
17
|
-
export declare
|
|
18
|
-
|
|
31
|
+
export declare class LazyCalculatorToolProvider implements ToolProviderApi<CalculatorProvider> {
|
|
32
|
+
readonly providerName: string;
|
|
19
33
|
readonly category: "calculator";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
readonly version: string;
|
|
35
|
+
readonly requiresAuth: boolean;
|
|
36
|
+
private readonly definition;
|
|
23
37
|
private calculatorProvider;
|
|
24
38
|
private initializationPromise;
|
|
25
39
|
private lifecycleGeneration;
|
|
40
|
+
constructor(definition: CalculatorProviderDefinition);
|
|
26
41
|
private emitTelemetry;
|
|
27
|
-
initialize(config?:
|
|
42
|
+
initialize(config?: CalculatorProviderInit): Promise<void>;
|
|
28
43
|
private initializeProvider;
|
|
29
44
|
createInstance(): Promise<CalculatorProvider>;
|
|
30
45
|
isReady(): boolean;
|
|
31
46
|
destroy(): void;
|
|
32
47
|
}
|
|
33
|
-
export {};
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Lazy-module and lifecycle implementation shared by every calculator backend:
|
|
3
|
+
* concurrent initialization is deduplicated, and `destroy()` cancels one in
|
|
4
|
+
* flight.
|
|
4
5
|
*/
|
|
5
6
|
export class LazyCalculatorToolProvider {
|
|
7
|
+
providerName;
|
|
6
8
|
category = "calculator";
|
|
9
|
+
version;
|
|
10
|
+
requiresAuth;
|
|
11
|
+
definition;
|
|
7
12
|
calculatorProvider = null;
|
|
8
13
|
initializationPromise = null;
|
|
9
14
|
lifecycleGeneration = 0;
|
|
15
|
+
constructor(definition) {
|
|
16
|
+
this.definition = definition;
|
|
17
|
+
this.providerName = definition.providerName;
|
|
18
|
+
this.version = definition.version;
|
|
19
|
+
this.requiresAuth = definition.requiresAuth;
|
|
20
|
+
}
|
|
10
21
|
async emitTelemetry(config, eventName, payload) {
|
|
11
22
|
try {
|
|
12
23
|
await config.onTelemetry?.(eventName, payload);
|
|
@@ -33,33 +44,34 @@ export class LazyCalculatorToolProvider {
|
|
|
33
44
|
}
|
|
34
45
|
}
|
|
35
46
|
async initializeProvider(config, generation) {
|
|
36
|
-
const
|
|
47
|
+
const { backend, initializationErrorMessage } = this.definition;
|
|
48
|
+
const operation = `${backend}-provider-module-import`;
|
|
37
49
|
const moduleLoadStartedAt = Date.now();
|
|
38
50
|
await this.emitTelemetry(config, "pie-tool-library-load-start", {
|
|
39
51
|
toolId: "calculator",
|
|
40
|
-
operation
|
|
41
|
-
backend
|
|
52
|
+
operation,
|
|
53
|
+
backend,
|
|
42
54
|
});
|
|
43
55
|
let ProviderConstructor;
|
|
44
56
|
try {
|
|
45
|
-
ProviderConstructor = await definition.
|
|
57
|
+
ProviderConstructor = await this.definition.load();
|
|
46
58
|
await this.emitTelemetry(config, "pie-tool-library-load-success", {
|
|
47
59
|
toolId: "calculator",
|
|
48
|
-
operation
|
|
49
|
-
backend
|
|
60
|
+
operation,
|
|
61
|
+
backend,
|
|
50
62
|
duration: Date.now() - moduleLoadStartedAt,
|
|
51
63
|
});
|
|
52
64
|
}
|
|
53
65
|
catch (error) {
|
|
54
66
|
await this.emitTelemetry(config, "pie-tool-library-load-error", {
|
|
55
67
|
toolId: "calculator",
|
|
56
|
-
operation
|
|
57
|
-
backend
|
|
68
|
+
operation,
|
|
69
|
+
backend,
|
|
58
70
|
duration: Date.now() - moduleLoadStartedAt,
|
|
59
71
|
errorType: "ToolLibraryLoadError",
|
|
60
72
|
message: error instanceof Error ? error.message : String(error),
|
|
61
73
|
});
|
|
62
|
-
throw new Error(
|
|
74
|
+
throw new Error(initializationErrorMessage, { cause: error });
|
|
63
75
|
}
|
|
64
76
|
if (generation !== this.lifecycleGeneration) {
|
|
65
77
|
throw new Error(`${this.providerName} initialization was cancelled`);
|
|
@@ -74,7 +86,7 @@ export class LazyCalculatorToolProvider {
|
|
|
74
86
|
}
|
|
75
87
|
catch (error) {
|
|
76
88
|
candidate.destroy();
|
|
77
|
-
throw new Error(
|
|
89
|
+
throw new Error(initializationErrorMessage, { cause: error });
|
|
78
90
|
}
|
|
79
91
|
}
|
|
80
92
|
async createInstance() {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The calculator backends of the packaged set, by `provider.id`. Every import
|
|
3
|
+
* named here lands in a host bundle that inlines dynamic imports, so only thin
|
|
4
|
+
* adapters over a vendor-hosted engine belong in it.
|
|
5
|
+
*/
|
|
6
|
+
import type { CalculatorProviderDefinition } from "./LazyCalculatorToolProvider.js";
|
|
7
|
+
export declare const DEFAULT_CALCULATOR_PROVIDER_ID = "calculator-desmos";
|
|
8
|
+
export declare const PACKAGED_CALCULATOR_PROVIDERS: Readonly<Record<string, CalculatorProviderDefinition>>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The calculator backends of the packaged set, by `provider.id`. Every import
|
|
3
|
+
* named here lands in a host bundle that inlines dynamic imports, so only thin
|
|
4
|
+
* adapters over a vendor-hosted engine belong in it.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_CALCULATOR_PROVIDER_ID = "calculator-desmos";
|
|
7
|
+
export const PACKAGED_CALCULATOR_PROVIDERS = {
|
|
8
|
+
"calculator-desmos": {
|
|
9
|
+
providerName: "Desmos Calculator",
|
|
10
|
+
version: "1.12",
|
|
11
|
+
requiresAuth: true,
|
|
12
|
+
backend: "desmos",
|
|
13
|
+
load: async () => (await import("@pie-players/pie-calculator-desmos"))
|
|
14
|
+
.DesmosCalculatorProvider,
|
|
15
|
+
initializationErrorMessage: "Failed to initialize Desmos calculator provider. Check the application key, preloaded API, runtime endpoint, or network access.",
|
|
16
|
+
},
|
|
17
|
+
"calculator-geogebra": {
|
|
18
|
+
providerName: "GeoGebra Calculator",
|
|
19
|
+
version: "6",
|
|
20
|
+
requiresAuth: false,
|
|
21
|
+
backend: "geogebra",
|
|
22
|
+
load: async () => (await import("@pie-players/pie-calculator-geogebra"))
|
|
23
|
+
.GeoGebraCalculatorProvider,
|
|
24
|
+
initializationErrorMessage: "Failed to initialize GeoGebra calculator provider. Confirm that the deployment may load GeoGebra and that its script URL is reachable.",
|
|
25
|
+
},
|
|
26
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export type { PackagedToolRegistryOptions } from "./packaged-capability-composition.js";
|
|
2
2
|
export { createEmptyPersonalNeedsProfile, createPackagedToolRegistry, createUniversalPersonalNeedsProfile, DEFAULT_TOOL_MODULE_LOADERS, PACKAGED_TOOL_REGISTRATIONS, PACKAGED_TOOL_TAG_MAP, SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT, } from "./packaged-capability-composition.js";
|
|
3
|
-
export { type AfaFeatureSet, type AfaPnpRecord, type AfaSpoken, createPersonalNeedsProfileFromAfa, } from "./afa-profile.js";
|
|
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
|
-
export { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
5
|
+
export { annotationToolbarRegistration, lineReaderToolRegistration, magnificationToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
6
6
|
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration, CONTENT_LEAD_SURFACE, resolveAudioTranscript, type ResolvedAudioTranscript, } from "./registrations/audio-transcript.js";
|
|
7
|
-
export { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
7
|
+
export { type CalculatorProviderDefinition, type CalculatorRegistrationOptions, calculatorToolRegistration, createCalculatorToolRegistration, } from "./registrations/calculator.js";
|
|
8
8
|
export { createDictionaryToolRegistration, createPictureDictionaryToolRegistration, dictionaryToolRegistration, type DictionaryVariantOptions, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
9
9
|
export { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
10
10
|
export { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,9 @@ export { createPersonalNeedsProfileFromAfa, } from "./afa-profile.js";
|
|
|
6
6
|
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
|
-
export { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
9
|
+
export { annotationToolbarRegistration, lineReaderToolRegistration, magnificationToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
10
10
|
export { AUDIO_TRANSCRIPT_FEATURE_ID, AUDIO_TRANSCRIPT_REGION_CLASS, AUDIO_TRANSCRIPT_REGION_LABEL, audioTranscriptRegistration, CONTENT_LEAD_SURFACE, resolveAudioTranscript, } from "./registrations/audio-transcript.js";
|
|
11
|
-
export { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
11
|
+
export { calculatorToolRegistration, createCalculatorToolRegistration, } from "./registrations/calculator.js";
|
|
12
12
|
export { createDictionaryToolRegistration, createPictureDictionaryToolRegistration, dictionaryToolRegistration, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
13
13
|
export { answerEliminatorToolRegistration } from "./registrations/interaction-tools.js";
|
|
14
14
|
export { protractorToolRegistration, rulerToolRegistration, } from "./registrations/measurement-tools.js";
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* cannot leave a second hand-maintained catalogue silently behind.
|
|
9
9
|
*/
|
|
10
10
|
import { ToolRegistry, } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
11
|
-
import { annotationToolbarRegistration, lineReaderToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
11
|
+
import { annotationToolbarRegistration, lineReaderToolRegistration, magnificationToolRegistration, themeToolRegistration, } from "./registrations/accessibility-tools.js";
|
|
12
12
|
import { audioTranscriptRegistration } from "./registrations/audio-transcript.js";
|
|
13
13
|
import { calculatorToolRegistration } from "./registrations/calculator.js";
|
|
14
14
|
import { dictionaryToolRegistration, pictureDictionaryToolRegistration, spanishDictionaryToolRegistration, spanishPictureDictionaryToolRegistration, } from "./registrations/dictionary-tools.js";
|
|
@@ -28,6 +28,7 @@ const loadProtractorModule = () => loadSideEffectModule(() => import("@pie-playe
|
|
|
28
28
|
const loadAnswerEliminatorModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-answer-eliminator"));
|
|
29
29
|
const loadAnnotationToolbarModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-annotation-toolbar"));
|
|
30
30
|
const loadLineReaderModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-line-reader"));
|
|
31
|
+
const loadMagnifierModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-magnifier"));
|
|
31
32
|
const loadThemeModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-theme"));
|
|
32
33
|
const loadGraphModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-graph"));
|
|
33
34
|
const loadPeriodicTableModule = () => loadSideEffectModule(() => import("@pie-players/pie-tool-periodic-table"));
|
|
@@ -76,6 +77,15 @@ const PACKAGED_CAPABILITY_DEFINITIONS = [
|
|
|
76
77
|
preferredPlacementOrder: { section: 40 },
|
|
77
78
|
universal: true,
|
|
78
79
|
},
|
|
80
|
+
{
|
|
81
|
+
registration: magnificationToolRegistration,
|
|
82
|
+
tagName: "pie-tool-magnifier",
|
|
83
|
+
loadModule: loadMagnifierModule,
|
|
84
|
+
preferredPlacementOrder: { section: 45 },
|
|
85
|
+
// Magnification is a granted low-vision accommodation in AfA PNP, so it
|
|
86
|
+
// is never universal.
|
|
87
|
+
universal: false,
|
|
88
|
+
},
|
|
79
89
|
{
|
|
80
90
|
registration: themeToolRegistration,
|
|
81
91
|
tagName: "pie-tool-theme",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Registers tools for visual accessibility and reading support:
|
|
5
5
|
* - Line Reader (reading guide)
|
|
6
|
+
* - Magnifier (movable magnifying lens)
|
|
6
7
|
* - Color Scheme (theme/contrast)
|
|
7
8
|
* - Annotation Toolbar (text highlighting)
|
|
8
9
|
*/
|
|
@@ -14,6 +15,13 @@ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools
|
|
|
14
15
|
* Useful for text-heavy passages and questions.
|
|
15
16
|
*/
|
|
16
17
|
export declare const lineReaderToolRegistration: ToolRegistration;
|
|
18
|
+
/**
|
|
19
|
+
* Magnifier tool registration
|
|
20
|
+
*
|
|
21
|
+
* A movable lens that shows the content under it enlarged. The AfA
|
|
22
|
+
* `magnification` tool parameter `zoom` sets the lens's starting level.
|
|
23
|
+
*/
|
|
24
|
+
export declare const magnificationToolRegistration: ToolRegistration;
|
|
17
25
|
/**
|
|
18
26
|
* Theme tool registration
|
|
19
27
|
*
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Registers tools for visual accessibility and reading support:
|
|
5
5
|
* - Line Reader (reading guide)
|
|
6
|
+
* - Magnifier (movable magnifying lens)
|
|
6
7
|
* - Color Scheme (theme/contrast)
|
|
7
8
|
* - Annotation Toolbar (text highlighting)
|
|
8
9
|
*/
|
|
@@ -36,6 +37,43 @@ export const lineReaderToolRegistration = {
|
|
|
36
37
|
});
|
|
37
38
|
},
|
|
38
39
|
};
|
|
40
|
+
/** A `zoom` worth passing on: a finite magnification above 1. */
|
|
41
|
+
const normalizeMagnifierZoom = (value) => typeof value === "number" && Number.isFinite(value) && value > 1
|
|
42
|
+
? value
|
|
43
|
+
: undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Magnifier tool registration
|
|
46
|
+
*
|
|
47
|
+
* A movable lens that shows the content under it enlarged. The AfA
|
|
48
|
+
* `magnification` tool parameter `zoom` sets the lens's starting level.
|
|
49
|
+
*/
|
|
50
|
+
export const magnificationToolRegistration = {
|
|
51
|
+
toolId: "magnification",
|
|
52
|
+
name: "Magnifier",
|
|
53
|
+
description: "Magnify the content under a movable lens",
|
|
54
|
+
nameKey: "tools.magnification.name",
|
|
55
|
+
descriptionKey: "tools.magnification.description",
|
|
56
|
+
icon: "magnifying-glass",
|
|
57
|
+
supportedLevels: ["section", "passage", "rubric", "item"],
|
|
58
|
+
/**
|
|
59
|
+
* Pass 2: anything on screen can be magnified, text or not
|
|
60
|
+
*/
|
|
61
|
+
isVisibleInContext() {
|
|
62
|
+
return true;
|
|
63
|
+
},
|
|
64
|
+
renderToolbar(context, toolbarContext) {
|
|
65
|
+
const result = renderOverlayToolbar(this, context, toolbarContext, {
|
|
66
|
+
surface: "frameless",
|
|
67
|
+
});
|
|
68
|
+
const overlay = result.elements?.[0]?.element;
|
|
69
|
+
const zoom = normalizeMagnifierZoom(toolbarContext.getToolParameters?.("magnification")?.zoom);
|
|
70
|
+
if (zoom === undefined)
|
|
71
|
+
overlay?.removeAttribute("zoom");
|
|
72
|
+
else
|
|
73
|
+
overlay?.setAttribute("zoom", String(zoom));
|
|
74
|
+
return result;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
39
77
|
/**
|
|
40
78
|
* Theme tool registration
|
|
41
79
|
*
|
|
@@ -6,15 +6,26 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
8
8
|
import type { ToolProviderConfig } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
export
|
|
9
|
+
import { type CalculatorProviderDefinition } from "../calculator-providers/LazyCalculatorToolProvider.js";
|
|
10
|
+
export type { CalculatorProviderDefinition };
|
|
11
|
+
export interface CalculatorRegistrationOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Backends by `provider.id`, merged over the packaged Desmos and GeoGebra
|
|
14
|
+
* definitions. An entry under a packaged id replaces that backend.
|
|
15
|
+
*/
|
|
16
|
+
providers?: Readonly<Record<string, CalculatorProviderDefinition>>;
|
|
17
|
+
}
|
|
18
|
+
export declare function resolveCalculatorProviderId(config: ToolProviderConfig | undefined, providers?: Readonly<Record<string, CalculatorProviderDefinition>>): string;
|
|
12
19
|
/**
|
|
13
|
-
*
|
|
20
|
+
* Builds the calculator registration over the packaged backends plus any the
|
|
21
|
+
* host adds, so a host bundles a backend only by naming it.
|
|
14
22
|
*
|
|
15
23
|
* Supports:
|
|
16
|
-
* - Basic, scientific, and graphing calculators through
|
|
24
|
+
* - Basic, scientific, and graphing calculators through the backend that
|
|
25
|
+
* `provider.id` selects, Desmos by default
|
|
17
26
|
* - Context-aware visibility (shows only when math content is detected)
|
|
18
27
|
* - Item level only
|
|
19
28
|
*/
|
|
29
|
+
export declare function createCalculatorToolRegistration(options?: CalculatorRegistrationOptions): ToolRegistration;
|
|
30
|
+
/** The calculator over the packaged Desmos and GeoGebra backends. */
|
|
20
31
|
export declare const calculatorToolRegistration: ToolRegistration;
|
|
@@ -7,32 +7,21 @@
|
|
|
7
7
|
import { hasMathContent } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
8
8
|
import { createScopedToolId } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
9
9
|
import { createToolElement } from "@pie-players/pie-assessment-toolkit/tools/registration";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { GeoGebraToolProvider } from "../calculator-providers/GeoGebraToolProvider.js";
|
|
10
|
+
import { LazyCalculatorToolProvider, } from "../calculator-providers/LazyCalculatorToolProvider.js";
|
|
11
|
+
import { DEFAULT_CALCULATOR_PROVIDER_ID, PACKAGED_CALCULATOR_PROVIDERS, } from "../calculator-providers/packaged-calculator-providers.js";
|
|
13
12
|
import { resolveOverlayElement } from "./overlay-element-cache.js";
|
|
14
|
-
export
|
|
15
|
-
export function resolveCalculatorProviderId(config) {
|
|
13
|
+
export function resolveCalculatorProviderId(config, providers = PACKAGED_CALCULATOR_PROVIDERS) {
|
|
16
14
|
const configured = config?.provider?.id;
|
|
17
15
|
if (configured === undefined || configured === "") {
|
|
18
16
|
return DEFAULT_CALCULATOR_PROVIDER_ID;
|
|
19
17
|
}
|
|
20
|
-
if (configured === "
|
|
21
|
-
configured === "calculator-geogebra" ||
|
|
22
|
-
configured === "calculator-cortex") {
|
|
18
|
+
if (typeof configured === "string" && Object.hasOwn(providers, configured)) {
|
|
23
19
|
return configured;
|
|
24
20
|
}
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
case "calculator-cortex":
|
|
30
|
-
return new CortexToolProvider();
|
|
31
|
-
case "calculator-geogebra":
|
|
32
|
-
return new GeoGebraToolProvider();
|
|
33
|
-
default:
|
|
34
|
-
return new DesmosToolProvider();
|
|
35
|
-
}
|
|
21
|
+
const expected = Object.keys(providers)
|
|
22
|
+
.map((id) => `"${id}"`)
|
|
23
|
+
.join(", ");
|
|
24
|
+
throw new Error(`Unsupported calculator provider "${String(configured)}". Expected one of ${expected}.`);
|
|
36
25
|
}
|
|
37
26
|
function getCalculatorInstanceConfig(config) {
|
|
38
27
|
const theme = config?.theme;
|
|
@@ -104,169 +93,175 @@ function applyCalculatorParamsToElement(element, calculatorType, availableTypes,
|
|
|
104
93
|
}
|
|
105
94
|
}
|
|
106
95
|
/**
|
|
107
|
-
*
|
|
96
|
+
* Builds the calculator registration over the packaged backends plus any the
|
|
97
|
+
* host adds, so a host bundles a backend only by naming it.
|
|
108
98
|
*
|
|
109
99
|
* Supports:
|
|
110
|
-
* - Basic, scientific, and graphing calculators through
|
|
100
|
+
* - Basic, scientific, and graphing calculators through the backend that
|
|
101
|
+
* `provider.id` selects, Desmos by default
|
|
111
102
|
* - Context-aware visibility (shows only when math content is detected)
|
|
112
103
|
* - Item level only
|
|
113
104
|
*/
|
|
114
|
-
export
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
105
|
+
export function createCalculatorToolRegistration(options = {}) {
|
|
106
|
+
const providers = { ...PACKAGED_CALCULATOR_PROVIDERS, ...options.providers };
|
|
107
|
+
return {
|
|
108
|
+
toolId: "calculator",
|
|
109
|
+
name: "Calculator",
|
|
110
|
+
description: "Multi-type calculator (basic, scientific, graphing)",
|
|
111
|
+
nameKey: "tools.calculator.name",
|
|
112
|
+
descriptionKey: "tools.calculator.description",
|
|
113
|
+
icon: "calculator",
|
|
114
|
+
provider: {
|
|
115
|
+
createProvider: (config) => new LazyCalculatorToolProvider(providers[resolveCalculatorProviderId(config, providers)]),
|
|
116
|
+
getInitConfig: (config) => config?.provider?.init ?? {},
|
|
117
|
+
getAuthFetcher: (config) => {
|
|
118
|
+
const runtimeAuthFetcher = config?.provider?.runtime?.authFetcher;
|
|
119
|
+
return typeof runtimeAuthFetcher === "function"
|
|
120
|
+
? runtimeAuthFetcher
|
|
121
|
+
: undefined;
|
|
122
|
+
},
|
|
123
|
+
lazy: true,
|
|
124
|
+
},
|
|
125
|
+
// Calculator is item-level in this player architecture.
|
|
126
|
+
supportedLevels: ["item"],
|
|
127
|
+
/**
|
|
128
|
+
* Pass 2: Determine if calculator is relevant in this context
|
|
129
|
+
*
|
|
130
|
+
* Calculator is relevant when context contains mathematical content
|
|
131
|
+
* (MathML, LaTeX, arithmetic markers).
|
|
132
|
+
*/
|
|
133
|
+
isVisibleInContext(context) {
|
|
134
|
+
return hasMathContent(context);
|
|
129
135
|
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
*/
|
|
231
|
-
initialAlign: "bottom-left",
|
|
232
|
-
initialMargin: 16,
|
|
233
|
-
// Header controls in the host's design system, and the layout that
|
|
234
|
-
// goes with them.
|
|
235
|
-
ndsHeaderControls: true,
|
|
236
|
-
// A learner reads the question while using the calculator, so Tab and
|
|
237
|
-
// Shift+Tab cross between the page and the shell instead of cycling
|
|
238
|
-
// inside it.
|
|
239
|
-
pageTabOrder: true,
|
|
240
|
-
content: {
|
|
241
|
-
overflowY: "auto",
|
|
242
|
-
preserveMinHeight: true,
|
|
136
|
+
renderToolbar(context, toolbarContext) {
|
|
137
|
+
const { calculatorType, availableTypes, displayName } = getCalculatorRenderParams(toolbarContext);
|
|
138
|
+
const calculatorToolConfig = toolbarContext.toolkitCoordinator?.getToolConfig(this.toolId) ||
|
|
139
|
+
undefined;
|
|
140
|
+
const calculatorConfig = getCalculatorInstanceConfig(calculatorToolConfig);
|
|
141
|
+
const fullToolId = createScopedToolId(this.toolId, toolbarContext.scope.level, toolbarContext.scope.scopeId);
|
|
142
|
+
const componentOverrides = toolbarContext.componentOverrides;
|
|
143
|
+
// Reused across renders: besides keeping state, this spares a Desmos boot
|
|
144
|
+
// and container mount on every re-render.
|
|
145
|
+
const overlay = resolveOverlayElement(toolbarContext, fullToolId, () => createToolElement(this.toolId, context, toolbarContext, componentOverrides));
|
|
146
|
+
overlay.setAttribute("tool-id", fullToolId);
|
|
147
|
+
applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, calculatorConfig);
|
|
148
|
+
const button = {
|
|
149
|
+
toolId: this.toolId,
|
|
150
|
+
label: displayName,
|
|
151
|
+
icon: typeof this.icon === "function" ? this.icon(context) : this.icon,
|
|
152
|
+
// Routes this button through <nds-icon-button> where the host enables NDS
|
|
153
|
+
// icons. Declared here because which capabilities render in the host's
|
|
154
|
+
// design system is a composition decision.
|
|
155
|
+
faIconName: "calculator",
|
|
156
|
+
disabled: false,
|
|
157
|
+
// The name stays put across open and closed. The toolbar mirrors
|
|
158
|
+
// `active` onto the button as `aria-pressed`, so the state is already
|
|
159
|
+
// exposed; a name that also swapped to "Close …" would contradict it.
|
|
160
|
+
ariaLabel: displayName,
|
|
161
|
+
tooltip: displayName,
|
|
162
|
+
onClick: () => toolbarContext.toggleTool(this.toolId),
|
|
163
|
+
active: toolbarContext.isToolVisible(this.toolId),
|
|
164
|
+
};
|
|
165
|
+
let lastVisibleState = button.active;
|
|
166
|
+
if (overlay.visible !== button.active) {
|
|
167
|
+
overlay.visible = button.active;
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
toolId: this.toolId,
|
|
171
|
+
elements: [
|
|
172
|
+
{
|
|
173
|
+
element: overlay,
|
|
174
|
+
mount: "after-buttons",
|
|
175
|
+
shell: {
|
|
176
|
+
// The variant name the button already carries — "Basic Calculator",
|
|
177
|
+
// not the registration's generic one.
|
|
178
|
+
title: displayName,
|
|
179
|
+
draggable: true,
|
|
180
|
+
resizable: true,
|
|
181
|
+
closeable: true,
|
|
182
|
+
/*
|
|
183
|
+
* Sized per type from what each layout measures, rather than one
|
|
184
|
+
* size for all three. A shell subtracts ~74px of header from the
|
|
185
|
+
* height it is given, and the numbers below are the content each
|
|
186
|
+
* type needs plus room for its history tape:
|
|
187
|
+
*
|
|
188
|
+
* - basic: strip, display, edit row and a four-row keypad measure
|
|
189
|
+
* 398px. 560 left ~90px of blank above the entry line, which is
|
|
190
|
+
* the gap that made the panel look mis-sized.
|
|
191
|
+
* - scientific: the same plus a keypad layer tab row.
|
|
192
|
+
* - graphing: the expression rail beside the plot, whose column
|
|
193
|
+
* wants 486px on its own — viewport controls, a 14rem board floor
|
|
194
|
+
* and the readout that *is* the graph for assistive technology,
|
|
195
|
+
* since the board itself is `aria-hidden`. At 620 that column was
|
|
196
|
+
* 12px short and the readout's last line was cut off.
|
|
197
|
+
*
|
|
198
|
+
* The minimums stay shared across types and backends. One
|
|
199
|
+
* registration serves every backend, so a graphing-only floor
|
|
200
|
+
* would move the resize limit under vendors whose layouts were
|
|
201
|
+
* never measured for it. Cortex below 42rem stacks the rail above
|
|
202
|
+
* the plot and needs 701px there, which no spacing tier closes — it
|
|
203
|
+
* scrolls its own content instead of clipping it, which is the
|
|
204
|
+
* contract every size below the opening one already relies on.
|
|
205
|
+
*/
|
|
206
|
+
initialWidth: calculatorType === "graphing" ? 720 : 380,
|
|
207
|
+
initialHeight: calculatorType === "graphing"
|
|
208
|
+
? 660
|
|
209
|
+
: calculatorType === "basic"
|
|
210
|
+
? 500
|
|
211
|
+
: 560,
|
|
212
|
+
minWidth: 380,
|
|
213
|
+
minHeight: 480,
|
|
214
|
+
/*
|
|
215
|
+
* `bottom-right` put a 560-620px-tall shell over the items
|
|
216
|
+
* column it shares the viewport with — tall enough, at
|
|
217
|
+
* ordinary viewport heights, to sit on top of a sibling
|
|
218
|
+
* item's own toolbar row and block its button from mouse
|
|
219
|
+
* and touch input. `bottom-left` keeps the same footprint
|
|
220
|
+
* over the passage column instead, which carries no
|
|
221
|
+
* per-item controls to collide with.
|
|
222
|
+
*/
|
|
223
|
+
initialAlign: "bottom-left",
|
|
224
|
+
initialMargin: 16,
|
|
225
|
+
// Header controls in the host's design system, and the layout that
|
|
226
|
+
// goes with them.
|
|
227
|
+
ndsHeaderControls: true,
|
|
228
|
+
// A learner reads the question while using the calculator, so Tab and
|
|
229
|
+
// Shift+Tab cross between the page and the shell instead of cycling
|
|
230
|
+
// inside it.
|
|
231
|
+
pageTabOrder: true,
|
|
232
|
+
content: {
|
|
233
|
+
overflowY: "auto",
|
|
234
|
+
preserveMinHeight: true,
|
|
235
|
+
},
|
|
243
236
|
},
|
|
244
237
|
},
|
|
238
|
+
],
|
|
239
|
+
button,
|
|
240
|
+
sync: () => {
|
|
241
|
+
const active = toolbarContext.isToolVisible(this.toolId);
|
|
242
|
+
button.active = active;
|
|
243
|
+
button.label = displayName;
|
|
244
|
+
// Static across the toggle: `aria-pressed` carries the state, and a
|
|
245
|
+
// "Close …" template built from a localized noun mixes languages
|
|
246
|
+
// ("Close rekenmachine" under nl-NL).
|
|
247
|
+
button.ariaLabel = displayName;
|
|
248
|
+
button.tooltip = displayName;
|
|
249
|
+
if (lastVisibleState !== active) {
|
|
250
|
+
overlay.visible = active;
|
|
251
|
+
lastVisibleState = active;
|
|
252
|
+
}
|
|
253
|
+
applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, calculatorConfig);
|
|
245
254
|
},
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
lastVisibleState = active;
|
|
260
|
-
}
|
|
261
|
-
applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, calculatorConfig);
|
|
262
|
-
},
|
|
263
|
-
subscribeActive: (callback) => {
|
|
264
|
-
if (!toolbarContext.subscribeVisibility)
|
|
265
|
-
return () => { };
|
|
266
|
-
return toolbarContext.subscribeVisibility(() => {
|
|
267
|
-
callback(toolbarContext.isToolVisible(this.toolId));
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
|
-
};
|
|
271
|
-
},
|
|
272
|
-
};
|
|
255
|
+
subscribeActive: (callback) => {
|
|
256
|
+
if (!toolbarContext.subscribeVisibility)
|
|
257
|
+
return () => { };
|
|
258
|
+
return toolbarContext.subscribeVisibility(() => {
|
|
259
|
+
callback(toolbarContext.isToolVisible(this.toolId));
|
|
260
|
+
});
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/** The calculator over the packaged Desmos and GeoGebra backends. */
|
|
267
|
+
export const calculatorToolRegistration = createCalculatorToolRegistration();
|
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.4",
|
|
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,25 +33,25 @@
|
|
|
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-
|
|
39
|
-
"@pie-players/pie-calculator-
|
|
40
|
-
"@pie-players/pie-
|
|
41
|
-
"@pie-players/pie-
|
|
42
|
-
"@pie-players/pie-tool-
|
|
43
|
-
"@pie-players/pie-tool-
|
|
44
|
-
"@pie-players/pie-tool-
|
|
45
|
-
"@pie-players/pie-tool-
|
|
46
|
-
"@pie-players/pie-tool-
|
|
47
|
-
"@pie-players/pie-tool-
|
|
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.4",
|
|
37
|
+
"@pie-players/pie-calculator": "1.0.0-beta.4",
|
|
38
|
+
"@pie-players/pie-calculator-desmos": "1.0.0-beta.4",
|
|
39
|
+
"@pie-players/pie-calculator-geogebra": "1.0.0-beta.4",
|
|
40
|
+
"@pie-players/pie-players-shared": "1.0.0-beta.4",
|
|
41
|
+
"@pie-players/pie-tool-annotation-toolbar": "1.0.0-beta.4",
|
|
42
|
+
"@pie-players/pie-tool-answer-eliminator": "1.0.0-beta.4",
|
|
43
|
+
"@pie-players/pie-tool-calculator-shared": "1.0.0-beta.4",
|
|
44
|
+
"@pie-players/pie-tool-dictionary": "1.0.0-beta.4",
|
|
45
|
+
"@pie-players/pie-tool-graph": "1.0.0-beta.4",
|
|
46
|
+
"@pie-players/pie-tool-line-reader": "1.0.0-beta.4",
|
|
47
|
+
"@pie-players/pie-tool-magnifier": "1.0.0-beta.4",
|
|
48
|
+
"@pie-players/pie-tool-periodic-table": "1.0.0-beta.4",
|
|
49
|
+
"@pie-players/pie-tool-picture-dictionary": "1.0.0-beta.4",
|
|
50
|
+
"@pie-players/pie-tool-protractor": "1.0.0-beta.4",
|
|
51
|
+
"@pie-players/pie-tool-ruler": "1.0.0-beta.4",
|
|
52
|
+
"@pie-players/pie-tool-theme": "1.0.0-beta.4",
|
|
53
|
+
"@pie-players/pie-tool-tts-inline": "1.0.0-beta.4",
|
|
54
|
+
"@pie-players/tts-client-server": "1.0.0-beta.4"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@biomejs/biome": "^2.5.15",
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/** Fully bundled open-source calculator adapter for the tool-provider registry. */
|
|
2
|
-
import type { CalculatorToolProviderInitConfig, LazyCalculatorProviderDefinition } from "./LazyCalculatorToolProvider.js";
|
|
3
|
-
import { LazyCalculatorToolProvider } from "./LazyCalculatorToolProvider.js";
|
|
4
|
-
export type CortexToolProviderConfig = CalculatorToolProviderInitConfig;
|
|
5
|
-
export declare class CortexToolProvider extends LazyCalculatorToolProvider<CortexToolProviderConfig> {
|
|
6
|
-
readonly providerName = "PIE Open-Source Calculator";
|
|
7
|
-
readonly version = "1";
|
|
8
|
-
readonly requiresAuth = false;
|
|
9
|
-
protected getDefinition(): LazyCalculatorProviderDefinition<CortexToolProviderConfig>;
|
|
10
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/** Fully bundled open-source calculator adapter for the tool-provider registry. */
|
|
2
|
-
import { LazyCalculatorToolProvider } from "./LazyCalculatorToolProvider.js";
|
|
3
|
-
export class CortexToolProvider extends LazyCalculatorToolProvider {
|
|
4
|
-
providerName = "PIE Open-Source Calculator";
|
|
5
|
-
version = "1";
|
|
6
|
-
requiresAuth = false;
|
|
7
|
-
getDefinition() {
|
|
8
|
-
return {
|
|
9
|
-
backend: "cortex",
|
|
10
|
-
moduleImportOperation: "cortex-provider-module-import",
|
|
11
|
-
loadProvider: async () => {
|
|
12
|
-
const module = await import("@pie-players/pie-calculator-cortex");
|
|
13
|
-
return module.CortexCalculatorProvider;
|
|
14
|
-
},
|
|
15
|
-
initializationErrorMessage: "Failed to initialize the PIE open-source calculator provider. Confirm that this browser supports module workers and that the bundled worker assets are available.",
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/** Desmos calculator adapter for the generic tool-provider registry. */
|
|
2
|
-
import type { CalculatorProviderInit } from "@pie-players/pie-calculator";
|
|
3
|
-
import { LazyCalculatorToolProvider, type LazyCalculatorProviderDefinition } from "./LazyCalculatorToolProvider.js";
|
|
4
|
-
/** Provider initialization is the provider-neutral calculator contract. */
|
|
5
|
-
export type DesmosToolProviderConfig = CalculatorProviderInit;
|
|
6
|
-
export declare class DesmosToolProvider extends LazyCalculatorToolProvider<DesmosToolProviderConfig> {
|
|
7
|
-
readonly providerName = "Desmos Calculator";
|
|
8
|
-
readonly version = "1.12";
|
|
9
|
-
readonly requiresAuth = true;
|
|
10
|
-
protected getDefinition(): LazyCalculatorProviderDefinition<DesmosToolProviderConfig>;
|
|
11
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/** Desmos calculator adapter for the generic tool-provider registry. */
|
|
2
|
-
import { LazyCalculatorToolProvider, } from "./LazyCalculatorToolProvider.js";
|
|
3
|
-
export class DesmosToolProvider extends LazyCalculatorToolProvider {
|
|
4
|
-
providerName = "Desmos Calculator";
|
|
5
|
-
version = "1.12";
|
|
6
|
-
requiresAuth = true;
|
|
7
|
-
getDefinition() {
|
|
8
|
-
return {
|
|
9
|
-
backend: "desmos",
|
|
10
|
-
moduleImportOperation: "desmos-provider-module-import",
|
|
11
|
-
loadProvider: async () => {
|
|
12
|
-
const module = await import("@pie-players/pie-calculator-desmos");
|
|
13
|
-
return module.DesmosCalculatorProvider;
|
|
14
|
-
},
|
|
15
|
-
initializationErrorMessage: "Failed to initialize Desmos calculator provider. Check the application key, preloaded API, runtime endpoint, or network access.",
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/** GeoGebra calculator adapter for the generic tool-provider registry. */
|
|
2
|
-
import type { CalculatorToolProviderInitConfig, LazyCalculatorProviderDefinition } from "./LazyCalculatorToolProvider.js";
|
|
3
|
-
import { LazyCalculatorToolProvider } from "./LazyCalculatorToolProvider.js";
|
|
4
|
-
export interface GeoGebraToolProviderConfig extends CalculatorToolProviderInitConfig {
|
|
5
|
-
scriptUrl?: string;
|
|
6
|
-
appletTimeoutMs?: number;
|
|
7
|
-
}
|
|
8
|
-
export declare class GeoGebraToolProvider extends LazyCalculatorToolProvider<GeoGebraToolProviderConfig> {
|
|
9
|
-
readonly providerName = "GeoGebra Calculator";
|
|
10
|
-
readonly version = "6";
|
|
11
|
-
readonly requiresAuth = false;
|
|
12
|
-
protected getDefinition(): LazyCalculatorProviderDefinition<GeoGebraToolProviderConfig>;
|
|
13
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/** GeoGebra calculator adapter for the generic tool-provider registry. */
|
|
2
|
-
import { LazyCalculatorToolProvider } from "./LazyCalculatorToolProvider.js";
|
|
3
|
-
export class GeoGebraToolProvider extends LazyCalculatorToolProvider {
|
|
4
|
-
providerName = "GeoGebra Calculator";
|
|
5
|
-
version = "6";
|
|
6
|
-
requiresAuth = false;
|
|
7
|
-
getDefinition() {
|
|
8
|
-
return {
|
|
9
|
-
backend: "geogebra",
|
|
10
|
-
moduleImportOperation: "geogebra-provider-module-import",
|
|
11
|
-
loadProvider: async () => {
|
|
12
|
-
const module = await import("@pie-players/pie-calculator-geogebra");
|
|
13
|
-
return module.GeoGebraCalculatorProvider;
|
|
14
|
-
},
|
|
15
|
-
initializationErrorMessage: "Failed to initialize GeoGebra calculator provider. Confirm that the deployment may load GeoGebra and that its script URL is reachable.",
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
}
|