@pie-players/pie-assessment-toolkit 0.3.53 → 0.3.55
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 +12 -5
- package/dist/components/ItemToolBar.custom-element.js +97 -55
- package/dist/components/PieAssessmentToolkit.custom-element.js +58 -52
- package/dist/components/SectionToolBar.custom-element.js +97 -55
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/ToolRegistry.d.ts +11 -0
- package/dist/services/ToolRegistry.js.map +1 -1
- package/dist/services/tts-runtime-config.d.ts +8 -1
- package/dist/services/tts-runtime-config.js +87 -18
- package/dist/services/tts-runtime-config.js.map +1 -1
- package/dist/tools/registrations/calculator.js +4 -0
- package/dist/tools/registrations/calculator.js.map +1 -1
- package/dist/tools/registrations/tts.js +7 -3
- package/dist/tools/registrations/tts.js.map +1 -1
- package/package.json +7 -7
|
@@ -10996,7 +10996,11 @@ var calculatorToolRegistration = {
|
|
|
10996
10996
|
minWidth: 380,
|
|
10997
10997
|
minHeight: 420,
|
|
10998
10998
|
initialAlign: "bottom-right",
|
|
10999
|
-
initialMargin: 16
|
|
10999
|
+
initialMargin: 16,
|
|
11000
|
+
content: {
|
|
11001
|
+
overflowY: "auto",
|
|
11002
|
+
preserveMinHeight: true
|
|
11003
|
+
}
|
|
11000
11004
|
}
|
|
11001
11005
|
}
|
|
11002
11006
|
],
|
|
@@ -11054,12 +11058,16 @@ var isServerBackend = (backend) => backend === "polly" || backend === "google" |
|
|
|
11054
11058
|
var withDefault = (value, fallback2) => value === undefined ? fallback2 : value;
|
|
11055
11059
|
var normalizeTTSLayoutMode = (value, fallback2 = "left-aligned") => typeof value === "string" && VALID_TTS_LAYOUT_MODES.has(value) ? value : fallback2;
|
|
11056
11060
|
var DEFAULT_TTS_SPEED_OPTIONS = Object.freeze([0.8, 1.25]);
|
|
11057
|
-
var
|
|
11061
|
+
var DEFAULT_TTS_SPEED_CONTROL_OPTIONS = Object.freeze([
|
|
11062
|
+
{ rate: 0.8, label: "Slow", ariaLabel: "Slow speed" },
|
|
11063
|
+
{ rate: 1, label: "Normal", ariaLabel: "Normal speed", default: true },
|
|
11064
|
+
{ rate: 1.25, label: "Fast", ariaLabel: "Fast speed" }
|
|
11065
|
+
]);
|
|
11066
|
+
var normalizeControlSpeedRate = (entry) => {
|
|
11058
11067
|
if (typeof entry !== "number" || !Number.isFinite(entry) || entry <= 0) {
|
|
11059
11068
|
return;
|
|
11060
11069
|
}
|
|
11061
|
-
|
|
11062
|
-
return rounded === 1 ? undefined : rounded;
|
|
11070
|
+
return Math.round(entry * 100) / 100;
|
|
11063
11071
|
};
|
|
11064
11072
|
var trimOptionalText = (value) => {
|
|
11065
11073
|
if (typeof value !== "string")
|
|
@@ -11068,7 +11076,7 @@ var trimOptionalText = (value) => {
|
|
|
11068
11076
|
return trimmed.length ? trimmed : undefined;
|
|
11069
11077
|
};
|
|
11070
11078
|
var formatSpeedLabel = (rate) => `${rate}x`;
|
|
11071
|
-
var formatSpeedAriaLabel = (label, usedDefaultLabel) => usedDefaultLabel ? `Speed ${label}` : `${label} speed`;
|
|
11079
|
+
var formatSpeedAriaLabel = (label, usedDefaultLabel) => label.toLowerCase() === "normal" ? "Normal speed" : usedDefaultLabel ? `Speed ${label}` : `${label} speed`;
|
|
11072
11080
|
var normalizeSpeedAriaLabel = (label, ariaLabel, usedDefaultLabel) => {
|
|
11073
11081
|
if (!ariaLabel)
|
|
11074
11082
|
return formatSpeedAriaLabel(label, usedDefaultLabel);
|
|
@@ -11076,59 +11084,55 @@ var normalizeSpeedAriaLabel = (label, ariaLabel, usedDefaultLabel) => {
|
|
|
11076
11084
|
return ariaLabel;
|
|
11077
11085
|
return `${label} ${ariaLabel}`;
|
|
11078
11086
|
};
|
|
11079
|
-
var
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
11083
|
-
return;
|
|
11084
|
-
const record = entry;
|
|
11085
|
-
const rate = normalizeSpeedRate(record.rate);
|
|
11086
|
-
if (rate === undefined)
|
|
11087
|
-
return;
|
|
11088
|
-
const label = trimOptionalText(record.label);
|
|
11089
|
-
const ariaLabel = trimOptionalText(record.ariaLabel);
|
|
11090
|
-
return {
|
|
11091
|
-
rate,
|
|
11092
|
-
...label ? { label } : {},
|
|
11093
|
-
...ariaLabel ? { ariaLabel } : {}
|
|
11094
|
-
};
|
|
11095
|
-
};
|
|
11096
|
-
var normalizeTTSSpeedOptionConfigs = (value) => {
|
|
11097
|
-
if (!Array.isArray(value))
|
|
11098
|
-
return [...DEFAULT_TTS_SPEED_OPTIONS];
|
|
11099
|
-
if (value.length === 0)
|
|
11087
|
+
var normalizeTTSSpeedControlOptions = (value) => {
|
|
11088
|
+
const input = Array.isArray(value) ? value : [...DEFAULT_TTS_SPEED_CONTROL_OPTIONS];
|
|
11089
|
+
if (input.length === 0)
|
|
11100
11090
|
return [];
|
|
11101
11091
|
const dedupedRates = new Set;
|
|
11102
11092
|
const normalized = [];
|
|
11103
|
-
for (const entry of
|
|
11104
|
-
const
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
const rate = typeof option === "number" ? option : option.rate;
|
|
11108
|
-
if (dedupedRates.has(rate))
|
|
11093
|
+
for (const entry of input) {
|
|
11094
|
+
const record = toRecord(entry);
|
|
11095
|
+
const rate = typeof entry === "number" ? normalizeControlSpeedRate(entry) : normalizeControlSpeedRate(record.rate);
|
|
11096
|
+
if (rate === undefined || dedupedRates.has(rate))
|
|
11109
11097
|
continue;
|
|
11110
11098
|
dedupedRates.add(rate);
|
|
11111
|
-
|
|
11099
|
+
const defaultLabel = rate === 1 ? "Normal" : typeof entry === "number" ? formatSpeedLabel(rate) : formatSpeedLabel(rate);
|
|
11100
|
+
const label = typeof entry === "number" ? defaultLabel : trimOptionalText(record.label) || defaultLabel;
|
|
11101
|
+
const ariaLabel = typeof entry === "number" ? rate === 1 ? "Normal speed" : formatSpeedAriaLabel(label, true) : normalizeSpeedAriaLabel(label, trimOptionalText(record.ariaLabel), label === defaultLabel);
|
|
11102
|
+
normalized.push({
|
|
11103
|
+
rate,
|
|
11104
|
+
label,
|
|
11105
|
+
ariaLabel,
|
|
11106
|
+
isDefault: false,
|
|
11107
|
+
requestedDefault: record.default === true || record.isDefault === true
|
|
11108
|
+
});
|
|
11112
11109
|
}
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
if (
|
|
11117
|
-
const
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
|
|
11110
|
+
if (!normalized.length) {
|
|
11111
|
+
return normalizeTTSSpeedControlOptions(DEFAULT_TTS_SPEED_CONTROL_OPTIONS);
|
|
11112
|
+
}
|
|
11113
|
+
if (!dedupedRates.has(1)) {
|
|
11114
|
+
const normalOption = {
|
|
11115
|
+
rate: 1,
|
|
11116
|
+
label: "Normal",
|
|
11117
|
+
ariaLabel: "Normal speed",
|
|
11118
|
+
isDefault: false,
|
|
11119
|
+
requestedDefault: false
|
|
11122
11120
|
};
|
|
11121
|
+
const firstFasterIndex = normalized.findIndex((option) => option.rate > 1);
|
|
11122
|
+
if (firstFasterIndex >= 0) {
|
|
11123
|
+
normalized.splice(firstFasterIndex, 0, normalOption);
|
|
11124
|
+
} else {
|
|
11125
|
+
normalized.push(normalOption);
|
|
11126
|
+
}
|
|
11123
11127
|
}
|
|
11124
|
-
const
|
|
11125
|
-
const
|
|
11126
|
-
return {
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
|
|
11130
|
-
|
|
11131
|
-
|
|
11128
|
+
const requestedDefaultIndex = normalized.findIndex((option) => option.requestedDefault);
|
|
11129
|
+
const defaultIndex = requestedDefaultIndex >= 0 ? requestedDefaultIndex : normalized.findIndex((option) => option.rate === 1);
|
|
11130
|
+
return normalized.map(({ requestedDefault: _requestedDefault, ...option }, index2) => ({
|
|
11131
|
+
...option,
|
|
11132
|
+
isDefault: index2 === defaultIndex
|
|
11133
|
+
}));
|
|
11134
|
+
};
|
|
11135
|
+
var DEFAULT_TTS_SPEED_CONTROL_RATES = Object.freeze([0.8, 1, 1.25]);
|
|
11132
11136
|
var applyRuntimeDefaults = (config) => {
|
|
11133
11137
|
const withLayoutDefaults = {
|
|
11134
11138
|
...config,
|
|
@@ -11283,7 +11287,7 @@ var ttsToolRegistration = {
|
|
|
11283
11287
|
settings.layoutMode = normalizeTTSLayoutMode(settings.layoutMode);
|
|
11284
11288
|
}
|
|
11285
11289
|
if (settings && "speedOptions" in settings) {
|
|
11286
|
-
settings.speedOptions =
|
|
11290
|
+
settings.speedOptions = normalizeTTSSpeedControlOptions(settings.speedOptions);
|
|
11287
11291
|
}
|
|
11288
11292
|
const normalizedConfig = {
|
|
11289
11293
|
...config
|
|
@@ -11292,7 +11296,7 @@ var ttsToolRegistration = {
|
|
|
11292
11296
|
normalizedConfig.layoutMode = normalizeTTSLayoutMode(normalizedConfig.layoutMode);
|
|
11293
11297
|
}
|
|
11294
11298
|
if ("speedOptions" in normalizedConfig) {
|
|
11295
|
-
normalizedConfig.speedOptions =
|
|
11299
|
+
normalizedConfig.speedOptions = normalizeTTSSpeedControlOptions(normalizedConfig.speedOptions);
|
|
11296
11300
|
}
|
|
11297
11301
|
if (settings) {
|
|
11298
11302
|
normalizedConfig.settings = settings;
|
|
@@ -11345,6 +11349,7 @@ var ttsToolRegistration = {
|
|
|
11345
11349
|
element2.setAttribute("size", resolveControlSize());
|
|
11346
11350
|
element2.setAttribute("layout-mode", resolveLayoutMode());
|
|
11347
11351
|
element2.speedOptions = resolveElementSpeedOptions();
|
|
11352
|
+
element2.showSingleSpeedOption = resolveRuntimeSettings().showSingleSpeedOption === true;
|
|
11348
11353
|
return element2;
|
|
11349
11354
|
};
|
|
11350
11355
|
const hostLayout = resolveHostLayout();
|
|
@@ -11382,6 +11387,7 @@ var ttsToolRegistration = {
|
|
|
11382
11387
|
element2.setAttribute("size", resolveControlSize());
|
|
11383
11388
|
element2.setAttribute("layout-mode", resolveLayoutMode());
|
|
11384
11389
|
element2.speedOptions = resolveElementSpeedOptions();
|
|
11390
|
+
element2.showSingleSpeedOption = resolveRuntimeSettings().showSingleSpeedOption === true;
|
|
11385
11391
|
}
|
|
11386
11392
|
};
|
|
11387
11393
|
}
|
|
@@ -13576,6 +13582,38 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
13576
13582
|
shellEl.style.overflowY = "visible";
|
|
13577
13583
|
}
|
|
13578
13584
|
};
|
|
13585
|
+
const getContentOverflowY = () => currentArgs.mounted.entry.shell?.content?.overflowY === "auto" ? "auto" : "hidden";
|
|
13586
|
+
const getHeaderHeight = () => {
|
|
13587
|
+
if (!headerEl)
|
|
13588
|
+
return 0;
|
|
13589
|
+
const rectHeight = headerEl.getBoundingClientRect().height;
|
|
13590
|
+
if (rectHeight > 0)
|
|
13591
|
+
return rectHeight;
|
|
13592
|
+
return headerEl.offsetHeight || 0;
|
|
13593
|
+
};
|
|
13594
|
+
const applyContentLayout = () => {
|
|
13595
|
+
if (!contentEl)
|
|
13596
|
+
return;
|
|
13597
|
+
const shellConfig = currentArgs.mounted.entry.shell;
|
|
13598
|
+
contentEl.style.overflowX = "hidden";
|
|
13599
|
+
contentEl.style.overflowY = getContentOverflowY();
|
|
13600
|
+
if (!mountedContentElement)
|
|
13601
|
+
return;
|
|
13602
|
+
if (shellConfig?.content?.preserveMinHeight === true) {
|
|
13603
|
+
const headerHeight = getHeaderHeight();
|
|
13604
|
+
const shellMinHeight = shellConfig.minHeight ?? 240;
|
|
13605
|
+
const contentMinHeight = Math.max(0, shellMinHeight - headerHeight);
|
|
13606
|
+
const availableHeight = Math.max(0, height - headerHeight);
|
|
13607
|
+
const elementHeight = Math.max(availableHeight, contentMinHeight);
|
|
13608
|
+
mountedContentElement.style.height = `${elementHeight}px`;
|
|
13609
|
+
mountedContentElement.style.minHeight = "0";
|
|
13610
|
+
mountedContentElement.style.flex = `0 0 ${elementHeight}px`;
|
|
13611
|
+
return;
|
|
13612
|
+
}
|
|
13613
|
+
mountedContentElement.style.height = "100%";
|
|
13614
|
+
mountedContentElement.style.minHeight = "0";
|
|
13615
|
+
mountedContentElement.style.flex = "1 1 auto";
|
|
13616
|
+
};
|
|
13579
13617
|
const applyPositionAndSize = () => {
|
|
13580
13618
|
const { minWidth, minHeight, maxWidth, maxHeight } = getShellBounds();
|
|
13581
13619
|
const effectiveMinWidth = Math.min(minWidth, window.innerWidth);
|
|
@@ -13586,6 +13624,7 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
13586
13624
|
y2 = clamp(y2, 0, Math.max(0, window.innerHeight - height));
|
|
13587
13625
|
applyShellStyle();
|
|
13588
13626
|
applyContentMinWidth();
|
|
13627
|
+
applyContentLayout();
|
|
13589
13628
|
notifyHostedResize();
|
|
13590
13629
|
};
|
|
13591
13630
|
const moveBy = (dx, dy) => {
|
|
@@ -13686,7 +13725,6 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
13686
13725
|
element2.style.height = "100%";
|
|
13687
13726
|
element2.style.flex = "1 1 auto";
|
|
13688
13727
|
element2.style.minHeight = "0";
|
|
13689
|
-
applyContentMinWidth();
|
|
13690
13728
|
if (mountedContentElement && mountedContentElement !== element2) {
|
|
13691
13729
|
if (mountedContentElement.parentNode === contentEl) {
|
|
13692
13730
|
invokeElementUnmount(mountedContentElement);
|
|
@@ -13701,6 +13739,8 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
13701
13739
|
contentEl.appendChild(element2);
|
|
13702
13740
|
}
|
|
13703
13741
|
mountedContentElement = element2;
|
|
13742
|
+
applyContentMinWidth();
|
|
13743
|
+
applyContentLayout();
|
|
13704
13744
|
notifyHostedMount(element2);
|
|
13705
13745
|
};
|
|
13706
13746
|
const bringToFront = () => {
|
|
@@ -13970,6 +14010,7 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
13970
14010
|
}
|
|
13971
14011
|
applyShellStyle();
|
|
13972
14012
|
applyContentMinWidth();
|
|
14013
|
+
applyContentLayout();
|
|
13973
14014
|
notifyHostedResize();
|
|
13974
14015
|
}
|
|
13975
14016
|
};
|
|
@@ -14182,7 +14223,8 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
14182
14223
|
contentEl.style.width = "100%";
|
|
14183
14224
|
contentEl.style.flex = "1 1 auto";
|
|
14184
14225
|
contentEl.style.minHeight = "0";
|
|
14185
|
-
contentEl.style.
|
|
14226
|
+
contentEl.style.overflowX = "hidden";
|
|
14227
|
+
contentEl.style.overflowY = getContentOverflowY();
|
|
14186
14228
|
contentEl.style.borderRadius = "0 0 12px 12px";
|
|
14187
14229
|
if (isCalculatorShell) {
|
|
14188
14230
|
const makeFocusGuard = (label) => {
|
|
@@ -14300,8 +14342,8 @@ function ItemToolBar($$anchor, $$props) {
|
|
|
14300
14342
|
titleEl.textContent = currentArgs.mounted.entry.shell?.title || currentArgs.mounted.toolId;
|
|
14301
14343
|
const closeButtonOpenDisplay = currentArgs.mounted.toolId === "calculator" ? "inline-block" : "inline-flex";
|
|
14302
14344
|
closeButtonEl.style.display = currentArgs.mounted.entry.shell?.closeable === false ? "none" : closeButtonOpenDisplay;
|
|
14303
|
-
mountContent();
|
|
14304
14345
|
applyShellStyle();
|
|
14346
|
+
mountContent();
|
|
14305
14347
|
notifyHostedResize();
|
|
14306
14348
|
if (!previousActive && currentArgs.active) {
|
|
14307
14349
|
installFocusTrap();
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export type { SerializedRange } from "./services/RangeSerializer.js";
|
|
|
23
23
|
export { RangeSerializer } from "./services/RangeSerializer.js";
|
|
24
24
|
export type { I18nConfig, PluralTranslation, TranslationBundle, } from "./services/I18nService.js";
|
|
25
25
|
export { I18nService } from "./services/I18nService.js";
|
|
26
|
-
export type { ResolvedToolContext, ToolbarContext, ToolContextResolver, ToolContextResolverContext, ToolContextResolverMap, ToolContextResolverResult, ToolModuleLoader, ToolToolbarButtonDefinition, ToolToolbarRenderResult, ToolRegistration, } from "./services/ToolRegistry.js";
|
|
26
|
+
export type { ResolvedToolContext, ToolbarContext, ToolContextResolver, ToolContextResolverContext, ToolContextResolverMap, ToolContextResolverResult, ToolModuleLoader, ToolToolbarButtonDefinition, ToolToolbarRenderResult, ToolWindowShellAction, ToolWindowShellAlign, ToolWindowShellConfig, ToolWindowShellContentConfig, ToolRegistration, } from "./services/ToolRegistry.js";
|
|
27
27
|
export { ToolRegistry } from "./services/ToolRegistry.js";
|
|
28
28
|
export type { AssessmentToolContext, BaseToolContext, ElementToolContext, ItemToolContext, PassageToolContext, RubricToolContext, SectionToolContext, ToolContext, ToolLevel, } from "./services/tool-context.js";
|
|
29
29
|
export { extractTextContent, hasChoiceInteraction, hasMathContent, hasReadableText, isAssessmentContext, isElementContext, isItemContext, isPassageContext, isRubricContext, isSectionContext, } from "./services/tool-context.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PIE Assessment Toolkit\n *\n * Independent, composable services for coordinating tools, accommodations,\n * and item players in assessment applications.\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Core Infrastructure\n// ============================================================================\n\nexport type {\n\tAssessmentToolkitHostRuntimeContext,\n\tAssessmentToolkitRegionScopeContext,\n\tAssessmentToolkitRuntimeContext,\n\tAssessmentToolkitShellContext,\n\tItemPlayerConfig,\n\tItemPlayerType,\n\tShellContextKind,\n} from \"./context/assessment-toolkit-context.js\";\nexport type {\n\tTTSHighlightContext,\n\tTTSHighlightTargetResolver,\n\tTTSHighlightTargetResolverProvider,\n\tTTSHighlightTargetResolverRuntime,\n} from \"./services/tts/highlight-target-resolver.js\";\nexport {\n\tassessmentToolkitHostRuntimeContext,\n\tassessmentToolkitRegionScopeContext,\n\tassessmentToolkitRuntimeContext,\n\tassessmentToolkitShellContext,\n} from \"./context/assessment-toolkit-context.js\";\nexport {\n\tconnectAssessmentToolkitHostRuntimeContext,\n\tconnectAssessmentToolkitRegionScopeContext,\n\tconnectAssessmentToolkitRuntimeContext,\n\tconnectAssessmentToolkitShellContext,\n} from \"./context/runtime-context-consumer.js\";\nexport {\n\tPIE_INTERNAL_CONTENT_LOADED_EVENT,\n\tPIE_INTERNAL_ITEM_SESSION_CHANGED_EVENT,\n\tPIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT,\n\tPIE_ITEM_SESSION_CHANGED_EVENT,\n\tPIE_REGISTER_EVENT,\n\tPIE_UNREGISTER_EVENT,\n\ttype InternalContentLoadedDetail,\n\ttype InternalItemSessionChangedDetail,\n\ttype InternalItemPlayerErrorDetail,\n\ttype ItemSessionChangedDetail,\n\ttype RuntimeRegistrationDetail,\n\ttype RuntimeRegistrationKind,\n} from \"./runtime/registration-events.js\";\nexport {\n\tconnectToolRegionScopeContext,\n\tconnectToolRuntimeContext,\n\tconnectToolShellContext,\n\tcreateCrossBoundaryEvent,\n\tdispatchCrossBoundaryEvent,\n\tisContextValueDefined,\n} from \"./runtime/tool-host-contract.js\";\n\n// ============================================================================\n// Service Interfaces\n// ============================================================================\n\nexport type {\n\tAccessibilityCatalogResolverApi,\n\tElementToolStateStoreApi,\n\tHighlightCoordinatorApi,\n\tI18nServiceApi,\n\tThemeProviderApi,\n\tToolCoordinatorApi,\n\tToolkitCoordinatorApi,\n\tTtsServiceApi,\n\tToolState,\n} from \"./services/interfaces.js\";\n\n// ============================================================================\n// Toolkit Services\n// ============================================================================\n\n// Accessibility Catalog Resolver (QTI 3.0 Accessibility Catalogs)\nexport type {\n\tCatalogLookupContext,\n\tCatalogLookupOptions,\n\tCatalogOwnerContext,\n\tCatalogOwnerKind,\n\tCatalogStatistics,\n\tCatalogType,\n\tResolvedCatalog,\n} from \"./services/AccessibilityCatalogResolver.js\";\nexport { AccessibilityCatalogResolver } from \"./services/AccessibilityCatalogResolver.js\";\n// Context Variable Store (QTI 3.0 Context Declarations)\nexport { ContextVariableStore } from \"./services/ContextVariableStore.js\";\n// Element Tool State Store (Element-level ephemeral tool state)\nexport { ElementToolStateStore } from \"./services/ElementToolStateStore.js\";\n// Highlight Coordinator\nexport type { Annotation } from \"./services/HighlightCoordinator.js\";\nexport {\n\tHighlightColor,\n\tHighlightCoordinator,\n\tHighlightType,\n} from \"./services/HighlightCoordinator.js\";\n// Range Serializer (for annotation persistence)\nexport type { SerializedRange } from \"./services/RangeSerializer.js\";\nexport { RangeSerializer } from \"./services/RangeSerializer.js\";\n// I18n Service\nexport type {\n\tI18nConfig,\n\tPluralTranslation,\n\tTranslationBundle,\n} from \"./services/I18nService.js\";\nexport { I18nService } from \"./services/I18nService.js\";\n// Tool Registry (Registry-based tool system)\nexport type {\n\tResolvedToolContext,\n\tToolbarContext,\n\tToolContextResolver,\n\tToolContextResolverContext,\n\tToolContextResolverMap,\n\tToolContextResolverResult,\n\tToolModuleLoader,\n\tToolToolbarButtonDefinition,\n\tToolToolbarRenderResult,\n\tToolRegistration,\n} from \"./services/ToolRegistry.js\";\nexport { ToolRegistry } from \"./services/ToolRegistry.js\";\nexport type {\n\tAssessmentToolContext,\n\tBaseToolContext,\n\tElementToolContext,\n\tItemToolContext,\n\tPassageToolContext,\n\tRubricToolContext,\n\tSectionToolContext,\n\tToolContext,\n\tToolLevel,\n} from \"./services/tool-context.js\";\nexport {\n\textractTextContent,\n\thasChoiceInteraction,\n\thasMathContent,\n\thasReadableText,\n\tisAssessmentContext,\n\tisElementContext,\n\tisItemContext,\n\tisPassageContext,\n\tisRubricContext,\n\tisSectionContext,\n} from \"./services/tool-context.js\";\nexport {\n\tDEFAULT_TOOL_PLACEMENT,\n\tDEFAULT_TOOL_ORDER,\n\tcreatePackagedToolRegistry,\n\tPACKAGED_TOOL_PLACEMENT,\n\tregisterPackagedTools,\n\tSECTION_PLAYER_PREFERRED_TOOL_PLACEMENT,\n} from \"./services/createDefaultToolRegistry.js\";\nexport type { CreateToolsConfigArgs } from \"./services/create-tools-config.js\";\nexport { createToolsConfig } from \"./services/create-tools-config.js\";\nexport {\n\tDEFAULT_PERSONAL_NEEDS_PROFILE,\n\tcreateDefaultPersonalNeedsProfile,\n} from \"./services/defaultPersonalNeedsProfile.js\";\nexport type {\n\tToolComponentFactory,\n\tToolComponentFactoryMap,\n\tToolComponentOverrides,\n\tToolTagMap,\n} from \"./tools/tool-tag-map.js\";\nexport {\n\tcreateToolElement,\n\tDEFAULT_TOOL_TAG_MAP,\n\tresolveToolTag,\n\ttoToolIdFromTag,\n} from \"./tools/tool-tag-map.js\";\n// QTI 3.0 Standard Access Features\nexport {\n\tALL_STANDARD_ACCESS_FEATURES,\n\tEXAMPLE_PNP_CONFIGURATIONS,\n\tgetFeatureCategory,\n\tgetFeaturesInCategory,\n\tisStandardAccessFeature,\n\tQTI_STANDARD_ACCESS_FEATURES,\n} from \"./services/pnp-standard-features.js\";\n// SSML Extractor (Auto-generates catalogs from embedded SSML)\nexport type { ExtractionResult } from \"./services/SSMLExtractor.js\";\nexport { SSMLExtractor } from \"./services/SSMLExtractor.js\";\n// Theme Provider\nexport type { FontSize, ThemeConfig } from \"./services/ThemeProvider.js\";\nexport { ThemeProvider } from \"./services/ThemeProvider.js\";\n// Tool Coordinator\nexport { ToolCoordinator, ZIndexLayer } from \"./services/ToolCoordinator.js\";\n// Toolkit Coordinator (Centralized service management)\nexport type {\n\tAnswerEliminatorToolConfig,\n\tProviderLifecycleContext,\n\tSectionControllerContext,\n\tSectionControllerEvent,\n\tSectionControllerEventType,\n\tSectionItemEvent,\n\tSectionItemEventType,\n\tSectionControllerFactoryDefaults,\n\tSectionControllerHandle,\n\tSectionControllerKey,\n\tSectionScopedEvent,\n\tSectionScopedEventType,\n\tSectionSessionPersistenceConfig,\n\tSectionItemEventSubscriptionArgs,\n\tSectionScopedEventSubscriptionArgs,\n\tSectionEventSubscriptionArgs,\n\tSectionSessionPersistenceStrategy,\n\tSectionControllerLoadedRenderable,\n\tSectionControllerRuntimeState,\n\tSectionControllerSessionState,\n\tSectionPersistenceFactoryDefaults,\n\tToolConfig,\n\tToolkitCoordinatorConfig,\n\tToolkitCoordinatorHooks,\n\tToolkitErrorContext,\n\tToolkitInitStatus,\n\tToolkitServiceBundle,\n\tToolkitToolsConfig,\n\tTTSToolConfig,\n} from \"./services/ToolkitCoordinator.js\";\nexport { ToolkitCoordinator } from \"./services/ToolkitCoordinator.js\";\nexport type {\n\tCanonicalToolsConfig,\n\tToolPlacementConfig,\n\tToolPlacementLevel,\n\tToolPolicyConfig,\n\tToolProvidersConfig,\n} from \"./services/tools-config-normalizer.js\";\nexport type {\n\tFrameworkErrorKind,\n\tFrameworkErrorModel,\n\tFrameworkErrorSeverity,\n} from \"./services/framework-error.js\";\nexport {\n\tformatFrameworkErrorForConsole,\n\tframeworkErrorFromToolConfigDiagnostics,\n\tframeworkErrorFromUnknown,\n\ttoFrameworkErrorModel,\n} from \"./services/framework-error.js\";\nexport type { FrameworkErrorListener } from \"./services/framework-error-bus.js\";\nexport type {\n\tToolConfigDiagnostic,\n\tToolConfigDiagnosticSeverity,\n\tToolConfigStrictness,\n\tToolConfigValidationOptions,\n\tToolConfigValidationResult,\n} from \"./services/tool-config-validation.js\";\nexport type {\n\tToolbarButtonItem,\n\tToolbarItem,\n\tToolbarItemBase,\n\tToolbarLinkItem,\n} from \"./services/toolbar-items.js\";\nexport {\n\tisExternalIconUrl,\n\tisInlineSvgIcon,\n\tisToolbarLinkItem,\n\tisValidToolbarItemShape,\n} from \"./services/toolbar-items.js\";\nexport {\n\tnormalizeToolsConfig,\n\tnormalizeToolAlias,\n\tnormalizeToolList,\n\tparseToolList,\n} from \"./services/tools-config-normalizer.js\";\nexport {\n\tframeworkErrorFromToolConfigValidation,\n\tnormalizeAndValidateToolsConfig,\n} from \"./services/tool-config-validation.js\";\nexport type {\n\tParsedToolInstanceId,\n\tToolScopeLevel,\n} from \"./services/tool-instance-id.js\";\nexport {\n\tcreateScopedToolId,\n\tparseScopedToolId,\n\ttoOverlayToolId,\n} from \"./services/tool-instance-id.js\";\n// Text-to-Speech Service\nexport type { TTSConfig } from \"./services/TTSService.js\";\nexport { PlaybackState, TTSService } from \"./services/TTSService.js\";\nexport {\n\tPIE_TTS_CONTROL_HANDOFF_EVENT,\n\ttype TTSControlHandoffDetail,\n} from \"./services/tts-control-events.js\";\nexport { BrowserTTSProvider } from \"./services/tts/browser-provider.js\";\nexport type { SREMathSpeechOptions } from \"./services/tts/math-speech.js\";\nexport type {\n\tNormalizedTTSSpeedOption,\n\tTTSHostToolbarLayout,\n\tTTSLayoutMode,\n\tTTSRuntimeSettings,\n\tTTSSpeedOption,\n\tTTSSpeedOptionConfig,\n} from \"./services/tts-runtime-config.js\";\nexport {\n\tDEFAULT_TTS_SPEED_OPTIONS,\n\tformatTTSSpeedOptionsAsText,\n\tnormalizeTTSLayoutMode,\n\tnormalizeTTSSpeedControlOptions,\n\tnormalizeTTSSpeedOptionConfigs,\n\tnormalizeTTSSpeedOptions,\n\tparseTTSSpeedOptionsFromText,\n\tresolveTTSHostToolbarLayout,\n\tresolveTTSLayoutMode,\n\tresolveTTSRuntimeSettings,\n} from \"./services/tts-runtime-config.js\";\n// TTS Provider System\nexport type {\n\tITTSProvider,\n\tITTSProviderImplementation,\n\tTTSSpeechSegment,\n\tTTSFeature,\n\tTTSProviderCapabilities,\n} from \"@pie-players/pie-tts\";\n\n// ============================================================================\n// Item loading (client-resolvable default; optional backend hook)\n// ============================================================================\n\nexport type {\n\tCreateLoadItemOptions,\n\tLoadItem,\n\tLoadItemOptions,\n} from \"./item-loader.js\";\nexport {\n\tcreateFetchItemLoader,\n\tcreateLoadItem,\n\tItemLoadError,\n} from \"./item-loader.js\";\n\n// ============================================================================\n// Attempt Session\n// ============================================================================\n\nexport type {\n\tStorageLike,\n\tTestAttemptItemSession,\n\tTestAttemptSession,\n\tTestAttemptSessionNavigationState,\n\tTestAttemptSessionRealization,\n} from \"./attempt/TestSession.js\";\nexport {\n\tcreateMemoryStorage,\n\tcreateTestAttemptSessionIdentifier,\n\tcreateNewTestAttemptSession,\n\tgetBrowserLocalStorage,\n\tgetOrCreateAnonymousDeviceId,\n\tgetTestAttemptSessionStorageKey,\n\tloadTestAttemptSession,\n\tsaveTestAttemptSession,\n\tsetCurrentPosition,\n\tupsertItemSessionFromPieSessionChange,\n\tupsertVisitedItem,\n} from \"./attempt/TestSession.js\";\nexport type {\n\tAssessmentSession,\n\tAssessmentSectionSessionState,\n\tAssessmentSessionNavigationState,\n\tAssessmentSessionRealization,\n} from \"./attempt/AssessmentSession.js\";\nexport {\n\tcreateNewAssessmentSession,\n\tgetAssessmentSessionStorageKey,\n\tloadAssessmentSession,\n\tsaveAssessmentSession,\n\tsetCurrentSectionPosition,\n\tupsertSectionSession,\n} from \"./attempt/AssessmentSession.js\";\nexport type {\n\tActivitySessionPatchPayload,\n\tMapActivityToTestAttemptSessionArgs,\n\tPieBackendActivityDefinition,\n\tPieBackendActivityItemRef,\n\tPieBackendActivitySession,\n} from \"./attempt/adapters/activity-to-test-attempt-session.js\";\nexport {\n\tbuildActivitySessionItemUpdate,\n\tbuildActivitySessionPatchFromTestAttemptSession,\n\tmapActivityToTestAttemptSession,\n\ttoItemSessionsRecord,\n} from \"./attempt/adapters/activity-to-test-attempt-session.js\";\n\n// Section Player - Use @pie-players/pie-section-player web component\n\n// ============================================================================\n// Shared Components\n// ============================================================================\n\n// ItemToolBar custom element registration helper is exported via package.json exports field\n// Import using: import '@pie-players/pie-assessment-toolkit/components/item-toolbar-element';\n// PieAssessmentToolkit custom element registration helper is exported via package.json exports field\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PIE Assessment Toolkit\n *\n * Independent, composable services for coordinating tools, accommodations,\n * and item players in assessment applications.\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// Core Infrastructure\n// ============================================================================\n\nexport type {\n\tAssessmentToolkitHostRuntimeContext,\n\tAssessmentToolkitRegionScopeContext,\n\tAssessmentToolkitRuntimeContext,\n\tAssessmentToolkitShellContext,\n\tItemPlayerConfig,\n\tItemPlayerType,\n\tShellContextKind,\n} from \"./context/assessment-toolkit-context.js\";\nexport type {\n\tTTSHighlightContext,\n\tTTSHighlightTargetResolver,\n\tTTSHighlightTargetResolverProvider,\n\tTTSHighlightTargetResolverRuntime,\n} from \"./services/tts/highlight-target-resolver.js\";\nexport {\n\tassessmentToolkitHostRuntimeContext,\n\tassessmentToolkitRegionScopeContext,\n\tassessmentToolkitRuntimeContext,\n\tassessmentToolkitShellContext,\n} from \"./context/assessment-toolkit-context.js\";\nexport {\n\tconnectAssessmentToolkitHostRuntimeContext,\n\tconnectAssessmentToolkitRegionScopeContext,\n\tconnectAssessmentToolkitRuntimeContext,\n\tconnectAssessmentToolkitShellContext,\n} from \"./context/runtime-context-consumer.js\";\nexport {\n\tPIE_INTERNAL_CONTENT_LOADED_EVENT,\n\tPIE_INTERNAL_ITEM_SESSION_CHANGED_EVENT,\n\tPIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT,\n\tPIE_ITEM_SESSION_CHANGED_EVENT,\n\tPIE_REGISTER_EVENT,\n\tPIE_UNREGISTER_EVENT,\n\ttype InternalContentLoadedDetail,\n\ttype InternalItemSessionChangedDetail,\n\ttype InternalItemPlayerErrorDetail,\n\ttype ItemSessionChangedDetail,\n\ttype RuntimeRegistrationDetail,\n\ttype RuntimeRegistrationKind,\n} from \"./runtime/registration-events.js\";\nexport {\n\tconnectToolRegionScopeContext,\n\tconnectToolRuntimeContext,\n\tconnectToolShellContext,\n\tcreateCrossBoundaryEvent,\n\tdispatchCrossBoundaryEvent,\n\tisContextValueDefined,\n} from \"./runtime/tool-host-contract.js\";\n\n// ============================================================================\n// Service Interfaces\n// ============================================================================\n\nexport type {\n\tAccessibilityCatalogResolverApi,\n\tElementToolStateStoreApi,\n\tHighlightCoordinatorApi,\n\tI18nServiceApi,\n\tThemeProviderApi,\n\tToolCoordinatorApi,\n\tToolkitCoordinatorApi,\n\tTtsServiceApi,\n\tToolState,\n} from \"./services/interfaces.js\";\n\n// ============================================================================\n// Toolkit Services\n// ============================================================================\n\n// Accessibility Catalog Resolver (QTI 3.0 Accessibility Catalogs)\nexport type {\n\tCatalogLookupContext,\n\tCatalogLookupOptions,\n\tCatalogOwnerContext,\n\tCatalogOwnerKind,\n\tCatalogStatistics,\n\tCatalogType,\n\tResolvedCatalog,\n} from \"./services/AccessibilityCatalogResolver.js\";\nexport { AccessibilityCatalogResolver } from \"./services/AccessibilityCatalogResolver.js\";\n// Context Variable Store (QTI 3.0 Context Declarations)\nexport { ContextVariableStore } from \"./services/ContextVariableStore.js\";\n// Element Tool State Store (Element-level ephemeral tool state)\nexport { ElementToolStateStore } from \"./services/ElementToolStateStore.js\";\n// Highlight Coordinator\nexport type { Annotation } from \"./services/HighlightCoordinator.js\";\nexport {\n\tHighlightColor,\n\tHighlightCoordinator,\n\tHighlightType,\n} from \"./services/HighlightCoordinator.js\";\n// Range Serializer (for annotation persistence)\nexport type { SerializedRange } from \"./services/RangeSerializer.js\";\nexport { RangeSerializer } from \"./services/RangeSerializer.js\";\n// I18n Service\nexport type {\n\tI18nConfig,\n\tPluralTranslation,\n\tTranslationBundle,\n} from \"./services/I18nService.js\";\nexport { I18nService } from \"./services/I18nService.js\";\n// Tool Registry (Registry-based tool system)\nexport type {\n\tResolvedToolContext,\n\tToolbarContext,\n\tToolContextResolver,\n\tToolContextResolverContext,\n\tToolContextResolverMap,\n\tToolContextResolverResult,\n\tToolModuleLoader,\n\tToolToolbarButtonDefinition,\n\tToolToolbarRenderResult,\n\tToolWindowShellAction,\n\tToolWindowShellAlign,\n\tToolWindowShellConfig,\n\tToolWindowShellContentConfig,\n\tToolRegistration,\n} from \"./services/ToolRegistry.js\";\nexport { ToolRegistry } from \"./services/ToolRegistry.js\";\nexport type {\n\tAssessmentToolContext,\n\tBaseToolContext,\n\tElementToolContext,\n\tItemToolContext,\n\tPassageToolContext,\n\tRubricToolContext,\n\tSectionToolContext,\n\tToolContext,\n\tToolLevel,\n} from \"./services/tool-context.js\";\nexport {\n\textractTextContent,\n\thasChoiceInteraction,\n\thasMathContent,\n\thasReadableText,\n\tisAssessmentContext,\n\tisElementContext,\n\tisItemContext,\n\tisPassageContext,\n\tisRubricContext,\n\tisSectionContext,\n} from \"./services/tool-context.js\";\nexport {\n\tDEFAULT_TOOL_PLACEMENT,\n\tDEFAULT_TOOL_ORDER,\n\tcreatePackagedToolRegistry,\n\tPACKAGED_TOOL_PLACEMENT,\n\tregisterPackagedTools,\n\tSECTION_PLAYER_PREFERRED_TOOL_PLACEMENT,\n} from \"./services/createDefaultToolRegistry.js\";\nexport type { CreateToolsConfigArgs } from \"./services/create-tools-config.js\";\nexport { createToolsConfig } from \"./services/create-tools-config.js\";\nexport {\n\tDEFAULT_PERSONAL_NEEDS_PROFILE,\n\tcreateDefaultPersonalNeedsProfile,\n} from \"./services/defaultPersonalNeedsProfile.js\";\nexport type {\n\tToolComponentFactory,\n\tToolComponentFactoryMap,\n\tToolComponentOverrides,\n\tToolTagMap,\n} from \"./tools/tool-tag-map.js\";\nexport {\n\tcreateToolElement,\n\tDEFAULT_TOOL_TAG_MAP,\n\tresolveToolTag,\n\ttoToolIdFromTag,\n} from \"./tools/tool-tag-map.js\";\n// QTI 3.0 Standard Access Features\nexport {\n\tALL_STANDARD_ACCESS_FEATURES,\n\tEXAMPLE_PNP_CONFIGURATIONS,\n\tgetFeatureCategory,\n\tgetFeaturesInCategory,\n\tisStandardAccessFeature,\n\tQTI_STANDARD_ACCESS_FEATURES,\n} from \"./services/pnp-standard-features.js\";\n// SSML Extractor (Auto-generates catalogs from embedded SSML)\nexport type { ExtractionResult } from \"./services/SSMLExtractor.js\";\nexport { SSMLExtractor } from \"./services/SSMLExtractor.js\";\n// Theme Provider\nexport type { FontSize, ThemeConfig } from \"./services/ThemeProvider.js\";\nexport { ThemeProvider } from \"./services/ThemeProvider.js\";\n// Tool Coordinator\nexport { ToolCoordinator, ZIndexLayer } from \"./services/ToolCoordinator.js\";\n// Toolkit Coordinator (Centralized service management)\nexport type {\n\tAnswerEliminatorToolConfig,\n\tProviderLifecycleContext,\n\tSectionControllerContext,\n\tSectionControllerEvent,\n\tSectionControllerEventType,\n\tSectionItemEvent,\n\tSectionItemEventType,\n\tSectionControllerFactoryDefaults,\n\tSectionControllerHandle,\n\tSectionControllerKey,\n\tSectionScopedEvent,\n\tSectionScopedEventType,\n\tSectionSessionPersistenceConfig,\n\tSectionItemEventSubscriptionArgs,\n\tSectionScopedEventSubscriptionArgs,\n\tSectionEventSubscriptionArgs,\n\tSectionSessionPersistenceStrategy,\n\tSectionControllerLoadedRenderable,\n\tSectionControllerRuntimeState,\n\tSectionControllerSessionState,\n\tSectionPersistenceFactoryDefaults,\n\tToolConfig,\n\tToolkitCoordinatorConfig,\n\tToolkitCoordinatorHooks,\n\tToolkitErrorContext,\n\tToolkitInitStatus,\n\tToolkitServiceBundle,\n\tToolkitToolsConfig,\n\tTTSToolConfig,\n} from \"./services/ToolkitCoordinator.js\";\nexport { ToolkitCoordinator } from \"./services/ToolkitCoordinator.js\";\nexport type {\n\tCanonicalToolsConfig,\n\tToolPlacementConfig,\n\tToolPlacementLevel,\n\tToolPolicyConfig,\n\tToolProvidersConfig,\n} from \"./services/tools-config-normalizer.js\";\nexport type {\n\tFrameworkErrorKind,\n\tFrameworkErrorModel,\n\tFrameworkErrorSeverity,\n} from \"./services/framework-error.js\";\nexport {\n\tformatFrameworkErrorForConsole,\n\tframeworkErrorFromToolConfigDiagnostics,\n\tframeworkErrorFromUnknown,\n\ttoFrameworkErrorModel,\n} from \"./services/framework-error.js\";\nexport type { FrameworkErrorListener } from \"./services/framework-error-bus.js\";\nexport type {\n\tToolConfigDiagnostic,\n\tToolConfigDiagnosticSeverity,\n\tToolConfigStrictness,\n\tToolConfigValidationOptions,\n\tToolConfigValidationResult,\n} from \"./services/tool-config-validation.js\";\nexport type {\n\tToolbarButtonItem,\n\tToolbarItem,\n\tToolbarItemBase,\n\tToolbarLinkItem,\n} from \"./services/toolbar-items.js\";\nexport {\n\tisExternalIconUrl,\n\tisInlineSvgIcon,\n\tisToolbarLinkItem,\n\tisValidToolbarItemShape,\n} from \"./services/toolbar-items.js\";\nexport {\n\tnormalizeToolsConfig,\n\tnormalizeToolAlias,\n\tnormalizeToolList,\n\tparseToolList,\n} from \"./services/tools-config-normalizer.js\";\nexport {\n\tframeworkErrorFromToolConfigValidation,\n\tnormalizeAndValidateToolsConfig,\n} from \"./services/tool-config-validation.js\";\nexport type {\n\tParsedToolInstanceId,\n\tToolScopeLevel,\n} from \"./services/tool-instance-id.js\";\nexport {\n\tcreateScopedToolId,\n\tparseScopedToolId,\n\ttoOverlayToolId,\n} from \"./services/tool-instance-id.js\";\n// Text-to-Speech Service\nexport type { TTSConfig } from \"./services/TTSService.js\";\nexport { PlaybackState, TTSService } from \"./services/TTSService.js\";\nexport {\n\tPIE_TTS_CONTROL_HANDOFF_EVENT,\n\ttype TTSControlHandoffDetail,\n} from \"./services/tts-control-events.js\";\nexport { BrowserTTSProvider } from \"./services/tts/browser-provider.js\";\nexport type { SREMathSpeechOptions } from \"./services/tts/math-speech.js\";\nexport type {\n\tNormalizedTTSSpeedOption,\n\tTTSHostToolbarLayout,\n\tTTSLayoutMode,\n\tTTSRuntimeSettings,\n\tTTSSpeedOption,\n\tTTSSpeedOptionConfig,\n} from \"./services/tts-runtime-config.js\";\nexport {\n\tDEFAULT_TTS_SPEED_OPTIONS,\n\tformatTTSSpeedOptionsAsText,\n\tnormalizeTTSLayoutMode,\n\tnormalizeTTSSpeedControlOptions,\n\tnormalizeTTSSpeedOptionConfigs,\n\tnormalizeTTSSpeedOptions,\n\tparseTTSSpeedOptionsFromText,\n\tresolveTTSHostToolbarLayout,\n\tresolveTTSLayoutMode,\n\tresolveTTSRuntimeSettings,\n} from \"./services/tts-runtime-config.js\";\n// TTS Provider System\nexport type {\n\tITTSProvider,\n\tITTSProviderImplementation,\n\tTTSSpeechSegment,\n\tTTSFeature,\n\tTTSProviderCapabilities,\n} from \"@pie-players/pie-tts\";\n\n// ============================================================================\n// Item loading (client-resolvable default; optional backend hook)\n// ============================================================================\n\nexport type {\n\tCreateLoadItemOptions,\n\tLoadItem,\n\tLoadItemOptions,\n} from \"./item-loader.js\";\nexport {\n\tcreateFetchItemLoader,\n\tcreateLoadItem,\n\tItemLoadError,\n} from \"./item-loader.js\";\n\n// ============================================================================\n// Attempt Session\n// ============================================================================\n\nexport type {\n\tStorageLike,\n\tTestAttemptItemSession,\n\tTestAttemptSession,\n\tTestAttemptSessionNavigationState,\n\tTestAttemptSessionRealization,\n} from \"./attempt/TestSession.js\";\nexport {\n\tcreateMemoryStorage,\n\tcreateTestAttemptSessionIdentifier,\n\tcreateNewTestAttemptSession,\n\tgetBrowserLocalStorage,\n\tgetOrCreateAnonymousDeviceId,\n\tgetTestAttemptSessionStorageKey,\n\tloadTestAttemptSession,\n\tsaveTestAttemptSession,\n\tsetCurrentPosition,\n\tupsertItemSessionFromPieSessionChange,\n\tupsertVisitedItem,\n} from \"./attempt/TestSession.js\";\nexport type {\n\tAssessmentSession,\n\tAssessmentSectionSessionState,\n\tAssessmentSessionNavigationState,\n\tAssessmentSessionRealization,\n} from \"./attempt/AssessmentSession.js\";\nexport {\n\tcreateNewAssessmentSession,\n\tgetAssessmentSessionStorageKey,\n\tloadAssessmentSession,\n\tsaveAssessmentSession,\n\tsetCurrentSectionPosition,\n\tupsertSectionSession,\n} from \"./attempt/AssessmentSession.js\";\nexport type {\n\tActivitySessionPatchPayload,\n\tMapActivityToTestAttemptSessionArgs,\n\tPieBackendActivityDefinition,\n\tPieBackendActivityItemRef,\n\tPieBackendActivitySession,\n} from \"./attempt/adapters/activity-to-test-attempt-session.js\";\nexport {\n\tbuildActivitySessionItemUpdate,\n\tbuildActivitySessionPatchFromTestAttemptSession,\n\tmapActivityToTestAttemptSession,\n\ttoItemSessionsRecord,\n} from \"./attempt/adapters/activity-to-test-attempt-session.js\";\n\n// Section Player - Use @pie-players/pie-section-player web component\n\n// ============================================================================\n// Shared Components\n// ============================================================================\n\n// ItemToolBar custom element registration helper is exported via package.json exports field\n// Import using: import '@pie-players/pie-assessment-toolkit/components/item-toolbar-element';\n// PieAssessmentToolkit custom element registration helper is exported via package.json exports field\n"]}
|
|
@@ -92,6 +92,16 @@ export interface ToolWindowShellAction {
|
|
|
92
92
|
* The shell is offset by `initialMargin` (default 16 px) from the chosen corner.
|
|
93
93
|
*/
|
|
94
94
|
export type ToolWindowShellAlign = "center" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
95
|
+
export interface ToolWindowShellContentConfig {
|
|
96
|
+
/** Vertical overflow behavior for the hosted content pane. Defaults to "hidden". */
|
|
97
|
+
overflowY?: "hidden" | "auto";
|
|
98
|
+
/**
|
|
99
|
+
* Preserve the content area's configured minimum height when the shell shrinks
|
|
100
|
+
* below `minHeight`, letting the content pane scroll instead of compressing
|
|
101
|
+
* the hosted element.
|
|
102
|
+
*/
|
|
103
|
+
preserveMinHeight?: boolean;
|
|
104
|
+
}
|
|
95
105
|
export interface ToolWindowShellConfig {
|
|
96
106
|
title?: string;
|
|
97
107
|
draggable?: boolean;
|
|
@@ -107,6 +117,7 @@ export interface ToolWindowShellConfig {
|
|
|
107
117
|
initialAlign?: ToolWindowShellAlign;
|
|
108
118
|
/** Distance (px) from the viewport edge when using a corner align. Defaults to 16. */
|
|
109
119
|
initialMargin?: number;
|
|
120
|
+
content?: ToolWindowShellContentConfig;
|
|
110
121
|
actions?: ToolWindowShellAction[];
|
|
111
122
|
}
|
|
112
123
|
export interface HostedToolContext {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolRegistry.js","sourceRoot":"","sources":["../../src/services/ToolRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool Registry\n *\n * Central registry for all assessment tools. Manages tool metadata, visibility logic,\n * and button/instance creation. Supports dynamic registration and override by integrators.\n */\n\nimport type { ToolContext, ToolLevel } from \"./tool-context.js\";\nimport type { ToolComponentOverrides } from \"../tools/tool-tag-map.js\";\nimport type {\n\tElementToolStateStoreApi,\n\tToolCoordinatorApi,\n\tToolkitCoordinatorApi,\n\tTtsServiceApi,\n} from \"./interfaces.js\";\nimport type { ToolProviderApi } from \"./tool-providers/ToolProviderApi.js\";\nimport type { ToolProviderConfig as ToolRuntimeConfig } from \"./tools-config-normalizer.js\";\nimport type { ToolConfigDiagnostic } from \"./tool-config-validation.js\";\nimport { normalizeToolAlias } from \"./tools-config-normalizer.js\";\n\nexport type ToolModuleLoader = () => Promise<unknown>;\n\nexport interface ToolToolbarButtonDefinition {\n\ttoolId: string;\n\tlabel: string;\n\ticon: string;\n\tariaLabel: string;\n\ttooltip?: string;\n\tonClick: () => void;\n\tclassName?: string;\n\tdisabled?: boolean;\n\tactive?: boolean;\n}\n\nexport interface ToolbarContext {\n\tscope: {\n\t\tlevel: ToolLevel;\n\t\tscopeId: string;\n\t\tassessmentId?: string;\n\t\tsectionId?: string;\n\t\titemId?: string;\n\t\tcanonicalItemId?: string;\n\t\tcontentKind?: string;\n\t};\n\titemId: string;\n\tcatalogId: string;\n\tlanguage: string;\n\tui?: {\n\t\tsize?: string;\n\t};\n\tgetScopeElement?: () => HTMLElement | null;\n\tgetGlobalElementId?: () => string | null;\n\ttoolCoordinator: ToolCoordinatorApi | null;\n\ttoolkitCoordinator: ToolkitCoordinatorApi | null;\n\tttsService: TtsServiceApi | null;\n\telementToolStateStore: ElementToolStateStoreApi | null;\n\ttoggleTool: (toolId: string) => void;\n\tisToolVisible: (toolId: string) => boolean;\n\tsubscribeVisibility: ((listener: () => void) => () => void) | null;\n\tcomponentOverrides?: ToolComponentOverrides;\n\tgetResolvedToolContext?: (toolId: string) => ResolvedToolContext | null;\n\tgetToolRenderParams?: (toolId: string) => Record<string, unknown> | null;\n}\n\nexport interface ToolContextResolverContext {\n\ttoolId: string;\n\tcontext: ToolContext;\n\ttoolbarContext: ToolbarContext;\n}\n\nexport interface ToolContextResolverResult {\n\tvisible?: boolean;\n\tparams?: Record<string, unknown>;\n\treason?: string;\n}\n\nexport type ToolContextResolver = (\n\tcontext: ToolContextResolverContext,\n) => ToolContextResolverResult | null | undefined;\n\nexport type ToolContextResolverMap = Record<\n\tstring,\n\tToolContextResolver | null | undefined\n>;\n\nexport interface ResolvedToolContext {\n\ttoolId: string;\n\tvisible: boolean;\n\tparams: Record<string, unknown>;\n\treason?: string;\n}\n\nexport interface ToolRenderElement {\n\telement: HTMLElement | null;\n\tmount: \"before-buttons\" | \"after-buttons\" | \"controls-row\";\n\tlayoutHints?: {\n\t\tcontrolsRow?: {\n\t\t\treserveSpace?: boolean;\n\t\t\tshowWhenToolActive?: boolean;\n\t\t};\n\t};\n\tshell?: ToolWindowShellConfig;\n}\n\nexport interface ToolWindowShellAction {\n\tid: string;\n\tlabel: string;\n\tariaLabel?: string;\n\ticonSvg?: string;\n\tonClick: () => void;\n}\n\n/**\n * Alignment corner for the initial shell position.\n * The shell is offset by `initialMargin` (default 16 px) from the chosen corner.\n */\nexport type ToolWindowShellAlign =\n\t| \"center\"\n\t| \"top-left\"\n\t| \"top-right\"\n\t| \"bottom-left\"\n\t| \"bottom-right\";\n\nexport interface ToolWindowShellConfig {\n\ttitle?: string;\n\tdraggable?: boolean;\n\tresizable?: boolean;\n\tcloseable?: boolean;\n\tinitialWidth?: number;\n\tinitialHeight?: number;\n\tminWidth?: number;\n\tminHeight?: number;\n\tmaxWidth?: number;\n\tmaxHeight?: number;\n\t/** Initial placement of the shell. Defaults to `'center'`. */\n\tinitialAlign?: ToolWindowShellAlign;\n\t/** Distance (px) from the viewport edge when using a corner align. Defaults to 16. */\n\tinitialMargin?: number;\n\tactions?: ToolWindowShellAction[];\n}\n\nexport interface HostedToolContext {\n\ttoolId: string;\n\ttoolbarContext: ToolbarContext;\n\tshellConfig: ToolWindowShellConfig;\n}\n\nexport interface HostedToolSize {\n\twidth: number;\n\theight: number;\n}\n\nexport interface ToolProviderDescriptor {\n\tgetProviderId?: (config: ToolRuntimeConfig | undefined) => string;\n\tcreateProvider: (config: ToolRuntimeConfig | undefined) => ToolProviderApi;\n\tgetInitConfig?: (\n\t\tconfig: ToolRuntimeConfig | undefined,\n\t) => Record<string, unknown>;\n\tsanitizeConfig?: (config: ToolRuntimeConfig) => ToolRuntimeConfig;\n\tvalidateConfig?: (config: ToolRuntimeConfig) => ToolConfigDiagnostic[];\n\tgetAuthFetcher?: (\n\t\tconfig: ToolRuntimeConfig | undefined,\n\t) => (() => Promise<Record<string, unknown>>) | undefined;\n\tlazy?: boolean;\n}\n\nexport interface ToolToolbarRenderResult {\n\ttoolId: string;\n\telements?: ToolRenderElement[];\n\tbutton?: ToolToolbarButtonDefinition | null;\n\tsync?: () => void;\n\tsubscribeActive?: (callback: (active: boolean) => void) => () => void;\n}\n\nexport type ToolActivation = \"toolbar-toggle\" | \"selection-gateway\";\nexport type ToolSingletonScope = \"section\";\n\n/**\n * Tool registration interface\n */\nexport interface ToolRegistration {\n\t/** Unique tool identifier (e.g., 'calculator', 'textToSpeech') */\n\ttoolId: string;\n\n\t/** Human-readable name */\n\tname: string;\n\n\t/** Description of what the tool does */\n\tdescription: string;\n\n\t/** Icon identifier or SVG string */\n\ticon: string | ((context: ToolContext) => string);\n\n\t/** Which levels this tool supports */\n\tsupportedLevels: ToolLevel[];\n\n\t/**\n\t * Activation model for this tool.\n\t * - toolbar-toggle: rendered as a toolbar button (default)\n\t * - selection-gateway: rendered as a singleton selection-driven gateway\n\t */\n\tactivation?: ToolActivation;\n\n\t/**\n\t * Optional singleton scope for activation models that mount exactly one instance.\n\t */\n\tsingletonScope?: ToolSingletonScope;\n\n\t/**\n\t * PNP support IDs that enable this tool (optional)\n\t * Used by the tool policy engine to determine if a PNP support enables this tool.\n\t * Example: ['calculator', 'basic-calculator', 'scientific-calculator']\n\t */\n\tpnpSupportIds?: string[];\n\t/**\n\t * Optional provider registration metadata.\n\t * When present, ToolkitCoordinator can register provider(s) generically\n\t * without hardcoded tool-specific branches.\n\t */\n\tprovider?: ToolProviderDescriptor;\n\t/**\n\t * Optional shell-host lifecycle hooks for hosted (floating) tools.\n\t */\n\tonHostedMount?: (\n\t\telement: HTMLElement,\n\t\tcontext: HostedToolContext,\n\t) => void | Promise<void>;\n\tonHostedResize?: (\n\t\tsize: HostedToolSize,\n\t\telement: HTMLElement,\n\t\tcontext: HostedToolContext,\n\t) => void | Promise<void>;\n\tonHostedUnmount?: (\n\t\telement: HTMLElement,\n\t\tcontext: HostedToolContext,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Pass 2: Tool decides if it's relevant in this context\n\t * Called ONLY if orchestrator has already allowed the tool (Pass 1)\n\t *\n\t * @param context - Rich context about where tool is being evaluated\n\t * @returns true if tool should be visible, false to hide\n\t */\n\tisVisibleInContext(context: ToolContext): boolean;\n\n\t/** Required toolbar-first render contract. */\n\trenderToolbar(\n\t\tcontext: ToolContext,\n\t\ttoolbarContext: ToolbarContext,\n\t): ToolToolbarRenderResult | null;\n}\n\nconst VALID_TOOL_LEVELS: ToolLevel[] = [\n\t\"assessment\",\n\t\"section\",\n\t\"item\",\n\t\"passage\",\n\t\"rubric\",\n\t\"element\",\n];\n\nfunction assertNonEmptyString(\n\tvalue: unknown,\n\tfieldName: string,\n): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration: \"${fieldName}\" must be a non-empty string.`,\n\t\t);\n\t}\n}\n\n// Defence-in-depth: reject obvious XSS payloads in tool-registered icon\n// markup at registration time. Runtime rendering still runs each icon\n// through DOMPurify (see `ToolIcon.svelte`), but surfacing the problem\n// early produces a clearer error for tool authors than \"the icon silently\n// disappeared after sanitization\".\nconst SCRIPTABLE_ICON_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [\n\t{ pattern: /<script\\b/i, reason: \"contains a <script> tag\" },\n\t{\n\t\tpattern: /\\son[a-z]+\\s*=/i,\n\t\treason: \"contains an inline event handler (on*=) attribute\",\n\t},\n\t{ pattern: /javascript:/i, reason: \"contains a javascript: URL\" },\n\t{\n\t\tpattern: /<foreignObject\\b/i,\n\t\treason: \"contains a <foreignObject> element\",\n\t},\n];\n\nfunction assertIconStringIsSafe(\n\ttoolId: string,\n\ticon: string,\n\tfieldName: string,\n): void {\n\tconst trimmed = icon.trimStart();\n\tconst looksLikeSvg = trimmed.toLowerCase().startsWith(\"<svg\");\n\tconst looksLikeUrl = /^https?:/i.test(trimmed);\n\tconst looksLikeDataUrl = /^data:/i.test(trimmed);\n\tif (looksLikeDataUrl) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${toolId}\": \"${fieldName}\" may not be a data: URL.`,\n\t\t);\n\t}\n\tif (!looksLikeSvg && !looksLikeUrl) return;\n\tfor (const { pattern, reason } of SCRIPTABLE_ICON_PATTERNS) {\n\t\tif (pattern.test(icon)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid tool registration \"${toolId}\": \"${fieldName}\" ${reason}. Inline SVG icons must not include scriptable content.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction assertToolRegistrationShape(registration: ToolRegistration): void {\n\tassertNonEmptyString(registration.toolId, \"toolId\");\n\tassertNonEmptyString(registration.name, \"name\");\n\tassertNonEmptyString(registration.description, \"description\");\n\n\tif (\n\t\ttypeof registration.icon !== \"string\" &&\n\t\ttypeof registration.icon !== \"function\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"icon\" must be a string or function.`,\n\t\t);\n\t}\n\tif (typeof registration.icon === \"string\") {\n\t\tassertIconStringIsSafe(registration.toolId, registration.icon, \"icon\");\n\t}\n\tif (\n\t\t!Array.isArray(registration.supportedLevels) ||\n\t\tregistration.supportedLevels.length === 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"supportedLevels\" must be a non-empty array.`,\n\t\t);\n\t}\n\tconst invalidLevel = registration.supportedLevels.find(\n\t\t(level) => !VALID_TOOL_LEVELS.includes(level),\n\t);\n\tif (invalidLevel) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": unsupported level \"${invalidLevel}\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.activation !== undefined &&\n\t\tregistration.activation !== \"toolbar-toggle\" &&\n\t\tregistration.activation !== \"selection-gateway\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": unsupported activation \"${String(registration.activation)}\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.singletonScope !== undefined &&\n\t\tregistration.singletonScope !== \"section\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": unsupported singletonScope \"${String(registration.singletonScope)}\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.activation === \"selection-gateway\" &&\n\t\tregistration.singletonScope !== \"section\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": selection-gateway tools must declare singletonScope \"section\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.pnpSupportIds !== undefined &&\n\t\t(!Array.isArray(registration.pnpSupportIds) ||\n\t\t\tregistration.pnpSupportIds.some(\n\t\t\t\t(pnpId) => typeof pnpId !== \"string\" || pnpId.trim().length === 0,\n\t\t\t))\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"pnpSupportIds\" must be an array of non-empty strings.`,\n\t\t);\n\t}\n\tif (typeof registration.isVisibleInContext !== \"function\") {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"isVisibleInContext\" must be a function.`,\n\t\t);\n\t}\n\tif (typeof registration.renderToolbar !== \"function\") {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"renderToolbar\" must be a function.`,\n\t\t);\n\t}\n}\n\n/**\n * Tool Registry\n *\n * Manages tool registrations and provides query/lookup functionality\n */\nexport class ToolRegistry {\n\tprivate tools = new Map<string, ToolRegistration>();\n\tprivate pnpIndex = new Map<string, Set<string>>(); // pnpSupportId → Set<toolId>\n\tprivate componentOverrides: ToolComponentOverrides = {};\n\tprivate moduleLoaders = new Map<string, ToolModuleLoader>();\n\tprivate loadedToolModules = new Set<string>();\n\tprivate moduleLoadPromises = new Map<string, Promise<void>>();\n\n\t/**\n\t * Normalize a single tool alias to canonical toolId.\n\t */\n\tnormalizeToolId(toolId: string): string {\n\t\treturn normalizeToolAlias(toolId);\n\t}\n\n\t/**\n\t * Normalize a list of tool aliases to canonical toolIds.\n\t */\n\tnormalizeToolIds(toolIds: string[]): string[] {\n\t\treturn toolIds.map((toolId) => this.normalizeToolId(toolId));\n\t}\n\n\t/**\n\t * Register a tool\n\t *\n\t * @param registration - Tool registration\n\t * @throws Error if toolId is already registered\n\t */\n\tregister(registration: ToolRegistration): void {\n\t\tassertToolRegistrationShape(registration);\n\t\tif (this.tools.has(registration.toolId)) {\n\t\t\tthrow new Error(`Tool '${registration.toolId}' is already registered`);\n\t\t}\n\n\t\tthis.tools.set(registration.toolId, registration);\n\n\t\t// Index PNP support IDs\n\t\tif (registration.pnpSupportIds) {\n\t\t\tfor (const pnpId of registration.pnpSupportIds) {\n\t\t\t\tif (!this.pnpIndex.has(pnpId)) {\n\t\t\t\t\tthis.pnpIndex.set(pnpId, new Set());\n\t\t\t\t}\n\t\t\t\tthis.pnpIndex.get(pnpId)!.add(registration.toolId);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Override an existing tool registration\n\t *\n\t * @param registration - New tool registration (must have existing toolId)\n\t */\n\toverride(registration: ToolRegistration): void {\n\t\tassertToolRegistrationShape(registration);\n\t\tif (!this.tools.has(registration.toolId)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot override non-existent tool '${registration.toolId}'`,\n\t\t\t);\n\t\t}\n\n\t\t// Remove old PNP index entries\n\t\tconst oldReg = this.tools.get(registration.toolId)!;\n\t\tif (oldReg.pnpSupportIds) {\n\t\t\tfor (const pnpId of oldReg.pnpSupportIds) {\n\t\t\t\tthis.pnpIndex.get(pnpId)?.delete(registration.toolId);\n\t\t\t}\n\t\t}\n\n\t\t// Add new registration\n\t\tthis.tools.set(registration.toolId, registration);\n\n\t\t// Re-index PNP support IDs\n\t\tif (registration.pnpSupportIds) {\n\t\t\tfor (const pnpId of registration.pnpSupportIds) {\n\t\t\t\tif (!this.pnpIndex.has(pnpId)) {\n\t\t\t\t\tthis.pnpIndex.set(pnpId, new Set());\n\t\t\t\t}\n\t\t\t\tthis.pnpIndex.get(pnpId)!.add(registration.toolId);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Unregister a tool\n\t *\n\t * @param toolId - Tool ID to remove\n\t */\n\tunregister(toolId: string): void {\n\t\tconst reg = this.tools.get(toolId);\n\t\tif (!reg) return;\n\n\t\t// Remove PNP index entries\n\t\tif (reg.pnpSupportIds) {\n\t\t\tfor (const pnpId of reg.pnpSupportIds) {\n\t\t\t\tthis.pnpIndex.get(pnpId)?.delete(toolId);\n\t\t\t}\n\t\t}\n\n\t\tthis.tools.delete(toolId);\n\t}\n\n\t/**\n\t * Get a tool registration by ID\n\t *\n\t * @param toolId - Tool ID\n\t * @returns Tool registration or undefined\n\t */\n\tget(toolId: string): ToolRegistration | undefined {\n\t\treturn this.tools.get(toolId);\n\t}\n\n\t/**\n\t * Check if a tool is registered\n\t *\n\t * @param toolId - Tool ID\n\t * @returns true if registered\n\t */\n\thas(toolId: string): boolean {\n\t\treturn this.tools.has(toolId);\n\t}\n\n\t/**\n\t * Get all registered tool IDs\n\t *\n\t * @returns Array of tool IDs\n\t */\n\tgetAllToolIds(): string[] {\n\t\treturn Array.from(this.tools.keys());\n\t}\n\n\t/**\n\t * Get all tool registrations\n\t *\n\t * @returns Array of tool registrations\n\t */\n\tgetAllTools(): ToolRegistration[] {\n\t\treturn Array.from(this.tools.values());\n\t}\n\n\t/**\n\t * Find tool IDs that support a given PNP support ID\n\t *\n\t * @param pnpSupportId - PNP support ID (e.g., 'calculator')\n\t * @returns Set of tool IDs that support this PNP ID\n\t */\n\tgetToolsByPNPSupport(pnpSupportId: string): Set<string> {\n\t\treturn this.pnpIndex.get(pnpSupportId) || new Set();\n\t}\n\n\t/**\n\t * Get tools that support a specific level\n\t *\n\t * @param level - Tool level (assessment, section, item, passage, element)\n\t * @returns Array of tool registrations that support this level\n\t */\n\tgetToolsByLevel(level: ToolLevel): ToolRegistration[] {\n\t\treturn this.getAllTools().filter((tool) =>\n\t\t\ttool.supportedLevels.includes(level),\n\t\t);\n\t}\n\n\t/**\n\t * Resolve tool activation, defaulting to toolbar-toggle.\n\t */\n\tgetToolActivation(toolId: string): ToolActivation {\n\t\treturn this.get(toolId)?.activation || \"toolbar-toggle\";\n\t}\n\n\t/**\n\t * Resolve singleton scope for a tool when present.\n\t */\n\tgetToolSingletonScope(toolId: string): ToolSingletonScope | null {\n\t\treturn this.get(toolId)?.singletonScope || null;\n\t}\n\n\t/**\n\t * Filter tool IDs by activation type.\n\t */\n\tfilterToolIdsByActivation(\n\t\ttoolIds: string[],\n\t\tactivation: ToolActivation,\n\t): string[] {\n\t\treturn toolIds.filter(\n\t\t\t(toolId) => this.getToolActivation(toolId) === activation,\n\t\t);\n\t}\n\n\t/**\n\t * Filter tools by visibility in a given context\n\t *\n\t * Pass 2 of the two-pass model: Given a list of allowed tool IDs (from Pass 1),\n\t * ask each tool if it's relevant in this context.\n\t *\n\t * @param allowedToolIds - Tool IDs that passed Pass 1 (orchestrator approval)\n\t * @param context - Context to evaluate\n\t * @returns Array of visible tool registrations\n\t */\n\tfilterVisibleInContext(\n\t\tallowedToolIds: string[],\n\t\tcontext: ToolContext,\n\t): ToolRegistration[] {\n\t\tconst visible: ToolRegistration[] = [];\n\n\t\tfor (const toolId of allowedToolIds) {\n\t\t\tconst tool = this.get(toolId);\n\t\t\tif (!tool) {\n\t\t\t\tconsole.warn(`Tool '${toolId}' is allowed but not registered`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check if tool supports this level\n\t\t\tif (!tool.supportedLevels.includes(context.level)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Pass 2: Ask tool if it's relevant\n\t\t\ttry {\n\t\t\t\tif (tool.isVisibleInContext(context)) {\n\t\t\t\t\tvisible.push(tool);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Error evaluating visibility for tool '${toolId}':`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn visible;\n\t}\n\n\t/**\n\t * Get tool metadata for building UIs\n\t * Useful for building PNP configuration interfaces\n\t *\n\t * @returns Array of tool metadata (id, name, description, pnpSupportIds)\n\t */\n\tgetToolMetadata(): Array<{\n\t\ttoolId: string;\n\t\tname: string;\n\t\tdescription: string;\n\t\tpnpSupportIds: string[];\n\t\tsupportedLevels: ToolLevel[];\n\t\tactivation: ToolActivation;\n\t\tsingletonScope: ToolSingletonScope | null;\n\t}> {\n\t\treturn this.getAllTools().map((tool) => ({\n\t\t\ttoolId: tool.toolId,\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tpnpSupportIds: tool.pnpSupportIds || [],\n\t\t\tsupportedLevels: tool.supportedLevels,\n\t\t\tactivation: tool.activation || \"toolbar-toggle\",\n\t\t\tsingletonScope: tool.singletonScope || null,\n\t\t}));\n\t}\n\n\t/**\n\t * Generate PNP support IDs from enabled tools\n\t * Useful for creating PNP profiles\n\t *\n\t * @param enabledToolIds - Tool IDs to enable\n\t * @returns Array of unique PNP support IDs\n\t */\n\tgeneratePNPSupportsFromTools(enabledToolIds: string[]): string[] {\n\t\tconst pnpSupports = new Set<string>();\n\n\t\tfor (const toolId of enabledToolIds) {\n\t\t\tconst tool = this.get(toolId);\n\t\t\tif (tool?.pnpSupportIds) {\n\t\t\t\tfor (const pnpId of tool.pnpSupportIds) {\n\t\t\t\t\tpnpSupports.add(pnpId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Array.from(pnpSupports);\n\t}\n\n\t/**\n\t * Clear all registrations (useful for testing)\n\t */\n\tclear(): void {\n\t\tthis.tools.clear();\n\t\tthis.pnpIndex.clear();\n\t}\n\n\t/**\n\t * Configure global component overrides used by tool instance creation.\n\t */\n\tsetComponentOverrides(overrides: ToolComponentOverrides): void {\n\t\tthis.componentOverrides = overrides;\n\t}\n\n\t/**\n\t * Register lazy module loaders by toolId.\n\t * Toolbars call ensureToolModuleLoaded(toolId) before instance creation.\n\t */\n\tsetToolModuleLoaders(\n\t\tloaders: Partial<Record<string, ToolModuleLoader>>,\n\t): void {\n\t\tfor (const [toolId, loader] of Object.entries(loaders)) {\n\t\t\tif (!loader) continue;\n\t\t\tassertNonEmptyString(toolId, \"tool module loader id\");\n\t\t\tif (typeof loader !== \"function\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid tool module loader for \"${toolId}\": expected a function.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.moduleLoaders.set(toolId, loader);\n\t\t}\n\t}\n\n\t/**\n\t * Ensure tool module side-effects are loaded exactly once.\n\t * Safe to call repeatedly; concurrent callers share the same promise.\n\t */\n\tasync ensureToolModuleLoaded(toolId: string): Promise<void> {\n\t\tif (this.loadedToolModules.has(toolId)) return;\n\n\t\tconst existingPromise = this.moduleLoadPromises.get(toolId);\n\t\tif (existingPromise) {\n\t\t\tawait existingPromise;\n\t\t\treturn;\n\t\t}\n\n\t\tconst loader = this.moduleLoaders.get(toolId);\n\t\tif (!loader) return;\n\n\t\tconst loadPromise = (async () => {\n\t\t\tawait loader();\n\t\t\tthis.loadedToolModules.add(toolId);\n\t\t})();\n\n\t\tthis.moduleLoadPromises.set(toolId, loadPromise);\n\t\ttry {\n\t\t\tawait loadPromise;\n\t\t} finally {\n\t\t\tthis.moduleLoadPromises.delete(toolId);\n\t\t}\n\t}\n\n\t/**\n\t * Ensure a set of tool modules are loaded.\n\t */\n\tasync ensureToolModulesLoaded(toolIds: string[]): Promise<void> {\n\t\tawait Promise.all(\n\t\t\ttoolIds.map((toolId) => this.ensureToolModuleLoaded(toolId)),\n\t\t);\n\t}\n\n\t/**\n\t * Whether a tool module has already been loaded.\n\t */\n\tisToolModuleLoaded(toolId: string): boolean {\n\t\treturn this.loadedToolModules.has(toolId);\n\t}\n\n\t/**\n\t * Render a tool for toolbar use with component overrides attached.\n\t */\n\trenderForToolbar(\n\t\ttoolId: string,\n\t\tcontext: ToolContext,\n\t\ttoolbarContext: ToolbarContext,\n\t): ToolToolbarRenderResult | null {\n\t\tconst tool = this.get(toolId);\n\t\tif (!tool) {\n\t\t\tthrow new Error(`Tool '${toolId}' is not registered`);\n\t\t}\n\n\t\tconst mergedContext: ToolbarContext = {\n\t\t\t...toolbarContext,\n\t\t\tcomponentOverrides: {\n\t\t\t\t...(this.componentOverrides || {}),\n\t\t\t\t...(toolbarContext.componentOverrides || {}),\n\t\t\t},\n\t\t};\n\n\t\treturn tool.renderToolbar(context, mergedContext);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ToolRegistry.js","sourceRoot":"","sources":["../../src/services/ToolRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool Registry\n *\n * Central registry for all assessment tools. Manages tool metadata, visibility logic,\n * and button/instance creation. Supports dynamic registration and override by integrators.\n */\n\nimport type { ToolContext, ToolLevel } from \"./tool-context.js\";\nimport type { ToolComponentOverrides } from \"../tools/tool-tag-map.js\";\nimport type {\n\tElementToolStateStoreApi,\n\tToolCoordinatorApi,\n\tToolkitCoordinatorApi,\n\tTtsServiceApi,\n} from \"./interfaces.js\";\nimport type { ToolProviderApi } from \"./tool-providers/ToolProviderApi.js\";\nimport type { ToolProviderConfig as ToolRuntimeConfig } from \"./tools-config-normalizer.js\";\nimport type { ToolConfigDiagnostic } from \"./tool-config-validation.js\";\nimport { normalizeToolAlias } from \"./tools-config-normalizer.js\";\n\nexport type ToolModuleLoader = () => Promise<unknown>;\n\nexport interface ToolToolbarButtonDefinition {\n\ttoolId: string;\n\tlabel: string;\n\ticon: string;\n\tariaLabel: string;\n\ttooltip?: string;\n\tonClick: () => void;\n\tclassName?: string;\n\tdisabled?: boolean;\n\tactive?: boolean;\n}\n\nexport interface ToolbarContext {\n\tscope: {\n\t\tlevel: ToolLevel;\n\t\tscopeId: string;\n\t\tassessmentId?: string;\n\t\tsectionId?: string;\n\t\titemId?: string;\n\t\tcanonicalItemId?: string;\n\t\tcontentKind?: string;\n\t};\n\titemId: string;\n\tcatalogId: string;\n\tlanguage: string;\n\tui?: {\n\t\tsize?: string;\n\t};\n\tgetScopeElement?: () => HTMLElement | null;\n\tgetGlobalElementId?: () => string | null;\n\ttoolCoordinator: ToolCoordinatorApi | null;\n\ttoolkitCoordinator: ToolkitCoordinatorApi | null;\n\tttsService: TtsServiceApi | null;\n\telementToolStateStore: ElementToolStateStoreApi | null;\n\ttoggleTool: (toolId: string) => void;\n\tisToolVisible: (toolId: string) => boolean;\n\tsubscribeVisibility: ((listener: () => void) => () => void) | null;\n\tcomponentOverrides?: ToolComponentOverrides;\n\tgetResolvedToolContext?: (toolId: string) => ResolvedToolContext | null;\n\tgetToolRenderParams?: (toolId: string) => Record<string, unknown> | null;\n}\n\nexport interface ToolContextResolverContext {\n\ttoolId: string;\n\tcontext: ToolContext;\n\ttoolbarContext: ToolbarContext;\n}\n\nexport interface ToolContextResolverResult {\n\tvisible?: boolean;\n\tparams?: Record<string, unknown>;\n\treason?: string;\n}\n\nexport type ToolContextResolver = (\n\tcontext: ToolContextResolverContext,\n) => ToolContextResolverResult | null | undefined;\n\nexport type ToolContextResolverMap = Record<\n\tstring,\n\tToolContextResolver | null | undefined\n>;\n\nexport interface ResolvedToolContext {\n\ttoolId: string;\n\tvisible: boolean;\n\tparams: Record<string, unknown>;\n\treason?: string;\n}\n\nexport interface ToolRenderElement {\n\telement: HTMLElement | null;\n\tmount: \"before-buttons\" | \"after-buttons\" | \"controls-row\";\n\tlayoutHints?: {\n\t\tcontrolsRow?: {\n\t\t\treserveSpace?: boolean;\n\t\t\tshowWhenToolActive?: boolean;\n\t\t};\n\t};\n\tshell?: ToolWindowShellConfig;\n}\n\nexport interface ToolWindowShellAction {\n\tid: string;\n\tlabel: string;\n\tariaLabel?: string;\n\ticonSvg?: string;\n\tonClick: () => void;\n}\n\n/**\n * Alignment corner for the initial shell position.\n * The shell is offset by `initialMargin` (default 16 px) from the chosen corner.\n */\nexport type ToolWindowShellAlign =\n\t| \"center\"\n\t| \"top-left\"\n\t| \"top-right\"\n\t| \"bottom-left\"\n\t| \"bottom-right\";\n\nexport interface ToolWindowShellContentConfig {\n\t/** Vertical overflow behavior for the hosted content pane. Defaults to \"hidden\". */\n\toverflowY?: \"hidden\" | \"auto\";\n\t/**\n\t * Preserve the content area's configured minimum height when the shell shrinks\n\t * below `minHeight`, letting the content pane scroll instead of compressing\n\t * the hosted element.\n\t */\n\tpreserveMinHeight?: boolean;\n}\n\nexport interface ToolWindowShellConfig {\n\ttitle?: string;\n\tdraggable?: boolean;\n\tresizable?: boolean;\n\tcloseable?: boolean;\n\tinitialWidth?: number;\n\tinitialHeight?: number;\n\tminWidth?: number;\n\tminHeight?: number;\n\tmaxWidth?: number;\n\tmaxHeight?: number;\n\t/** Initial placement of the shell. Defaults to `'center'`. */\n\tinitialAlign?: ToolWindowShellAlign;\n\t/** Distance (px) from the viewport edge when using a corner align. Defaults to 16. */\n\tinitialMargin?: number;\n\tcontent?: ToolWindowShellContentConfig;\n\tactions?: ToolWindowShellAction[];\n}\n\nexport interface HostedToolContext {\n\ttoolId: string;\n\ttoolbarContext: ToolbarContext;\n\tshellConfig: ToolWindowShellConfig;\n}\n\nexport interface HostedToolSize {\n\twidth: number;\n\theight: number;\n}\n\nexport interface ToolProviderDescriptor {\n\tgetProviderId?: (config: ToolRuntimeConfig | undefined) => string;\n\tcreateProvider: (config: ToolRuntimeConfig | undefined) => ToolProviderApi;\n\tgetInitConfig?: (\n\t\tconfig: ToolRuntimeConfig | undefined,\n\t) => Record<string, unknown>;\n\tsanitizeConfig?: (config: ToolRuntimeConfig) => ToolRuntimeConfig;\n\tvalidateConfig?: (config: ToolRuntimeConfig) => ToolConfigDiagnostic[];\n\tgetAuthFetcher?: (\n\t\tconfig: ToolRuntimeConfig | undefined,\n\t) => (() => Promise<Record<string, unknown>>) | undefined;\n\tlazy?: boolean;\n}\n\nexport interface ToolToolbarRenderResult {\n\ttoolId: string;\n\telements?: ToolRenderElement[];\n\tbutton?: ToolToolbarButtonDefinition | null;\n\tsync?: () => void;\n\tsubscribeActive?: (callback: (active: boolean) => void) => () => void;\n}\n\nexport type ToolActivation = \"toolbar-toggle\" | \"selection-gateway\";\nexport type ToolSingletonScope = \"section\";\n\n/**\n * Tool registration interface\n */\nexport interface ToolRegistration {\n\t/** Unique tool identifier (e.g., 'calculator', 'textToSpeech') */\n\ttoolId: string;\n\n\t/** Human-readable name */\n\tname: string;\n\n\t/** Description of what the tool does */\n\tdescription: string;\n\n\t/** Icon identifier or SVG string */\n\ticon: string | ((context: ToolContext) => string);\n\n\t/** Which levels this tool supports */\n\tsupportedLevels: ToolLevel[];\n\n\t/**\n\t * Activation model for this tool.\n\t * - toolbar-toggle: rendered as a toolbar button (default)\n\t * - selection-gateway: rendered as a singleton selection-driven gateway\n\t */\n\tactivation?: ToolActivation;\n\n\t/**\n\t * Optional singleton scope for activation models that mount exactly one instance.\n\t */\n\tsingletonScope?: ToolSingletonScope;\n\n\t/**\n\t * PNP support IDs that enable this tool (optional)\n\t * Used by the tool policy engine to determine if a PNP support enables this tool.\n\t * Example: ['calculator', 'basic-calculator', 'scientific-calculator']\n\t */\n\tpnpSupportIds?: string[];\n\t/**\n\t * Optional provider registration metadata.\n\t * When present, ToolkitCoordinator can register provider(s) generically\n\t * without hardcoded tool-specific branches.\n\t */\n\tprovider?: ToolProviderDescriptor;\n\t/**\n\t * Optional shell-host lifecycle hooks for hosted (floating) tools.\n\t */\n\tonHostedMount?: (\n\t\telement: HTMLElement,\n\t\tcontext: HostedToolContext,\n\t) => void | Promise<void>;\n\tonHostedResize?: (\n\t\tsize: HostedToolSize,\n\t\telement: HTMLElement,\n\t\tcontext: HostedToolContext,\n\t) => void | Promise<void>;\n\tonHostedUnmount?: (\n\t\telement: HTMLElement,\n\t\tcontext: HostedToolContext,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Pass 2: Tool decides if it's relevant in this context\n\t * Called ONLY if orchestrator has already allowed the tool (Pass 1)\n\t *\n\t * @param context - Rich context about where tool is being evaluated\n\t * @returns true if tool should be visible, false to hide\n\t */\n\tisVisibleInContext(context: ToolContext): boolean;\n\n\t/** Required toolbar-first render contract. */\n\trenderToolbar(\n\t\tcontext: ToolContext,\n\t\ttoolbarContext: ToolbarContext,\n\t): ToolToolbarRenderResult | null;\n}\n\nconst VALID_TOOL_LEVELS: ToolLevel[] = [\n\t\"assessment\",\n\t\"section\",\n\t\"item\",\n\t\"passage\",\n\t\"rubric\",\n\t\"element\",\n];\n\nfunction assertNonEmptyString(\n\tvalue: unknown,\n\tfieldName: string,\n): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration: \"${fieldName}\" must be a non-empty string.`,\n\t\t);\n\t}\n}\n\n// Defence-in-depth: reject obvious XSS payloads in tool-registered icon\n// markup at registration time. Runtime rendering still runs each icon\n// through DOMPurify (see `ToolIcon.svelte`), but surfacing the problem\n// early produces a clearer error for tool authors than \"the icon silently\n// disappeared after sanitization\".\nconst SCRIPTABLE_ICON_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [\n\t{ pattern: /<script\\b/i, reason: \"contains a <script> tag\" },\n\t{\n\t\tpattern: /\\son[a-z]+\\s*=/i,\n\t\treason: \"contains an inline event handler (on*=) attribute\",\n\t},\n\t{ pattern: /javascript:/i, reason: \"contains a javascript: URL\" },\n\t{\n\t\tpattern: /<foreignObject\\b/i,\n\t\treason: \"contains a <foreignObject> element\",\n\t},\n];\n\nfunction assertIconStringIsSafe(\n\ttoolId: string,\n\ticon: string,\n\tfieldName: string,\n): void {\n\tconst trimmed = icon.trimStart();\n\tconst looksLikeSvg = trimmed.toLowerCase().startsWith(\"<svg\");\n\tconst looksLikeUrl = /^https?:/i.test(trimmed);\n\tconst looksLikeDataUrl = /^data:/i.test(trimmed);\n\tif (looksLikeDataUrl) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${toolId}\": \"${fieldName}\" may not be a data: URL.`,\n\t\t);\n\t}\n\tif (!looksLikeSvg && !looksLikeUrl) return;\n\tfor (const { pattern, reason } of SCRIPTABLE_ICON_PATTERNS) {\n\t\tif (pattern.test(icon)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid tool registration \"${toolId}\": \"${fieldName}\" ${reason}. Inline SVG icons must not include scriptable content.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction assertToolRegistrationShape(registration: ToolRegistration): void {\n\tassertNonEmptyString(registration.toolId, \"toolId\");\n\tassertNonEmptyString(registration.name, \"name\");\n\tassertNonEmptyString(registration.description, \"description\");\n\n\tif (\n\t\ttypeof registration.icon !== \"string\" &&\n\t\ttypeof registration.icon !== \"function\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"icon\" must be a string or function.`,\n\t\t);\n\t}\n\tif (typeof registration.icon === \"string\") {\n\t\tassertIconStringIsSafe(registration.toolId, registration.icon, \"icon\");\n\t}\n\tif (\n\t\t!Array.isArray(registration.supportedLevels) ||\n\t\tregistration.supportedLevels.length === 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"supportedLevels\" must be a non-empty array.`,\n\t\t);\n\t}\n\tconst invalidLevel = registration.supportedLevels.find(\n\t\t(level) => !VALID_TOOL_LEVELS.includes(level),\n\t);\n\tif (invalidLevel) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": unsupported level \"${invalidLevel}\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.activation !== undefined &&\n\t\tregistration.activation !== \"toolbar-toggle\" &&\n\t\tregistration.activation !== \"selection-gateway\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": unsupported activation \"${String(registration.activation)}\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.singletonScope !== undefined &&\n\t\tregistration.singletonScope !== \"section\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": unsupported singletonScope \"${String(registration.singletonScope)}\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.activation === \"selection-gateway\" &&\n\t\tregistration.singletonScope !== \"section\"\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": selection-gateway tools must declare singletonScope \"section\".`,\n\t\t);\n\t}\n\tif (\n\t\tregistration.pnpSupportIds !== undefined &&\n\t\t(!Array.isArray(registration.pnpSupportIds) ||\n\t\t\tregistration.pnpSupportIds.some(\n\t\t\t\t(pnpId) => typeof pnpId !== \"string\" || pnpId.trim().length === 0,\n\t\t\t))\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"pnpSupportIds\" must be an array of non-empty strings.`,\n\t\t);\n\t}\n\tif (typeof registration.isVisibleInContext !== \"function\") {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"isVisibleInContext\" must be a function.`,\n\t\t);\n\t}\n\tif (typeof registration.renderToolbar !== \"function\") {\n\t\tthrow new Error(\n\t\t\t`Invalid tool registration \"${registration.toolId}\": \"renderToolbar\" must be a function.`,\n\t\t);\n\t}\n}\n\n/**\n * Tool Registry\n *\n * Manages tool registrations and provides query/lookup functionality\n */\nexport class ToolRegistry {\n\tprivate tools = new Map<string, ToolRegistration>();\n\tprivate pnpIndex = new Map<string, Set<string>>(); // pnpSupportId → Set<toolId>\n\tprivate componentOverrides: ToolComponentOverrides = {};\n\tprivate moduleLoaders = new Map<string, ToolModuleLoader>();\n\tprivate loadedToolModules = new Set<string>();\n\tprivate moduleLoadPromises = new Map<string, Promise<void>>();\n\n\t/**\n\t * Normalize a single tool alias to canonical toolId.\n\t */\n\tnormalizeToolId(toolId: string): string {\n\t\treturn normalizeToolAlias(toolId);\n\t}\n\n\t/**\n\t * Normalize a list of tool aliases to canonical toolIds.\n\t */\n\tnormalizeToolIds(toolIds: string[]): string[] {\n\t\treturn toolIds.map((toolId) => this.normalizeToolId(toolId));\n\t}\n\n\t/**\n\t * Register a tool\n\t *\n\t * @param registration - Tool registration\n\t * @throws Error if toolId is already registered\n\t */\n\tregister(registration: ToolRegistration): void {\n\t\tassertToolRegistrationShape(registration);\n\t\tif (this.tools.has(registration.toolId)) {\n\t\t\tthrow new Error(`Tool '${registration.toolId}' is already registered`);\n\t\t}\n\n\t\tthis.tools.set(registration.toolId, registration);\n\n\t\t// Index PNP support IDs\n\t\tif (registration.pnpSupportIds) {\n\t\t\tfor (const pnpId of registration.pnpSupportIds) {\n\t\t\t\tif (!this.pnpIndex.has(pnpId)) {\n\t\t\t\t\tthis.pnpIndex.set(pnpId, new Set());\n\t\t\t\t}\n\t\t\t\tthis.pnpIndex.get(pnpId)!.add(registration.toolId);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Override an existing tool registration\n\t *\n\t * @param registration - New tool registration (must have existing toolId)\n\t */\n\toverride(registration: ToolRegistration): void {\n\t\tassertToolRegistrationShape(registration);\n\t\tif (!this.tools.has(registration.toolId)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot override non-existent tool '${registration.toolId}'`,\n\t\t\t);\n\t\t}\n\n\t\t// Remove old PNP index entries\n\t\tconst oldReg = this.tools.get(registration.toolId)!;\n\t\tif (oldReg.pnpSupportIds) {\n\t\t\tfor (const pnpId of oldReg.pnpSupportIds) {\n\t\t\t\tthis.pnpIndex.get(pnpId)?.delete(registration.toolId);\n\t\t\t}\n\t\t}\n\n\t\t// Add new registration\n\t\tthis.tools.set(registration.toolId, registration);\n\n\t\t// Re-index PNP support IDs\n\t\tif (registration.pnpSupportIds) {\n\t\t\tfor (const pnpId of registration.pnpSupportIds) {\n\t\t\t\tif (!this.pnpIndex.has(pnpId)) {\n\t\t\t\t\tthis.pnpIndex.set(pnpId, new Set());\n\t\t\t\t}\n\t\t\t\tthis.pnpIndex.get(pnpId)!.add(registration.toolId);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Unregister a tool\n\t *\n\t * @param toolId - Tool ID to remove\n\t */\n\tunregister(toolId: string): void {\n\t\tconst reg = this.tools.get(toolId);\n\t\tif (!reg) return;\n\n\t\t// Remove PNP index entries\n\t\tif (reg.pnpSupportIds) {\n\t\t\tfor (const pnpId of reg.pnpSupportIds) {\n\t\t\t\tthis.pnpIndex.get(pnpId)?.delete(toolId);\n\t\t\t}\n\t\t}\n\n\t\tthis.tools.delete(toolId);\n\t}\n\n\t/**\n\t * Get a tool registration by ID\n\t *\n\t * @param toolId - Tool ID\n\t * @returns Tool registration or undefined\n\t */\n\tget(toolId: string): ToolRegistration | undefined {\n\t\treturn this.tools.get(toolId);\n\t}\n\n\t/**\n\t * Check if a tool is registered\n\t *\n\t * @param toolId - Tool ID\n\t * @returns true if registered\n\t */\n\thas(toolId: string): boolean {\n\t\treturn this.tools.has(toolId);\n\t}\n\n\t/**\n\t * Get all registered tool IDs\n\t *\n\t * @returns Array of tool IDs\n\t */\n\tgetAllToolIds(): string[] {\n\t\treturn Array.from(this.tools.keys());\n\t}\n\n\t/**\n\t * Get all tool registrations\n\t *\n\t * @returns Array of tool registrations\n\t */\n\tgetAllTools(): ToolRegistration[] {\n\t\treturn Array.from(this.tools.values());\n\t}\n\n\t/**\n\t * Find tool IDs that support a given PNP support ID\n\t *\n\t * @param pnpSupportId - PNP support ID (e.g., 'calculator')\n\t * @returns Set of tool IDs that support this PNP ID\n\t */\n\tgetToolsByPNPSupport(pnpSupportId: string): Set<string> {\n\t\treturn this.pnpIndex.get(pnpSupportId) || new Set();\n\t}\n\n\t/**\n\t * Get tools that support a specific level\n\t *\n\t * @param level - Tool level (assessment, section, item, passage, element)\n\t * @returns Array of tool registrations that support this level\n\t */\n\tgetToolsByLevel(level: ToolLevel): ToolRegistration[] {\n\t\treturn this.getAllTools().filter((tool) =>\n\t\t\ttool.supportedLevels.includes(level),\n\t\t);\n\t}\n\n\t/**\n\t * Resolve tool activation, defaulting to toolbar-toggle.\n\t */\n\tgetToolActivation(toolId: string): ToolActivation {\n\t\treturn this.get(toolId)?.activation || \"toolbar-toggle\";\n\t}\n\n\t/**\n\t * Resolve singleton scope for a tool when present.\n\t */\n\tgetToolSingletonScope(toolId: string): ToolSingletonScope | null {\n\t\treturn this.get(toolId)?.singletonScope || null;\n\t}\n\n\t/**\n\t * Filter tool IDs by activation type.\n\t */\n\tfilterToolIdsByActivation(\n\t\ttoolIds: string[],\n\t\tactivation: ToolActivation,\n\t): string[] {\n\t\treturn toolIds.filter(\n\t\t\t(toolId) => this.getToolActivation(toolId) === activation,\n\t\t);\n\t}\n\n\t/**\n\t * Filter tools by visibility in a given context\n\t *\n\t * Pass 2 of the two-pass model: Given a list of allowed tool IDs (from Pass 1),\n\t * ask each tool if it's relevant in this context.\n\t *\n\t * @param allowedToolIds - Tool IDs that passed Pass 1 (orchestrator approval)\n\t * @param context - Context to evaluate\n\t * @returns Array of visible tool registrations\n\t */\n\tfilterVisibleInContext(\n\t\tallowedToolIds: string[],\n\t\tcontext: ToolContext,\n\t): ToolRegistration[] {\n\t\tconst visible: ToolRegistration[] = [];\n\n\t\tfor (const toolId of allowedToolIds) {\n\t\t\tconst tool = this.get(toolId);\n\t\t\tif (!tool) {\n\t\t\t\tconsole.warn(`Tool '${toolId}' is allowed but not registered`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check if tool supports this level\n\t\t\tif (!tool.supportedLevels.includes(context.level)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Pass 2: Ask tool if it's relevant\n\t\t\ttry {\n\t\t\t\tif (tool.isVisibleInContext(context)) {\n\t\t\t\t\tvisible.push(tool);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Error evaluating visibility for tool '${toolId}':`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn visible;\n\t}\n\n\t/**\n\t * Get tool metadata for building UIs\n\t * Useful for building PNP configuration interfaces\n\t *\n\t * @returns Array of tool metadata (id, name, description, pnpSupportIds)\n\t */\n\tgetToolMetadata(): Array<{\n\t\ttoolId: string;\n\t\tname: string;\n\t\tdescription: string;\n\t\tpnpSupportIds: string[];\n\t\tsupportedLevels: ToolLevel[];\n\t\tactivation: ToolActivation;\n\t\tsingletonScope: ToolSingletonScope | null;\n\t}> {\n\t\treturn this.getAllTools().map((tool) => ({\n\t\t\ttoolId: tool.toolId,\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tpnpSupportIds: tool.pnpSupportIds || [],\n\t\t\tsupportedLevels: tool.supportedLevels,\n\t\t\tactivation: tool.activation || \"toolbar-toggle\",\n\t\t\tsingletonScope: tool.singletonScope || null,\n\t\t}));\n\t}\n\n\t/**\n\t * Generate PNP support IDs from enabled tools\n\t * Useful for creating PNP profiles\n\t *\n\t * @param enabledToolIds - Tool IDs to enable\n\t * @returns Array of unique PNP support IDs\n\t */\n\tgeneratePNPSupportsFromTools(enabledToolIds: string[]): string[] {\n\t\tconst pnpSupports = new Set<string>();\n\n\t\tfor (const toolId of enabledToolIds) {\n\t\t\tconst tool = this.get(toolId);\n\t\t\tif (tool?.pnpSupportIds) {\n\t\t\t\tfor (const pnpId of tool.pnpSupportIds) {\n\t\t\t\t\tpnpSupports.add(pnpId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Array.from(pnpSupports);\n\t}\n\n\t/**\n\t * Clear all registrations (useful for testing)\n\t */\n\tclear(): void {\n\t\tthis.tools.clear();\n\t\tthis.pnpIndex.clear();\n\t}\n\n\t/**\n\t * Configure global component overrides used by tool instance creation.\n\t */\n\tsetComponentOverrides(overrides: ToolComponentOverrides): void {\n\t\tthis.componentOverrides = overrides;\n\t}\n\n\t/**\n\t * Register lazy module loaders by toolId.\n\t * Toolbars call ensureToolModuleLoaded(toolId) before instance creation.\n\t */\n\tsetToolModuleLoaders(\n\t\tloaders: Partial<Record<string, ToolModuleLoader>>,\n\t): void {\n\t\tfor (const [toolId, loader] of Object.entries(loaders)) {\n\t\t\tif (!loader) continue;\n\t\t\tassertNonEmptyString(toolId, \"tool module loader id\");\n\t\t\tif (typeof loader !== \"function\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid tool module loader for \"${toolId}\": expected a function.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.moduleLoaders.set(toolId, loader);\n\t\t}\n\t}\n\n\t/**\n\t * Ensure tool module side-effects are loaded exactly once.\n\t * Safe to call repeatedly; concurrent callers share the same promise.\n\t */\n\tasync ensureToolModuleLoaded(toolId: string): Promise<void> {\n\t\tif (this.loadedToolModules.has(toolId)) return;\n\n\t\tconst existingPromise = this.moduleLoadPromises.get(toolId);\n\t\tif (existingPromise) {\n\t\t\tawait existingPromise;\n\t\t\treturn;\n\t\t}\n\n\t\tconst loader = this.moduleLoaders.get(toolId);\n\t\tif (!loader) return;\n\n\t\tconst loadPromise = (async () => {\n\t\t\tawait loader();\n\t\t\tthis.loadedToolModules.add(toolId);\n\t\t})();\n\n\t\tthis.moduleLoadPromises.set(toolId, loadPromise);\n\t\ttry {\n\t\t\tawait loadPromise;\n\t\t} finally {\n\t\t\tthis.moduleLoadPromises.delete(toolId);\n\t\t}\n\t}\n\n\t/**\n\t * Ensure a set of tool modules are loaded.\n\t */\n\tasync ensureToolModulesLoaded(toolIds: string[]): Promise<void> {\n\t\tawait Promise.all(\n\t\t\ttoolIds.map((toolId) => this.ensureToolModuleLoaded(toolId)),\n\t\t);\n\t}\n\n\t/**\n\t * Whether a tool module has already been loaded.\n\t */\n\tisToolModuleLoaded(toolId: string): boolean {\n\t\treturn this.loadedToolModules.has(toolId);\n\t}\n\n\t/**\n\t * Render a tool for toolbar use with component overrides attached.\n\t */\n\trenderForToolbar(\n\t\ttoolId: string,\n\t\tcontext: ToolContext,\n\t\ttoolbarContext: ToolbarContext,\n\t): ToolToolbarRenderResult | null {\n\t\tconst tool = this.get(toolId);\n\t\tif (!tool) {\n\t\t\tthrow new Error(`Tool '${toolId}' is not registered`);\n\t\t}\n\n\t\tconst mergedContext: ToolbarContext = {\n\t\t\t...toolbarContext,\n\t\t\tcomponentOverrides: {\n\t\t\t\t...(this.componentOverrides || {}),\n\t\t\t\t...(toolbarContext.componentOverrides || {}),\n\t\t\t},\n\t\t};\n\n\t\treturn tool.renderToolbar(context, mergedContext);\n\t}\n}\n"]}
|
|
@@ -13,12 +13,14 @@ export interface TTSSpeedOptionConfig {
|
|
|
13
13
|
rate: number;
|
|
14
14
|
label?: string;
|
|
15
15
|
ariaLabel?: string;
|
|
16
|
+
default?: boolean;
|
|
16
17
|
}
|
|
17
18
|
export type TTSSpeedOption = number | TTSSpeedOptionConfig;
|
|
18
19
|
export interface NormalizedTTSSpeedOption {
|
|
19
20
|
rate: number;
|
|
20
21
|
label: string;
|
|
21
22
|
ariaLabel: string;
|
|
23
|
+
isDefault: boolean;
|
|
22
24
|
}
|
|
23
25
|
export interface TTSRuntimeSettings {
|
|
24
26
|
backend?: "browser" | "polly" | "google" | "server";
|
|
@@ -49,6 +51,11 @@ export interface TTSRuntimeSettings {
|
|
|
49
51
|
* - Object entries can customize button text while preserving numeric rates.
|
|
50
52
|
*/
|
|
51
53
|
speedOptions?: TTSSpeedOption[];
|
|
54
|
+
/**
|
|
55
|
+
* Show a rendered speed group even when there is only one visible option.
|
|
56
|
+
* Defaults to false because a one-option radio group has no meaningful choice.
|
|
57
|
+
*/
|
|
58
|
+
showSingleSpeedOption?: boolean;
|
|
52
59
|
layoutMode?: TTSLayoutMode;
|
|
53
60
|
/**
|
|
54
61
|
* Per-token highlighting of math expressions.
|
|
@@ -67,7 +74,7 @@ export interface TTSRuntimeSettings {
|
|
|
67
74
|
mathSpeech?: SREMathSpeechOptions;
|
|
68
75
|
}
|
|
69
76
|
export declare const normalizeTTSLayoutMode: (value: unknown, fallback?: TTSLayoutMode) => TTSLayoutMode;
|
|
70
|
-
/**
|
|
77
|
+
/** Legacy numeric helper defaults. Rendered controls add visible Normal separately. */
|
|
71
78
|
export declare const DEFAULT_TTS_SPEED_OPTIONS: readonly number[];
|
|
72
79
|
export declare const normalizeTTSSpeedOptionConfigs: (value: unknown) => TTSSpeedOption[];
|
|
73
80
|
/**
|