@pie-players/pie-default-tool-loaders 0.3.74 → 0.3.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +47 -57
  2. package/dist/calculator-providers/CortexToolProvider.d.ts +1 -2
  3. package/dist/calculator-providers/CortexToolProvider.js +0 -1
  4. package/dist/calculator-providers/DesmosToolProvider.d.ts +1 -2
  5. package/dist/calculator-providers/DesmosToolProvider.js +0 -1
  6. package/dist/calculator-providers/GeoGebraToolProvider.d.ts +1 -2
  7. package/dist/calculator-providers/GeoGebraToolProvider.js +0 -1
  8. package/dist/calculator-providers/LazyCalculatorToolProvider.d.ts +2 -3
  9. package/dist/content-alternates.d.ts +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +1 -1
  12. package/dist/packaged-capability-composition.d.ts +17 -49
  13. package/dist/packaged-capability-composition.js +60 -261
  14. package/dist/registrations/accessibility-tools.d.ts +1 -5
  15. package/dist/registrations/accessibility-tools.js +6 -40
  16. package/dist/registrations/audio-transcript.d.ts +1 -1
  17. package/dist/registrations/audio-transcript.js +0 -1
  18. package/dist/registrations/calculator.d.ts +2 -6
  19. package/dist/registrations/calculator.js +9 -31
  20. package/dist/registrations/dictionary-tools.d.ts +6 -5
  21. package/dist/registrations/dictionary-tools.js +21 -26
  22. package/dist/registrations/interaction-tools.d.ts +1 -7
  23. package/dist/registrations/interaction-tools.js +22 -27
  24. package/dist/registrations/measurement-tools.d.ts +1 -5
  25. package/dist/registrations/measurement-tools.js +1 -17
  26. package/dist/registrations/overlay-element-cache.d.ts +3 -1
  27. package/dist/registrations/overlay-element-cache.js +2 -1
  28. package/dist/registrations/overlay-toolbar-render.d.ts +3 -10
  29. package/dist/registrations/overlay-toolbar-render.js +3 -7
  30. package/dist/registrations/selection-actions.d.ts +1 -1
  31. package/dist/registrations/selection-actions.js +1 -1
  32. package/dist/registrations/subject-specific-tools.d.ts +1 -5
  33. package/dist/registrations/subject-specific-tools.js +1 -15
  34. package/dist/registrations/tts.d.ts +1 -6
  35. package/dist/registrations/tts.js +36 -89
  36. package/package.json +22 -23
@@ -3,13 +3,9 @@
3
3
  *
4
4
  * Registers the calculator tool with support for multiple calculator types
5
5
  * (basic, scientific, graphing) through a host-selected provider.
6
- *
7
- * Maps to QTI 3.0 standard access features:
8
- * - calculator (cognitive support)
9
- * - graphingCalculator (assessment tool)
10
6
  */
11
- import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
12
- import type { ToolProviderConfig } from "@pie-players/pie-assessment-toolkit/tools/internal";
7
+ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
8
+ import type { ToolProviderConfig } from "@pie-players/pie-assessment-toolkit/tools/registration";
13
9
  export type CalculatorProviderId = "calculator-desmos" | "calculator-geogebra" | "calculator-cortex";
14
10
  export declare const DEFAULT_CALCULATOR_PROVIDER_ID: CalculatorProviderId;
15
11
  export declare function resolveCalculatorProviderId(config: ToolProviderConfig | undefined): CalculatorProviderId;
@@ -3,14 +3,10 @@
3
3
  *
4
4
  * Registers the calculator tool with support for multiple calculator types
5
5
  * (basic, scientific, graphing) through a host-selected provider.
6
- *
7
- * Maps to QTI 3.0 standard access features:
8
- * - calculator (cognitive support)
9
- * - graphingCalculator (assessment tool)
10
6
  */
11
- import { hasMathContent } from "@pie-players/pie-assessment-toolkit/tools/internal";
12
- import { createScopedToolId } from "@pie-players/pie-assessment-toolkit/tools/internal";
13
- import { createToolElement } from "@pie-players/pie-assessment-toolkit/tools/internal";
7
+ import { hasMathContent } from "@pie-players/pie-assessment-toolkit/tools/registration";
8
+ import { createScopedToolId } from "@pie-players/pie-assessment-toolkit/tools/registration";
9
+ import { createToolElement } from "@pie-players/pie-assessment-toolkit/tools/registration";
14
10
  import { CortexToolProvider } from "../calculator-providers/CortexToolProvider.js";
15
11
  import { DesmosToolProvider } from "../calculator-providers/DesmosToolProvider.js";
16
12
  import { GeoGebraToolProvider } from "../calculator-providers/GeoGebraToolProvider.js";
@@ -86,11 +82,9 @@ const CALCULATOR_NAME_KEYS = {
86
82
  graphing: "tools.calculator.nameGraphing",
87
83
  untyped: "tools.calculator.name",
88
84
  };
89
- function applyCalculatorParamsToElement(element, calculatorType, availableTypes, providerId, calculatorConfig) {
85
+ function applyCalculatorParamsToElement(element, calculatorType, availableTypes, calculatorConfig) {
90
86
  const calculatorElement = element;
91
- calculatorElement.providerId = providerId;
92
87
  calculatorElement.calculatorConfig = calculatorConfig;
93
- element.setAttribute("provider-id", providerId);
94
88
  if (calculatorType) {
95
89
  calculatorElement.calculatorType = calculatorType;
96
90
  element.setAttribute("calculator-type", calculatorType);
@@ -122,7 +116,6 @@ export const calculatorToolRegistration = {
122
116
  descriptionKey: "tools.calculator.description",
123
117
  icon: "calculator",
124
118
  provider: {
125
- getProviderId: resolveCalculatorProviderId,
126
119
  createProvider: createCalculatorToolProvider,
127
120
  getInitConfig: (config) => config?.provider?.init ?? {},
128
121
  getAuthFetcher: (config) => {
@@ -135,16 +128,6 @@ export const calculatorToolRegistration = {
135
128
  },
136
129
  // Calculator is item-level in this player architecture.
137
130
  supportedLevels: ["item"],
138
- // PNP support IDs that enable this tool
139
- // Maps to QTI 3.0 standard features: calculator, graphingCalculator
140
- // A type is not a feature id: `calculatorType` arrives through the host's
141
- // render params, so `basicCalculator` / `scientificCalculator` granted the
142
- // same untyped calculator these two do and only looked like they selected a
143
- // variant.
144
- pnpSupportIds: [
145
- "calculator", // QTI 3.0 standard (cognitive.calculator)
146
- "graphingCalculator", // QTI 3.0 standard (assessment.graphingCalculator)
147
- ],
148
131
  /**
149
132
  * Pass 2: Determine if calculator is relevant in this context
150
133
  *
@@ -159,7 +142,6 @@ export const calculatorToolRegistration = {
159
142
  const { calculatorType, availableTypes, displayName } = getCalculatorRenderParams(toolbarContext);
160
143
  const calculatorToolConfig = toolbarContext.toolkitCoordinator?.getToolConfig(this.toolId) ||
161
144
  undefined;
162
- const providerId = resolveCalculatorProviderId(calculatorToolConfig);
163
145
  const calculatorConfig = getCalculatorInstanceConfig(calculatorToolConfig);
164
146
  const fullToolId = createScopedToolId(this.toolId, toolbarContext.scope.level, toolbarContext.scope.scopeId);
165
147
  const componentOverrides = toolbarContext.componentOverrides;
@@ -167,8 +149,7 @@ export const calculatorToolRegistration = {
167
149
  // and container mount on every re-render.
168
150
  const overlay = resolveOverlayElement(toolbarContext, fullToolId, () => createToolElement(this.toolId, context, toolbarContext, componentOverrides));
169
151
  overlay.setAttribute("tool-id", fullToolId);
170
- overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
171
- applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, providerId, calculatorConfig);
152
+ applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, calculatorConfig);
172
153
  const button = {
173
154
  toolId: this.toolId,
174
155
  label: displayName,
@@ -185,7 +166,7 @@ export const calculatorToolRegistration = {
185
166
  ariaLabel: displayName,
186
167
  tooltip: displayName,
187
168
  onClick: () => toolbarContext.toggleTool(this.toolId),
188
- active: toolbarContext.isToolVisible(fullToolId),
169
+ active: toolbarContext.isToolVisible(this.toolId),
189
170
  };
190
171
  let lastVisibleState = button.active;
191
172
  if (overlay.visible !== button.active) {
@@ -264,7 +245,7 @@ export const calculatorToolRegistration = {
264
245
  ],
265
246
  button,
266
247
  sync: () => {
267
- const active = toolbarContext.isToolVisible(fullToolId);
248
+ const active = toolbarContext.isToolVisible(this.toolId);
268
249
  button.active = active;
269
250
  button.label = displayName;
270
251
  // Static across the toggle. The previous `Close ${name.toLowerCase()}`
@@ -277,16 +258,13 @@ export const calculatorToolRegistration = {
277
258
  overlay.visible = active;
278
259
  lastVisibleState = active;
279
260
  }
280
- if (overlay.toolkitCoordinator !== toolbarContext.toolkitCoordinator) {
281
- overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
282
- }
283
- applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, providerId, calculatorConfig);
261
+ applyCalculatorParamsToElement(overlay, calculatorType, availableTypes, calculatorConfig);
284
262
  },
285
263
  subscribeActive: (callback) => {
286
264
  if (!toolbarContext.subscribeVisibility)
287
265
  return () => { };
288
266
  return toolbarContext.subscribeVisibility(() => {
289
- callback(toolbarContext.isToolVisible(fullToolId));
267
+ callback(toolbarContext.isToolVisible(this.toolId));
290
268
  });
291
269
  },
292
270
  };
@@ -15,7 +15,7 @@
15
15
  * there without caret browsing, an OS toggle absent on mobile — so a selection-only
16
16
  * dictionary is unreachable for them. The panel's own field is the keyboard route.
17
17
  */
18
- import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
18
+ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
19
19
  /**
20
20
  * What distinguishes one dictionary capability from another.
21
21
  *
@@ -32,14 +32,15 @@ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools
32
32
  * so a host catalog that lacks one is a plain label rather than a broken button.
33
33
  */
34
34
  export interface DictionaryVariantOptions {
35
- /** Capability id, unique per language. Defaults to the base tool's id. */
35
+ /**
36
+ * Capability id, unique per language, and the PNP support id that grants it.
37
+ * Defaults to the base tool's id.
38
+ */
36
39
  toolId?: string;
37
40
  name?: string;
38
41
  description?: string;
39
42
  /** Catalog prefix for this variant's strings. Defaults to `tools.<toolId>`. */
40
43
  messageKeyPrefix?: string;
41
- /** PNP ids that grant this variant. A language variant needs its own. */
42
- pnpSupportIds?: string[];
43
44
  /**
44
45
  * The corpus language this capability looks words up in, as a BCP-47 tag.
45
46
  *
@@ -53,7 +54,7 @@ export interface DictionaryVariantOptions {
53
54
  * Dictionary tool registration
54
55
  *
55
56
  * 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
+ * `toolId` and `lookupLanguage` to offer a second language beside it.
57
58
  */
58
59
  export declare function createDictionaryToolRegistration(options?: DictionaryVariantOptions): ToolRegistration;
59
60
  /** The content-following dictionary every deployment gets. */
@@ -15,8 +15,14 @@
15
15
  * there without caret browsing, an OS toggle absent on mobile — so a selection-only
16
16
  * dictionary is unreachable for them. The panel's own field is the keyboard route.
17
17
  */
18
- import { createScopedVisibilityBinding, createToolElement, hasReadableText, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/internal";
18
+ import { createScopedVisibilityBinding, createToolElement, hasReadableText, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/registration";
19
19
  import { resolveOverlayElement } from "./overlay-element-cache.js";
20
+ /**
21
+ * The lookup fields each panel last took from render params. The panel outlives
22
+ * renders, so a field the host stops supplying is cleared here; a field it never
23
+ * supplied, such as one a component factory set, is left alone.
24
+ */
25
+ const appliedLookupFields = new WeakMap();
20
26
  /**
21
27
  * Apply the host's per-tool render params to the panel.
22
28
  *
@@ -34,14 +40,23 @@ function applyLookupParams(element, toolId, toolbarContext,
34
40
  /** A language variant's own corpus language; see {@link DictionaryVariantOptions}. */
35
41
  lookupLanguage) {
36
42
  const params = toolbarContext.getToolRenderParams?.(toolId) ?? {};
43
+ const supplied = {};
37
44
  if (typeof params.endpoint === "string")
38
- element.endpoint = params.endpoint;
45
+ supplied.endpoint = params.endpoint;
39
46
  if (typeof params.lookup === "function")
40
- element.lookup = params.lookup;
47
+ supplied.lookup = params.lookup;
41
48
  if (typeof params.headers === "function")
42
- element.headers = params.headers;
49
+ supplied.headers = params.headers;
43
50
  if (typeof params.credentials === "string")
44
- element.credentials = params.credentials;
51
+ supplied.credentials = params.credentials;
52
+ // A dropped `lookup` left in place would keep outranking the endpoint that
53
+ // replaced it.
54
+ for (const field of appliedLookupFields.get(element) ?? []) {
55
+ if (!(field in supplied))
56
+ element[field] = undefined;
57
+ }
58
+ Object.assign(element, supplied);
59
+ appliedLookupFields.set(element, new Set(Object.keys(supplied)));
45
60
  // The selection door: a gateway acting on the learner's selection requests this
46
61
  // tool with the words in `term`, and the toolbar layers that over the host's own
47
62
  // params. The toolbar stamps every request with a neutral `toolRequestId` — core
@@ -122,7 +137,7 @@ function renderDictionaryPanel(args) {
122
137
  * Dictionary tool registration
123
138
  *
124
139
  * Word lookup from a host-supplied service, in one language. Call this again with another
125
- * `toolId`, `pnpSupportIds` and `lookupLanguage` to offer a second language beside it.
140
+ * `toolId` and `lookupLanguage` to offer a second language beside it.
126
141
  */
127
142
  export function createDictionaryToolRegistration(options = {}) {
128
143
  const toolId = options.toolId ?? "dictionary";
@@ -136,15 +151,6 @@ export function createDictionaryToolRegistration(options = {}) {
136
151
  icon: "book-open",
137
152
  // Text can appear at any of these; the panel itself floats at section scope.
138
153
  supportedLevels: ["section", "item", "passage", "rubric"],
139
- // PNP support IDs
140
- // Maps to AfA PNP 3.0 / QTI 3.0 dictionary support, plus the common variants a
141
- // host profile is likely to carry.
142
- pnpSupportIds: options.pnpSupportIds ?? [
143
- "dictionary", // Canonical id
144
- "englishDictionary", // Common variant
145
- "glossary", // Common variant
146
- "definitions", // Common variant
147
- ],
148
154
  /** Pass 2: a dictionary is relevant wherever there is text to look words up from. */
149
155
  isVisibleInContext(context) {
150
156
  return hasReadableText(context);
@@ -185,15 +191,6 @@ export function createPictureDictionaryToolRegistration(options = {}) {
185
191
  descriptionKey: `${prefix}.description`,
186
192
  icon: "photo",
187
193
  supportedLevels: ["section", "item", "passage", "rubric"],
188
- // PNP support IDs
189
- // AfA PNP 3.0 names an illustrated equivalent of a glossary; the variants cover
190
- // what host profiles call it in practice.
191
- pnpSupportIds: options.pnpSupportIds ?? [
192
- "pictureDictionary", // Canonical id
193
- "illustratedGlossary", // Common variant
194
- "symbolDictionary", // Common variant
195
- "pictureSupport", // Common variant
196
- ],
197
194
  isVisibleInContext(context) {
198
195
  return hasReadableText(context);
199
196
  },
@@ -224,13 +221,11 @@ export const spanishDictionaryToolRegistration = createDictionaryToolRegistratio
224
221
  toolId: "dictionarySpanish",
225
222
  name: "Spanish Dictionary",
226
223
  description: "Look up word definitions in Spanish",
227
- pnpSupportIds: ["spanishDictionary"],
228
224
  lookupLanguage: "es",
229
225
  });
230
226
  export const spanishPictureDictionaryToolRegistration = createPictureDictionaryToolRegistration({
231
227
  toolId: "pictureDictionarySpanish",
232
228
  name: "Spanish Picture Dictionary",
233
229
  description: "Look up pictures for words in Spanish",
234
- pnpSupportIds: ["spanishPictureDictionary"],
235
230
  lookupLanguage: "es",
236
231
  });
@@ -3,14 +3,8 @@
3
3
  *
4
4
  * Registers tools for interacting with question content:
5
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
6
  */
13
- import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
7
+ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
14
8
  /**
15
9
  * Answer Eliminator tool registration
16
10
  *
@@ -3,17 +3,28 @@
3
3
  *
4
4
  * Registers tools for interacting with question content:
5
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
6
  */
13
- import { hasChoiceInteraction } from "@pie-players/pie-assessment-toolkit/tools/internal";
14
- import { createToolElement, } from "@pie-players/pie-assessment-toolkit/tools/internal";
15
- import { createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/internal";
7
+ import { hasChoiceInteraction } from "@pie-players/pie-assessment-toolkit/tools/registration";
8
+ import { createToolElement, } from "@pie-players/pie-assessment-toolkit/tools/registration";
9
+ import { createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/registration";
16
10
  import { resolveOverlayElement } from "./overlay-element-cache.js";
11
+ /** `tools.providers.answerEliminator.strategy`, defaulting to strikethrough. */
12
+ const normalizeEliminationStrategy = (value) => value === "mask" ? "mask" : "strikethrough";
13
+ /** The state-store key of each PIE element in the item, by model id. */
14
+ function resolveElementStateKeys(context, toolbarContext) {
15
+ const keys = {};
16
+ if (!("item" in context) || !toolbarContext.getGlobalElementId)
17
+ return keys;
18
+ for (const model of context.item?.config?.models ?? []) {
19
+ const elementId = model?.id;
20
+ if (typeof elementId !== "string" || !elementId)
21
+ continue;
22
+ const key = toolbarContext.getGlobalElementId(elementId);
23
+ if (key)
24
+ keys[elementId] = key;
25
+ }
26
+ return keys;
27
+ }
17
28
  /**
18
29
  * Answer Eliminator tool registration
19
30
  *
@@ -29,13 +40,6 @@ export const answerEliminatorToolRegistration = {
29
40
  icon: "strikethrough",
30
41
  // Answer eliminator appears at item level only
31
42
  supportedLevels: ["item"],
32
- // PNP support IDs
33
- // Maps to QTI 3.0 standard feature: answerMasking
34
- pnpSupportIds: [
35
- "answerMasking", // QTI 3.0 standard (assessment.answerMasking)
36
- "answerEliminator", // QTI 3.0 standard (assessment.answerEliminator)
37
- "strikethrough", // QTI 3.0 standard (assessment.strikethrough)
38
- ],
39
43
  /**
40
44
  * Pass 2: Answer eliminator is relevant only for choice-based questions
41
45
  */
@@ -58,8 +62,8 @@ export const answerEliminatorToolRegistration = {
58
62
  const componentOverrides = toolbarContext.componentOverrides ?? {};
59
63
  const overlay = resolveOverlayElement(toolbarContext, visibility.fullToolId, () => createToolElement(this.toolId, context, toolbarContext, componentOverrides));
60
64
  overlay.setAttribute("tool-id", visibility.fullToolId);
61
- overlay.setAttribute("strategy", "strikethrough");
62
65
  overlay.setAttribute("button-alignment", "inline");
66
+ overlay.setAttribute("strategy", normalizeEliminationStrategy(toolbarContext.toolkitCoordinator?.getToolConfig(this.toolId)?.strategy));
63
67
  const button = {
64
68
  toolId: this.toolId,
65
69
  label: this.name,
@@ -80,17 +84,8 @@ export const answerEliminatorToolRegistration = {
80
84
  overlay,
81
85
  isActive: visibility.isActive,
82
86
  });
83
- if (toolbarContext.toolCoordinator) {
84
- overlay.coordinator = toolbarContext.toolCoordinator;
85
- }
86
87
  overlay.scopeElement = toolbarContext.getScopeElement?.() || null;
87
- if (toolbarContext.elementToolStateStore) {
88
- overlay.elementToolStateStore = toolbarContext.elementToolStateStore;
89
- }
90
- const globalElementId = toolbarContext.getGlobalElementId?.();
91
- if (globalElementId) {
92
- overlay.globalElementId = globalElementId;
93
- }
88
+ overlay.elementStateKeys = resolveElementStateKeys(context, toolbarContext);
94
89
  },
95
90
  subscribeActive: visibility.subscribeActive,
96
91
  };
@@ -2,12 +2,8 @@
2
2
  * Measurement Tools Registrations
3
3
  *
4
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
5
  */
10
- import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
6
+ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
11
7
  /**
12
8
  * Ruler tool registration
13
9
  *
@@ -2,12 +2,8 @@
2
2
  * Measurement Tools Registrations
3
3
  *
4
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
5
  */
10
- import { hasMathContent } from "@pie-players/pie-assessment-toolkit/tools/internal";
6
+ import { hasMathContent } from "@pie-players/pie-assessment-toolkit/tools/registration";
11
7
  import { renderOverlayToolbar } from "./overlay-toolbar-render.js";
12
8
  /**
13
9
  * Ruler tool registration
@@ -24,11 +20,6 @@ export const rulerToolRegistration = {
24
20
  icon: "ruler",
25
21
  // Ruler typically appears at section/item/element level
26
22
  supportedLevels: ["section", "item", "element"],
27
- // PNP support IDs
28
- // Maps to QTI 3.0 standard feature: ruler
29
- pnpSupportIds: [
30
- "ruler", // QTI 3.0 standard (assessment.ruler)
31
- ],
32
23
  /**
33
24
  * Pass 2: Ruler is relevant when math content is present
34
25
  */
@@ -38,7 +29,6 @@ export const rulerToolRegistration = {
38
29
  renderToolbar(context, toolbarContext) {
39
30
  return renderOverlayToolbar(this, context, toolbarContext, {
40
31
  surface: "frameless",
41
- handsOverCoordinator: true,
42
32
  });
43
33
  },
44
34
  };
@@ -57,11 +47,6 @@ export const protractorToolRegistration = {
57
47
  icon: "protractor",
58
48
  // Protractor typically appears at section/item/element level
59
49
  supportedLevels: ["section", "item", "element"],
60
- // PNP support IDs
61
- // Maps to QTI 3.0 standard feature: protractor
62
- pnpSupportIds: [
63
- "protractor", // QTI 3.0 standard (assessment.protractor)
64
- ],
65
50
  /**
66
51
  * Pass 2: Protractor is relevant when math content is present
67
52
  */
@@ -71,7 +56,6 @@ export const protractorToolRegistration = {
71
56
  renderToolbar(context, toolbarContext) {
72
57
  return renderOverlayToolbar(this, context, toolbarContext, {
73
58
  surface: "frameless",
74
- handsOverCoordinator: true,
75
59
  });
76
60
  },
77
61
  };
@@ -12,7 +12,9 @@
12
12
  * A Svelte custom element tears its component down once it leaves the document,
13
13
  * so a cached element found disconnected is dropped and recreated.
14
14
  */
15
- import type { ToolbarContext } from "@pie-players/pie-assessment-toolkit/tools/internal";
15
+ import type { ToolbarContext } from "@pie-players/pie-assessment-toolkit/tools/registration";
16
+ /** The property the toolbar calls as it unmounts a tool element. */
17
+ export declare const TOOL_ELEMENT_UNMOUNT_CALLBACK_PROP = "__pieToolElementUnmount";
16
18
  /**
17
19
  * The element cached for `fullToolId` under this toolbar's coordinator, or the
18
20
  * one `create` returns, which is then cached. Without a coordinator there is no
@@ -12,7 +12,8 @@
12
12
  * A Svelte custom element tears its component down once it leaves the document,
13
13
  * so a cached element found disconnected is dropped and recreated.
14
14
  */
15
- import { TOOL_ELEMENT_UNMOUNT_CALLBACK_PROP } from "./tts.js";
15
+ /** The property the toolbar calls as it unmounts a tool element. */
16
+ export const TOOL_ELEMENT_UNMOUNT_CALLBACK_PROP = "__pieToolElementUnmount";
16
17
  const overlayElements = new WeakMap();
17
18
  /**
18
19
  * The element cached for `fullToolId` under this toolbar's coordinator, or the
@@ -3,9 +3,8 @@
3
3
  * overlay behind one toolbar button.
4
4
  *
5
5
  * Seven registrations had this inline. What actually varies between them is the
6
- * three options below and nothing else: whether the overlay paints its own chrome
7
- * or takes a draggable window, that window's size, and whether the overlay needs
8
- * the coordinator re-handed on each sync. Everything else — the visibility
6
+ * two options below and nothing else: whether the overlay paints its own chrome
7
+ * or takes a draggable window, and that window's size. Everything else — the visibility
9
8
  * binding, the button, the component-override lookup, the `tool-id` attribute, the
10
9
  * sync — was identical, which is why one rule landing in three spellings was
11
10
  * possible: the shell title was `resolveToolRegistrationName` in two files,
@@ -16,7 +15,7 @@
16
15
  * different prefix — the dictionary variants, which compose several capabilities
17
16
  * off one element — keeps its own renderer.
18
17
  */
19
- import { type ToolContext, type ToolRegistration, type ToolToolbarRenderResult, type ToolbarContext } from "@pie-players/pie-assessment-toolkit/tools/internal";
18
+ import { type ToolContext, type ToolRegistration, type ToolToolbarRenderResult, type ToolbarContext } from "@pie-players/pie-assessment-toolkit/tools/registration";
20
19
  /** A window's geometry. Absent for overlays that paint their own chrome. */
21
20
  export interface OverlayToolShell {
22
21
  resizable: boolean;
@@ -33,11 +32,5 @@ export interface RenderOverlayToolbarOptions {
33
32
  surface?: "frameless";
34
33
  /** Present when the capability opens in a draggable, closeable window. */
35
34
  shell?: OverlayToolShell;
36
- /**
37
- * Re-hand the toolkit coordinator on every sync. Overlays that take part in
38
- * stacking or visibility restore need it; the two that only render their own
39
- * model do not, and giving them a property they ignore is not free to assume.
40
- */
41
- handsOverCoordinator?: boolean;
42
35
  }
43
36
  export declare function renderOverlayToolbar(registration: ToolRegistration, context: ToolContext, toolbarContext: ToolbarContext, options?: RenderOverlayToolbarOptions): ToolToolbarRenderResult;
@@ -3,9 +3,8 @@
3
3
  * overlay behind one toolbar button.
4
4
  *
5
5
  * Seven registrations had this inline. What actually varies between them is the
6
- * three options below and nothing else: whether the overlay paints its own chrome
7
- * or takes a draggable window, that window's size, and whether the overlay needs
8
- * the coordinator re-handed on each sync. Everything else — the visibility
6
+ * two options below and nothing else: whether the overlay paints its own chrome
7
+ * or takes a draggable window, and that window's size. Everything else — the visibility
9
8
  * binding, the button, the component-override lookup, the `tool-id` attribute, the
10
9
  * sync — was identical, which is why one rule landing in three spellings was
11
10
  * possible: the shell title was `resolveToolRegistrationName` in two files,
@@ -16,7 +15,7 @@
16
15
  * different prefix — the dictionary variants, which compose several capabilities
17
16
  * off one element — keeps its own renderer.
18
17
  */
19
- import { applyOverlaySurface, createScopedVisibilityBinding, createToolElement, resolveToolRegistrationName, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/internal";
18
+ import { applyOverlaySurface, createScopedVisibilityBinding, createToolElement, resolveToolRegistrationName, syncButtonAndOverlayVisibility, } from "@pie-players/pie-assessment-toolkit/tools/registration";
20
19
  import { resolveOverlayElement } from "./overlay-element-cache.js";
21
20
  export function renderOverlayToolbar(registration, context, toolbarContext, options = {}) {
22
21
  const { toolId } = registration;
@@ -74,9 +73,6 @@ export function renderOverlayToolbar(registration, context, toolbarContext, opti
74
73
  overlay,
75
74
  isActive: visibility.isActive,
76
75
  });
77
- if (options.handsOverCoordinator && toolbarContext.toolkitCoordinator) {
78
- overlay.toolkitCoordinator = toolbarContext.toolkitCoordinator;
79
- }
80
76
  },
81
77
  subscribeActive: visibility.subscribeActive,
82
78
  };
@@ -12,7 +12,7 @@
12
12
  * cannot originate one at all. Every tool named here also opens from the toolbar and
13
13
  * carries its own term field.
14
14
  */
15
- import type { ToolSelectionAction, ToolSurfaceServices } from "@pie-players/pie-assessment-toolkit/tools/internal";
15
+ import type { ToolSelectionAction, ToolSurfaceServices } from "@pie-players/pie-assessment-toolkit/tools/registration";
16
16
  /**
17
17
  * Actions for the gateway to render, given the services it was handed.
18
18
  *
@@ -12,7 +12,7 @@
12
12
  * cannot originate one at all. Every tool named here also opens from the toolbar and
13
13
  * carries its own term field.
14
14
  */
15
- import { resolveFallbackToolIcon } from "@pie-players/pie-assessment-toolkit/tools/internal";
15
+ import { resolveFallbackToolIcon } from "@pie-players/pie-assessment-toolkit/tools/registration";
16
16
  function asRequestCapable(coordinator) {
17
17
  const candidate = coordinator;
18
18
  if (typeof candidate?.canRequestTool !== "function")
@@ -4,12 +4,8 @@
4
4
  * Registers tools for specific subject areas:
5
5
  * - Graph (coordinate plane)
6
6
  * - Periodic Table (chemistry reference)
7
- *
8
- * Maps to QTI 3.0 standard access features:
9
- * - graph (assessment tool)
10
- * - periodicTable (assessment tool)
11
7
  */
12
- import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
8
+ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
13
9
  /**
14
10
  * Graph tool registration
15
11
  *
@@ -4,12 +4,8 @@
4
4
  * Registers tools for specific subject areas:
5
5
  * - Graph (coordinate plane)
6
6
  * - Periodic Table (chemistry reference)
7
- *
8
- * Maps to QTI 3.0 standard access features:
9
- * - graph (assessment tool)
10
- * - periodicTable (assessment tool)
11
7
  */
12
- import { hasMathContent, hasScienceContent, } from "@pie-players/pie-assessment-toolkit/tools/internal";
8
+ import { hasMathContent, hasScienceContent, } from "@pie-players/pie-assessment-toolkit/tools/registration";
13
9
  import { renderOverlayToolbar } from "./overlay-toolbar-render.js";
14
10
  /**
15
11
  * Graph tool registration
@@ -27,11 +23,6 @@ export const graphToolRegistration = {
27
23
  // A floating tool, placed on a section toolbar or on an item toolbar where
28
24
  // the toolkit runs without a section.
29
25
  supportedLevels: ["section", "item"],
30
- // `graphingCalculator` grants the calculator, whose graphing type a host
31
- // selects through render params; the coordinate plane is not that tool.
32
- pnpSupportIds: [
33
- "graph", // QTI 3.0 standard (assessment.graph)
34
- ],
35
26
  /**
36
27
  * Pass 2: Graph is relevant when math content is present
37
28
  */
@@ -66,11 +57,6 @@ export const periodicTableToolRegistration = {
66
57
  // A floating tool, placed on a section toolbar or on an item toolbar where
67
58
  // the toolkit runs without a section.
68
59
  supportedLevels: ["section", "item"],
69
- // PNP support IDs
70
- // Maps to QTI 3.0 standard feature: periodicTable
71
- pnpSupportIds: [
72
- "periodicTable", // QTI 3.0 standard (assessment.periodicTable)
73
- ],
74
60
  /**
75
61
  * Pass 2: Periodic table is relevant when science content is present
76
62
  */
@@ -2,13 +2,8 @@
2
2
  * Text-to-Speech (TTS) Tool Registration
3
3
  *
4
4
  * Registers the TTS tool for reading content aloud.
5
- *
6
- * Maps to QTI 3.0 standard access features:
7
- * - textToSpeech (auditory support)
8
- * - readAloud (auditory support)
9
5
  */
10
- import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/internal";
11
- export declare const TOOL_ELEMENT_UNMOUNT_CALLBACK_PROP = "__pieToolElementUnmount";
6
+ import type { ToolRegistration } from "@pie-players/pie-assessment-toolkit/tools/registration";
12
7
  export declare const TOOL_ACTIVE_CHANGE_EVENT = "pie-tool-active-change";
13
8
  /**
14
9
  * Text-to-Speech tool registration