@pie-players/pie-assessment-toolkit 0.2.0
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 +520 -0
- package/dist/attempt/TestSession.d.ts +90 -0
- package/dist/attempt/TestSession.d.ts.map +1 -0
- package/dist/attempt/TestSession.js +174 -0
- package/dist/attempt/TestSession.js.map +1 -0
- package/dist/core/TypedEventBus.d.ts +48 -0
- package/dist/core/TypedEventBus.d.ts.map +1 -0
- package/dist/core/TypedEventBus.js +63 -0
- package/dist/core/TypedEventBus.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/item-loader.d.ts +45 -0
- package/dist/item-loader.d.ts.map +1 -0
- package/dist/item-loader.js +62 -0
- package/dist/item-loader.js.map +1 -0
- package/dist/player/AssessmentPlayer.d.ts +388 -0
- package/dist/player/AssessmentPlayer.d.ts.map +1 -0
- package/dist/player/AssessmentPlayer.js +965 -0
- package/dist/player/AssessmentPlayer.js.map +1 -0
- package/dist/player/index.d.ts +17 -0
- package/dist/player/index.d.ts.map +1 -0
- package/dist/player/index.js +15 -0
- package/dist/player/index.js.map +1 -0
- package/dist/player/navigation-types.d.ts +63 -0
- package/dist/player/navigation-types.d.ts.map +1 -0
- package/dist/player/navigation-types.js +7 -0
- package/dist/player/navigation-types.js.map +1 -0
- package/dist/player/qti-navigation.d.ts +29 -0
- package/dist/player/qti-navigation.d.ts.map +1 -0
- package/dist/player/qti-navigation.js +160 -0
- package/dist/player/qti-navigation.js.map +1 -0
- package/dist/reference-layout/index.d.ts +19 -0
- package/dist/reference-layout/index.d.ts.map +1 -0
- package/dist/reference-layout/index.js +20 -0
- package/dist/reference-layout/index.js.map +1 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts +141 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts.map +1 -0
- package/dist/services/AccessibilityCatalogResolver.js +249 -0
- package/dist/services/AccessibilityCatalogResolver.js.map +1 -0
- package/dist/services/AssessmentAuthoringService.d.ts +60 -0
- package/dist/services/AssessmentAuthoringService.d.ts.map +1 -0
- package/dist/services/AssessmentAuthoringService.js +183 -0
- package/dist/services/AssessmentAuthoringService.js.map +1 -0
- package/dist/services/ContextVariableStore.d.ts +114 -0
- package/dist/services/ContextVariableStore.d.ts.map +1 -0
- package/dist/services/ContextVariableStore.js +207 -0
- package/dist/services/ContextVariableStore.js.map +1 -0
- package/dist/services/ElementToolStateStore.d.ts +125 -0
- package/dist/services/ElementToolStateStore.d.ts.map +1 -0
- package/dist/services/ElementToolStateStore.js +200 -0
- package/dist/services/ElementToolStateStore.js.map +1 -0
- package/dist/services/HighlightCoordinator.d.ts +179 -0
- package/dist/services/HighlightCoordinator.d.ts.map +1 -0
- package/dist/services/HighlightCoordinator.js +446 -0
- package/dist/services/HighlightCoordinator.js.map +1 -0
- package/dist/services/I18nService.d.ts +121 -0
- package/dist/services/I18nService.d.ts.map +1 -0
- package/dist/services/I18nService.js +276 -0
- package/dist/services/I18nService.js.map +1 -0
- package/dist/services/PNPMapper.d.ts +71 -0
- package/dist/services/PNPMapper.d.ts.map +1 -0
- package/dist/services/PNPMapper.js +98 -0
- package/dist/services/PNPMapper.js.map +1 -0
- package/dist/services/PNPToolResolver.d.ts +127 -0
- package/dist/services/PNPToolResolver.d.ts.map +1 -0
- package/dist/services/PNPToolResolver.js +222 -0
- package/dist/services/PNPToolResolver.js.map +1 -0
- package/dist/services/SSMLExtractor.d.ts +61 -0
- package/dist/services/SSMLExtractor.d.ts.map +1 -0
- package/dist/services/SSMLExtractor.js +181 -0
- package/dist/services/SSMLExtractor.js.map +1 -0
- package/dist/services/TTSService.d.ts +162 -0
- package/dist/services/TTSService.d.ts.map +1 -0
- package/dist/services/TTSService.js +465 -0
- package/dist/services/TTSService.js.map +1 -0
- package/dist/services/ThemeProvider.d.ts +95 -0
- package/dist/services/ThemeProvider.d.ts.map +1 -0
- package/dist/services/ThemeProvider.js +299 -0
- package/dist/services/ThemeProvider.js.map +1 -0
- package/dist/services/ToolConfigResolver.d.ts +162 -0
- package/dist/services/ToolConfigResolver.d.ts.map +1 -0
- package/dist/services/ToolConfigResolver.js +230 -0
- package/dist/services/ToolConfigResolver.js.map +1 -0
- package/dist/services/ToolCoordinator.d.ts +137 -0
- package/dist/services/ToolCoordinator.d.ts.map +1 -0
- package/dist/services/ToolCoordinator.js +318 -0
- package/dist/services/ToolCoordinator.js.map +1 -0
- package/dist/services/ToolkitCoordinator.d.ts +188 -0
- package/dist/services/ToolkitCoordinator.d.ts.map +1 -0
- package/dist/services/ToolkitCoordinator.js +252 -0
- package/dist/services/ToolkitCoordinator.js.map +1 -0
- package/dist/services/interfaces.d.ts +391 -0
- package/dist/services/interfaces.d.ts.map +1 -0
- package/dist/services/interfaces.js +12 -0
- package/dist/services/interfaces.js.map +1 -0
- package/dist/services/tool-providers/DesmosToolProvider.d.ts +103 -0
- package/dist/services/tool-providers/DesmosToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/DesmosToolProvider.js +127 -0
- package/dist/services/tool-providers/DesmosToolProvider.js.map +1 -0
- package/dist/services/tool-providers/IToolProvider.d.ts +137 -0
- package/dist/services/tool-providers/IToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/IToolProvider.js +13 -0
- package/dist/services/tool-providers/IToolProvider.js.map +1 -0
- package/dist/services/tool-providers/TIToolProvider.d.ts +107 -0
- package/dist/services/tool-providers/TIToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/TIToolProvider.js +123 -0
- package/dist/services/tool-providers/TIToolProvider.js.map +1 -0
- package/dist/services/tool-providers/TTSToolProvider.d.ts +143 -0
- package/dist/services/tool-providers/TTSToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/TTSToolProvider.js +168 -0
- package/dist/services/tool-providers/TTSToolProvider.js.map +1 -0
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +165 -0
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts.map +1 -0
- package/dist/services/tool-providers/ToolProviderRegistry.js +240 -0
- package/dist/services/tool-providers/ToolProviderRegistry.js.map +1 -0
- package/dist/services/tool-providers/index.d.ts +18 -0
- package/dist/services/tool-providers/index.d.ts.map +1 -0
- package/dist/services/tool-providers/index.js +15 -0
- package/dist/services/tool-providers/index.js.map +1 -0
- package/dist/services/tts/browser-provider.d.ts +24 -0
- package/dist/services/tts/browser-provider.d.ts.map +1 -0
- package/dist/services/tts/browser-provider.js +177 -0
- package/dist/services/tts/browser-provider.js.map +1 -0
- package/dist/services/tts/provider-interface.d.ts +131 -0
- package/dist/services/tts/provider-interface.d.ts.map +1 -0
- package/dist/services/tts/provider-interface.js +10 -0
- package/dist/services/tts/provider-interface.js.map +1 -0
- package/dist/tools/calculators/desmos-provider.d.ts +54 -0
- package/dist/tools/calculators/desmos-provider.d.ts.map +1 -0
- package/dist/tools/calculators/desmos-provider.js +384 -0
- package/dist/tools/calculators/desmos-provider.js.map +1 -0
- package/dist/tools/calculators/mathjs-provider.d.ts +50 -0
- package/dist/tools/calculators/mathjs-provider.d.ts.map +1 -0
- package/dist/tools/calculators/mathjs-provider.js +660 -0
- package/dist/tools/calculators/mathjs-provider.js.map +1 -0
- package/dist/tools/calculators/ti-provider.d.ts +122 -0
- package/dist/tools/calculators/ti-provider.d.ts.map +1 -0
- package/dist/tools/calculators/ti-provider.js +587 -0
- package/dist/tools/calculators/ti-provider.js.map +1 -0
- package/dist/tools/client.d.ts +17 -0
- package/dist/tools/client.d.ts.map +1 -0
- package/dist/tools/client.js +26 -0
- package/dist/tools/client.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +10 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/library-loader.d.ts +63 -0
- package/dist/tools/library-loader.d.ts.map +1 -0
- package/dist/tools/library-loader.js +292 -0
- package/dist/tools/library-loader.js.map +1 -0
- package/dist/tools/response-discovery.d.ts +72 -0
- package/dist/tools/response-discovery.d.ts.map +1 -0
- package/dist/tools/response-discovery.js +183 -0
- package/dist/tools/response-discovery.js.map +1 -0
- package/dist/tools/tool-coordinator.d.ts +76 -0
- package/dist/tools/tool-coordinator.d.ts.map +1 -0
- package/dist/tools/tool-coordinator.js +197 -0
- package/dist/tools/tool-coordinator.js.map +1 -0
- package/dist/tools/types.d.ts +427 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +13 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/variant-resolver.d.ts +48 -0
- package/dist/tools/variant-resolver.d.ts.map +1 -0
- package/dist/tools/variant-resolver.js +214 -0
- package/dist/tools/variant-resolver.js.map +1 -0
- package/dist/types/events.d.ts +157 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +11 -0
- package/dist/types/events.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +11 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +71 -0
- package/src/README.md +626 -0
- package/src/components/QuestionToolBar.svelte +406 -0
- package/src/player/AssessmentLayout.svelte +68 -0
- package/src/player/README.md +154 -0
- package/src/reference-layout/README.md +135 -0
- package/src/reference-layout/ReferenceLayout.svelte +209 -0
- package/src/reference-layout/components/AssessmentContent.svelte +259 -0
- package/src/reference-layout/components/AssessmentFooter.svelte +89 -0
- package/src/reference-layout/components/AssessmentHeader.svelte +250 -0
- package/src/reference-layout/components/AssessmentNavigation.svelte +134 -0
- package/src/reference-layout/components/AssessmentToolsBar.svelte +176 -0
- package/src/reference-layout/components/ItemPanel.svelte +200 -0
- package/src/reference-layout/components/NotesPanel.svelte +179 -0
- package/src/reference-layout/components/PassagePanel.svelte +76 -0
- package/src/tools/README.md +616 -0
- package/src/tools/calculators/README.md +395 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToolConfigResolver
|
|
3
|
+
*
|
|
4
|
+
* Implements 3-tier hierarchy for tool configuration:
|
|
5
|
+
* Item requirements > Roster allowances > Student accommodations
|
|
6
|
+
*
|
|
7
|
+
* Ensures IEP/504 compliance by properly handling accommodation requirements
|
|
8
|
+
* while respecting item-level and test-level restrictions.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - 3-tier configuration hierarchy
|
|
12
|
+
* - IEP/504 accommodation support
|
|
13
|
+
* - Item-specific tool requirements
|
|
14
|
+
* - Test-level tool restrictions
|
|
15
|
+
* - Type-safe configuration
|
|
16
|
+
*
|
|
17
|
+
* Part of PIE Assessment Toolkit.
|
|
18
|
+
*/
|
|
19
|
+
export class ToolConfigResolver {
|
|
20
|
+
/**
|
|
21
|
+
* Resolve configuration for a specific tool
|
|
22
|
+
*
|
|
23
|
+
* Hierarchy (highest to lowest priority):
|
|
24
|
+
* 1. Item level: Item requires scientific calculator → must provide
|
|
25
|
+
* 2. Roster level: Test blocks dictionary → blocked regardless of accommodation
|
|
26
|
+
* 3. Student level: IEP requires TTS → enabled unless blocked above
|
|
27
|
+
*
|
|
28
|
+
* @param toolId Tool identifier
|
|
29
|
+
* @param itemConfig Item-level tool configuration
|
|
30
|
+
* @param rosterConfig Roster-level tool allowances
|
|
31
|
+
* @param studentProfile Student accommodation profile
|
|
32
|
+
* @returns Resolved configuration or null if tool not available
|
|
33
|
+
*/
|
|
34
|
+
resolveTool(toolId, itemConfig, rosterConfig, studentProfile) {
|
|
35
|
+
// Check item level (highest priority)
|
|
36
|
+
const itemTool = itemConfig?.[toolId];
|
|
37
|
+
if (itemTool) {
|
|
38
|
+
// Item explicitly configures this tool
|
|
39
|
+
return {
|
|
40
|
+
enabled: true,
|
|
41
|
+
type: itemTool.type,
|
|
42
|
+
required: itemTool.required ?? false,
|
|
43
|
+
settings: itemTool.settings,
|
|
44
|
+
source: "item",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Check roster level (blocks take precedence)
|
|
48
|
+
const rosterAllowance = rosterConfig?.[toolId];
|
|
49
|
+
if (rosterAllowance === "0") {
|
|
50
|
+
// Roster explicitly blocks this tool
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (rosterAllowance === "1") {
|
|
54
|
+
// Roster allows this tool
|
|
55
|
+
return {
|
|
56
|
+
enabled: true,
|
|
57
|
+
required: false,
|
|
58
|
+
source: "roster",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Check student level (lowest priority)
|
|
62
|
+
const hasAccommodation = studentProfile?.accommodations.includes(toolId) ?? false;
|
|
63
|
+
if (hasAccommodation) {
|
|
64
|
+
// Student has accommodation for this tool
|
|
65
|
+
return {
|
|
66
|
+
enabled: true,
|
|
67
|
+
required: false,
|
|
68
|
+
source: "student",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Tool not configured at any level
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Resolve all tools from configuration
|
|
76
|
+
*
|
|
77
|
+
* @param input Configuration input
|
|
78
|
+
* @returns Map of tool ID to resolved configuration
|
|
79
|
+
*/
|
|
80
|
+
resolveAll(input) {
|
|
81
|
+
const resolved = new Map();
|
|
82
|
+
// Collect all tool IDs from all levels
|
|
83
|
+
const allToolIds = new Set();
|
|
84
|
+
// From item config
|
|
85
|
+
if (input.itemConfig) {
|
|
86
|
+
Object.keys(input.itemConfig).forEach((id) => allToolIds.add(id));
|
|
87
|
+
}
|
|
88
|
+
// From roster config
|
|
89
|
+
if (input.rosterConfig) {
|
|
90
|
+
Object.keys(input.rosterConfig).forEach((id) => allToolIds.add(id));
|
|
91
|
+
}
|
|
92
|
+
// From student accommodations
|
|
93
|
+
if (input.studentProfile) {
|
|
94
|
+
input.studentProfile.accommodations.forEach((id) => allToolIds.add(id));
|
|
95
|
+
}
|
|
96
|
+
// Resolve each tool
|
|
97
|
+
for (const toolId of allToolIds) {
|
|
98
|
+
const config = this.resolveTool(toolId, input.itemConfig, input.rosterConfig, input.studentProfile);
|
|
99
|
+
if (config) {
|
|
100
|
+
resolved.set(toolId, config);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return resolved;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if a tool is enabled
|
|
107
|
+
*
|
|
108
|
+
* @param toolId Tool identifier
|
|
109
|
+
* @param input Configuration input
|
|
110
|
+
* @returns true if tool is enabled
|
|
111
|
+
*/
|
|
112
|
+
isToolEnabled(toolId, input) {
|
|
113
|
+
const config = this.resolveTool(toolId, input.itemConfig, input.rosterConfig, input.studentProfile);
|
|
114
|
+
return config?.enabled ?? false;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if a tool is required
|
|
118
|
+
*
|
|
119
|
+
* @param toolId Tool identifier
|
|
120
|
+
* @param input Configuration input
|
|
121
|
+
* @returns true if tool is required
|
|
122
|
+
*/
|
|
123
|
+
isToolRequired(toolId, input) {
|
|
124
|
+
const config = this.resolveTool(toolId, input.itemConfig, input.rosterConfig, input.studentProfile);
|
|
125
|
+
return config?.required ?? false;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get tool type (e.g., 'scientific' for calculator)
|
|
129
|
+
*
|
|
130
|
+
* @param toolId Tool identifier
|
|
131
|
+
* @param input Configuration input
|
|
132
|
+
* @returns Tool type or null
|
|
133
|
+
*/
|
|
134
|
+
getToolType(toolId, input) {
|
|
135
|
+
const config = this.resolveTool(toolId, input.itemConfig, input.rosterConfig, input.studentProfile);
|
|
136
|
+
return config?.type ?? null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get tool settings
|
|
140
|
+
*
|
|
141
|
+
* @param toolId Tool identifier
|
|
142
|
+
* @param input Configuration input
|
|
143
|
+
* @returns Tool settings or null
|
|
144
|
+
*/
|
|
145
|
+
getToolSettings(toolId, input) {
|
|
146
|
+
const config = this.resolveTool(toolId, input.itemConfig, input.rosterConfig, input.studentProfile);
|
|
147
|
+
return config?.settings ?? null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get list of all enabled tools
|
|
151
|
+
*
|
|
152
|
+
* @param input Configuration input
|
|
153
|
+
* @returns Array of enabled tool IDs
|
|
154
|
+
*/
|
|
155
|
+
getEnabledTools(input) {
|
|
156
|
+
const resolved = this.resolveAll(input);
|
|
157
|
+
return Array.from(resolved.entries())
|
|
158
|
+
.filter(([_, config]) => config.enabled)
|
|
159
|
+
.map(([toolId]) => toolId);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get list of required tools
|
|
163
|
+
*
|
|
164
|
+
* @param input Configuration input
|
|
165
|
+
* @returns Array of required tool IDs
|
|
166
|
+
*/
|
|
167
|
+
getRequiredTools(input) {
|
|
168
|
+
const resolved = this.resolveAll(input);
|
|
169
|
+
return Array.from(resolved.entries())
|
|
170
|
+
.filter(([_, config]) => config.required)
|
|
171
|
+
.map(([toolId]) => toolId);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Validate that all required tools are available
|
|
175
|
+
*
|
|
176
|
+
* @param availableTools Set of available tool IDs
|
|
177
|
+
* @param input Configuration input
|
|
178
|
+
* @returns Object with validation result
|
|
179
|
+
*/
|
|
180
|
+
validate(availableTools, input) {
|
|
181
|
+
const requiredTools = this.getRequiredTools(input);
|
|
182
|
+
const missingTools = requiredTools.filter((toolId) => !availableTools.has(toolId));
|
|
183
|
+
return {
|
|
184
|
+
valid: missingTools.length === 0,
|
|
185
|
+
missingTools,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Merge multiple roster configurations (for complex assessments)
|
|
190
|
+
*
|
|
191
|
+
* More restrictive settings win (blocked > allowed).
|
|
192
|
+
*
|
|
193
|
+
* @param configs Array of roster configurations
|
|
194
|
+
* @returns Merged configuration
|
|
195
|
+
*/
|
|
196
|
+
mergeRosterConfigs(...configs) {
|
|
197
|
+
const merged = {};
|
|
198
|
+
for (const config of configs) {
|
|
199
|
+
for (const [toolId, allowance] of Object.entries(config)) {
|
|
200
|
+
// If any config blocks the tool, it's blocked
|
|
201
|
+
if (allowance === "0") {
|
|
202
|
+
merged[toolId] = "0";
|
|
203
|
+
}
|
|
204
|
+
else if (!merged[toolId]) {
|
|
205
|
+
// If not already set, use this allowance
|
|
206
|
+
merged[toolId] = allowance;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return merged;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Merge multiple student accommodation profiles
|
|
214
|
+
*
|
|
215
|
+
* Union of all accommodations.
|
|
216
|
+
*
|
|
217
|
+
* @param profiles Array of student profiles
|
|
218
|
+
* @returns Merged profile
|
|
219
|
+
*/
|
|
220
|
+
mergeStudentProfiles(...profiles) {
|
|
221
|
+
const allAccommodations = new Set();
|
|
222
|
+
for (const profile of profiles) {
|
|
223
|
+
profile.accommodations.forEach((acc) => allAccommodations.add(acc));
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
accommodations: Array.from(allAccommodations),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=ToolConfigResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolConfigResolver.js","sourceRoot":"","sources":["../../src/services/ToolConfigResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToolCoordinator
|
|
3
|
+
*
|
|
4
|
+
* Manages z-index layering and visibility for floating tools.
|
|
5
|
+
* Prevents conflicts between calculator, ruler, protractor, etc.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Centralized z-index management with defined layers
|
|
9
|
+
* - Tool visibility state tracking
|
|
10
|
+
* - Bring-to-front on interaction
|
|
11
|
+
* - Framework-agnostic (works with any DOM element)
|
|
12
|
+
*
|
|
13
|
+
* Part of PIE Assessment Toolkit.
|
|
14
|
+
*/
|
|
15
|
+
import type { IToolCoordinator, ToolState } from "./interfaces";
|
|
16
|
+
/**
|
|
17
|
+
* Z-index layers for assessment components
|
|
18
|
+
*/
|
|
19
|
+
export declare enum ZIndexLayer {
|
|
20
|
+
BASE = 0,// PIE content, player chrome (0-999)
|
|
21
|
+
TOOL = 1000,// Non-modal tools (ruler, protractor) (1000-1999)
|
|
22
|
+
MODAL = 2000,// Modal tools (calculator, dictionary) (2000-2999)
|
|
23
|
+
CONTROL = 3000,// Drag handles, resize controls (3000-3999)
|
|
24
|
+
HIGHLIGHT = 4000
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Configuration for ToolCoordinator
|
|
28
|
+
* Currently empty but allows future extension without breaking changes
|
|
29
|
+
*/
|
|
30
|
+
export type ToolCoordinatorConfig = Record<string, never>;
|
|
31
|
+
export declare class ToolCoordinator implements IToolCoordinator {
|
|
32
|
+
private config;
|
|
33
|
+
private tools;
|
|
34
|
+
private layerCounters;
|
|
35
|
+
private listeners;
|
|
36
|
+
constructor(config?: ToolCoordinatorConfig);
|
|
37
|
+
/**
|
|
38
|
+
* Subscribe to tool state changes
|
|
39
|
+
* Returns unsubscribe function
|
|
40
|
+
*/
|
|
41
|
+
subscribe(listener: () => void): () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Notify all listeners of state change
|
|
44
|
+
*/
|
|
45
|
+
private notifyListeners;
|
|
46
|
+
/**
|
|
47
|
+
* Register a tool with the coordinator
|
|
48
|
+
*
|
|
49
|
+
* @param id Unique tool identifier
|
|
50
|
+
* @param name Display name
|
|
51
|
+
* @param element DOM element for the tool (optional for backward compatibility)
|
|
52
|
+
* @param layer Z-index layer (defaults to MODAL)
|
|
53
|
+
*/
|
|
54
|
+
registerTool(id: string, name: string, element?: HTMLElement, layer?: ZIndexLayer): void;
|
|
55
|
+
/**
|
|
56
|
+
* Unregister a tool
|
|
57
|
+
*
|
|
58
|
+
* @param id Tool identifier
|
|
59
|
+
*/
|
|
60
|
+
unregisterTool(id: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Show a tool
|
|
63
|
+
*
|
|
64
|
+
* @param id Tool identifier
|
|
65
|
+
*/
|
|
66
|
+
showTool(id: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* Hide a tool
|
|
69
|
+
*
|
|
70
|
+
* @param id Tool identifier
|
|
71
|
+
*/
|
|
72
|
+
hideTool(id: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Toggle tool visibility
|
|
75
|
+
*
|
|
76
|
+
* @param id Tool identifier
|
|
77
|
+
*/
|
|
78
|
+
toggleTool(id: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Check if tool is visible
|
|
81
|
+
*
|
|
82
|
+
* @param id Tool identifier
|
|
83
|
+
* @returns true if tool is visible
|
|
84
|
+
*/
|
|
85
|
+
isToolVisible(id: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Bring element to front of its layer
|
|
88
|
+
*
|
|
89
|
+
* @param element DOM element to bring forward
|
|
90
|
+
*/
|
|
91
|
+
bringToFront(element: HTMLElement): void;
|
|
92
|
+
/**
|
|
93
|
+
* Get all registered tool IDs
|
|
94
|
+
*/
|
|
95
|
+
getRegisteredTools(): string[];
|
|
96
|
+
/**
|
|
97
|
+
* Get tool element by ID
|
|
98
|
+
*/
|
|
99
|
+
getToolElement(id: string): HTMLElement | null;
|
|
100
|
+
/**
|
|
101
|
+
* Get next offset within a layer
|
|
102
|
+
*/
|
|
103
|
+
private getNextLayerOffset;
|
|
104
|
+
/**
|
|
105
|
+
* Get maximum z-index currently in use in a layer
|
|
106
|
+
*/
|
|
107
|
+
private getMaxZIndexInLayer;
|
|
108
|
+
/**
|
|
109
|
+
* Reset all tools to their base z-indices
|
|
110
|
+
*/
|
|
111
|
+
resetZIndices(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Update tool element reference (backward compatibility)
|
|
114
|
+
*
|
|
115
|
+
* @param id Tool identifier
|
|
116
|
+
* @param element New DOM element
|
|
117
|
+
*/
|
|
118
|
+
updateToolElement(id: string, element: HTMLElement): void;
|
|
119
|
+
/**
|
|
120
|
+
* Hide all tools (backward compatibility)
|
|
121
|
+
*/
|
|
122
|
+
hideAllTools(): void;
|
|
123
|
+
/**
|
|
124
|
+
* Get tool state (interface method)
|
|
125
|
+
*
|
|
126
|
+
* @param id Tool identifier
|
|
127
|
+
* @returns Tool state or undefined
|
|
128
|
+
*/
|
|
129
|
+
getToolState(id: string): ToolState | undefined;
|
|
130
|
+
/**
|
|
131
|
+
* Get all visible tools (interface method)
|
|
132
|
+
*
|
|
133
|
+
* @returns Array of visible tool states
|
|
134
|
+
*/
|
|
135
|
+
getVisibleTools(): ToolState[];
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=ToolCoordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/ToolCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIhE;;GAEG;AACH,oBAAY,WAAW;IACtB,IAAI,IAAI,CAAE,qCAAqC;IAC/C,IAAI,OAAO,CAAE,kDAAkD;IAC/D,KAAK,OAAO,CAAE,mDAAmD;IACjE,OAAO,OAAO,CAAE,4CAA4C;IAC5D,SAAS,OAAO;CAChB;AAeD;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE1D,qBAAa,eAAgB,YAAW,gBAAgB;IACvD,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,SAAS,CAAyB;gBAE9B,MAAM,GAAE,qBAA0B;IAU9C;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAO3C;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;;;;;;OAOG;IACH,YAAY,CACX,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,WAAW,EACrB,KAAK,GAAE,WAA+B,GACpC,IAAI;IA8CP;;;;OAIG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAYhC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAe1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAc1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAmB5B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAKlC;;;;OAIG;IACH,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAgBxC;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAI9B;;OAEG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAI9C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;OAEG;IACH,aAAa,IAAI,IAAI;IAQrB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IA6BzD;;OAEG;IACH,YAAY,IAAI,IAAI;IAOpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAa/C;;;;OAIG;IACH,eAAe,IAAI,SAAS,EAAE;CAW9B"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToolCoordinator
|
|
3
|
+
*
|
|
4
|
+
* Manages z-index layering and visibility for floating tools.
|
|
5
|
+
* Prevents conflicts between calculator, ruler, protractor, etc.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Centralized z-index management with defined layers
|
|
9
|
+
* - Tool visibility state tracking
|
|
10
|
+
* - Bring-to-front on interaction
|
|
11
|
+
* - Framework-agnostic (works with any DOM element)
|
|
12
|
+
*
|
|
13
|
+
* Part of PIE Assessment Toolkit.
|
|
14
|
+
*/
|
|
15
|
+
import { createLogger } from "../utils/logger";
|
|
16
|
+
const log = createLogger("ToolCoordinator");
|
|
17
|
+
/**
|
|
18
|
+
* Z-index layers for assessment components
|
|
19
|
+
*/
|
|
20
|
+
export var ZIndexLayer;
|
|
21
|
+
(function (ZIndexLayer) {
|
|
22
|
+
ZIndexLayer[ZIndexLayer["BASE"] = 0] = "BASE";
|
|
23
|
+
ZIndexLayer[ZIndexLayer["TOOL"] = 1000] = "TOOL";
|
|
24
|
+
ZIndexLayer[ZIndexLayer["MODAL"] = 2000] = "MODAL";
|
|
25
|
+
ZIndexLayer[ZIndexLayer["CONTROL"] = 3000] = "CONTROL";
|
|
26
|
+
ZIndexLayer[ZIndexLayer["HIGHLIGHT"] = 4000] = "HIGHLIGHT";
|
|
27
|
+
})(ZIndexLayer || (ZIndexLayer = {}));
|
|
28
|
+
export class ToolCoordinator {
|
|
29
|
+
config;
|
|
30
|
+
tools = new Map();
|
|
31
|
+
layerCounters = new Map();
|
|
32
|
+
listeners = new Set();
|
|
33
|
+
constructor(config = {}) {
|
|
34
|
+
this.config = config;
|
|
35
|
+
// Initialize layer counters
|
|
36
|
+
this.layerCounters.set(ZIndexLayer.BASE, 0);
|
|
37
|
+
this.layerCounters.set(ZIndexLayer.TOOL, 0);
|
|
38
|
+
this.layerCounters.set(ZIndexLayer.MODAL, 0);
|
|
39
|
+
this.layerCounters.set(ZIndexLayer.CONTROL, 0);
|
|
40
|
+
this.layerCounters.set(ZIndexLayer.HIGHLIGHT, 0);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Subscribe to tool state changes
|
|
44
|
+
* Returns unsubscribe function
|
|
45
|
+
*/
|
|
46
|
+
subscribe(listener) {
|
|
47
|
+
this.listeners.add(listener);
|
|
48
|
+
return () => {
|
|
49
|
+
this.listeners.delete(listener);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Notify all listeners of state change
|
|
54
|
+
*/
|
|
55
|
+
notifyListeners() {
|
|
56
|
+
this.listeners.forEach((listener) => listener());
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Register a tool with the coordinator
|
|
60
|
+
*
|
|
61
|
+
* @param id Unique tool identifier
|
|
62
|
+
* @param name Display name
|
|
63
|
+
* @param element DOM element for the tool (optional for backward compatibility)
|
|
64
|
+
* @param layer Z-index layer (defaults to MODAL)
|
|
65
|
+
*/
|
|
66
|
+
registerTool(id, name, element, layer = ZIndexLayer.MODAL) {
|
|
67
|
+
log("registerTool called:", { id, name, hasElement: !!element, layer });
|
|
68
|
+
if (this.tools.has(id)) {
|
|
69
|
+
log(`Tool ${id} is already registered`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// If no element provided, create a placeholder registration
|
|
73
|
+
if (!element) {
|
|
74
|
+
this.tools.set(id, {
|
|
75
|
+
id,
|
|
76
|
+
name,
|
|
77
|
+
element: null,
|
|
78
|
+
layer,
|
|
79
|
+
isVisible: false,
|
|
80
|
+
baseZIndex: layer,
|
|
81
|
+
});
|
|
82
|
+
log("Tool registered without element:", id);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Calculate base z-index for this layer
|
|
86
|
+
const baseZIndex = layer + this.getNextLayerOffset(layer);
|
|
87
|
+
// Apply z-index
|
|
88
|
+
element.style.zIndex = String(baseZIndex);
|
|
89
|
+
// Create and store event handler to enable proper cleanup
|
|
90
|
+
const mouseDownHandler = () => this.bringToFront(element);
|
|
91
|
+
element.addEventListener("mousedown", mouseDownHandler);
|
|
92
|
+
// Register tool with handler reference
|
|
93
|
+
this.tools.set(id, {
|
|
94
|
+
id,
|
|
95
|
+
name,
|
|
96
|
+
element,
|
|
97
|
+
layer,
|
|
98
|
+
isVisible: false,
|
|
99
|
+
baseZIndex,
|
|
100
|
+
mouseDownHandler,
|
|
101
|
+
});
|
|
102
|
+
log("Tool registered with element:", id);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Unregister a tool
|
|
106
|
+
*
|
|
107
|
+
* @param id Tool identifier
|
|
108
|
+
*/
|
|
109
|
+
unregisterTool(id) {
|
|
110
|
+
const tool = this.tools.get(id);
|
|
111
|
+
if (!tool)
|
|
112
|
+
return;
|
|
113
|
+
// Remove event listeners using stored handler reference
|
|
114
|
+
if (tool.element && tool.mouseDownHandler) {
|
|
115
|
+
tool.element.removeEventListener("mousedown", tool.mouseDownHandler);
|
|
116
|
+
}
|
|
117
|
+
this.tools.delete(id);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Show a tool
|
|
121
|
+
*
|
|
122
|
+
* @param id Tool identifier
|
|
123
|
+
*/
|
|
124
|
+
showTool(id) {
|
|
125
|
+
const tool = this.tools.get(id);
|
|
126
|
+
if (!tool) {
|
|
127
|
+
log(`Tool ${id} not found`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (tool.element) {
|
|
131
|
+
tool.element.style.display = "";
|
|
132
|
+
this.bringToFront(tool.element);
|
|
133
|
+
}
|
|
134
|
+
tool.isVisible = true;
|
|
135
|
+
this.notifyListeners();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Hide a tool
|
|
139
|
+
*
|
|
140
|
+
* @param id Tool identifier
|
|
141
|
+
*/
|
|
142
|
+
hideTool(id) {
|
|
143
|
+
const tool = this.tools.get(id);
|
|
144
|
+
if (!tool) {
|
|
145
|
+
log(`Tool ${id} not found`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (tool.element) {
|
|
149
|
+
tool.element.style.display = "none";
|
|
150
|
+
}
|
|
151
|
+
tool.isVisible = false;
|
|
152
|
+
this.notifyListeners();
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Toggle tool visibility
|
|
156
|
+
*
|
|
157
|
+
* @param id Tool identifier
|
|
158
|
+
*/
|
|
159
|
+
toggleTool(id) {
|
|
160
|
+
log("toggleTool called for:", id);
|
|
161
|
+
const tool = this.tools.get(id);
|
|
162
|
+
if (!tool) {
|
|
163
|
+
log(`Tool ${id} not found. Registered tools:`, Array.from(this.tools.keys()));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
log("Tool found, current visibility:", tool.isVisible);
|
|
167
|
+
if (tool.isVisible) {
|
|
168
|
+
this.hideTool(id);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
this.showTool(id);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check if tool is visible
|
|
176
|
+
*
|
|
177
|
+
* @param id Tool identifier
|
|
178
|
+
* @returns true if tool is visible
|
|
179
|
+
*/
|
|
180
|
+
isToolVisible(id) {
|
|
181
|
+
const tool = this.tools.get(id);
|
|
182
|
+
return tool?.isVisible ?? false;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Bring element to front of its layer
|
|
186
|
+
*
|
|
187
|
+
* @param element DOM element to bring forward
|
|
188
|
+
*/
|
|
189
|
+
bringToFront(element) {
|
|
190
|
+
// Find tool registration
|
|
191
|
+
const tool = Array.from(this.tools.values()).find((t) => t.element === element);
|
|
192
|
+
if (!tool)
|
|
193
|
+
return;
|
|
194
|
+
// Calculate new z-index (highest in layer + 1)
|
|
195
|
+
const maxZIndexInLayer = this.getMaxZIndexInLayer(tool.layer);
|
|
196
|
+
const newZIndex = Math.max(maxZIndexInLayer + 1, tool.layer + 1);
|
|
197
|
+
// Update z-index
|
|
198
|
+
element.style.zIndex = String(newZIndex);
|
|
199
|
+
tool.baseZIndex = newZIndex;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get all registered tool IDs
|
|
203
|
+
*/
|
|
204
|
+
getRegisteredTools() {
|
|
205
|
+
return Array.from(this.tools.keys());
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get tool element by ID
|
|
209
|
+
*/
|
|
210
|
+
getToolElement(id) {
|
|
211
|
+
return this.tools.get(id)?.element ?? null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get next offset within a layer
|
|
215
|
+
*/
|
|
216
|
+
getNextLayerOffset(layer) {
|
|
217
|
+
const current = this.layerCounters.get(layer) ?? 0;
|
|
218
|
+
this.layerCounters.set(layer, current + 1);
|
|
219
|
+
return current;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get maximum z-index currently in use in a layer
|
|
223
|
+
*/
|
|
224
|
+
getMaxZIndexInLayer(layer) {
|
|
225
|
+
let max = layer;
|
|
226
|
+
for (const tool of this.tools.values()) {
|
|
227
|
+
if (tool.layer === layer) {
|
|
228
|
+
max = Math.max(max, tool.baseZIndex);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return max;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Reset all tools to their base z-indices
|
|
235
|
+
*/
|
|
236
|
+
resetZIndices() {
|
|
237
|
+
for (const tool of this.tools.values()) {
|
|
238
|
+
if (tool.element) {
|
|
239
|
+
tool.element.style.zIndex = String(tool.baseZIndex);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Update tool element reference (backward compatibility)
|
|
245
|
+
*
|
|
246
|
+
* @param id Tool identifier
|
|
247
|
+
* @param element New DOM element
|
|
248
|
+
*/
|
|
249
|
+
updateToolElement(id, element) {
|
|
250
|
+
const tool = this.tools.get(id);
|
|
251
|
+
if (!tool) {
|
|
252
|
+
log(`Tool ${id} not found`);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Remove old event listener using stored handler reference
|
|
256
|
+
if (tool.element && tool.mouseDownHandler) {
|
|
257
|
+
tool.element.removeEventListener("mousedown", tool.mouseDownHandler);
|
|
258
|
+
}
|
|
259
|
+
// Create new handler and add listener
|
|
260
|
+
const mouseDownHandler = () => this.bringToFront(element);
|
|
261
|
+
element.addEventListener("mousedown", mouseDownHandler);
|
|
262
|
+
// Update element and handler reference
|
|
263
|
+
tool.element = element;
|
|
264
|
+
tool.mouseDownHandler = mouseDownHandler;
|
|
265
|
+
// Apply z-index to new element
|
|
266
|
+
element.style.zIndex = String(tool.baseZIndex);
|
|
267
|
+
if (tool.isVisible) {
|
|
268
|
+
element.style.display = "";
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
element.style.display = "none";
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Hide all tools (backward compatibility)
|
|
276
|
+
*/
|
|
277
|
+
hideAllTools() {
|
|
278
|
+
for (const id of this.tools.keys()) {
|
|
279
|
+
this.hideTool(id);
|
|
280
|
+
}
|
|
281
|
+
this.notifyListeners();
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get tool state (interface method)
|
|
285
|
+
*
|
|
286
|
+
* @param id Tool identifier
|
|
287
|
+
* @returns Tool state or undefined
|
|
288
|
+
*/
|
|
289
|
+
getToolState(id) {
|
|
290
|
+
const tool = this.tools.get(id);
|
|
291
|
+
if (!tool)
|
|
292
|
+
return undefined;
|
|
293
|
+
return {
|
|
294
|
+
id: tool.id,
|
|
295
|
+
name: tool.name,
|
|
296
|
+
isVisible: tool.isVisible,
|
|
297
|
+
element: tool.element ?? null,
|
|
298
|
+
layer: tool.layer,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get all visible tools (interface method)
|
|
303
|
+
*
|
|
304
|
+
* @returns Array of visible tool states
|
|
305
|
+
*/
|
|
306
|
+
getVisibleTools() {
|
|
307
|
+
return Array.from(this.tools.values())
|
|
308
|
+
.filter((tool) => tool.isVisible)
|
|
309
|
+
.map((tool) => ({
|
|
310
|
+
id: tool.id,
|
|
311
|
+
name: tool.name,
|
|
312
|
+
isVisible: tool.isVisible,
|
|
313
|
+
element: tool.element ?? null,
|
|
314
|
+
layer: tool.layer,
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=ToolCoordinator.js.map
|