@pie-players/pie-section-tools-toolbar 0.2.9 → 0.2.10
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/dist/pie-tool-calculator-CjiwM9t4.js +3443 -0
- package/dist/section-tools-toolbar.js +1171 -1163
- package/dist/tool-graph-CXPY5FT9.js +4573 -0
- package/dist/tool-line-reader-CIyMzHIp.js +4315 -0
- package/dist/tool-periodic-table-C3x2EIo9.js +4181 -0
- package/dist/tool-protractor-B3JIgh4k.js +13787 -0
- package/dist/tool-ruler-BdnBVoda.js +13819 -0
- package/package.json +16 -13
- package/section-tools-toolbar.svelte +164 -161
- package/dist/section-tools-toolbar.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-players/pie-section-tools-toolbar",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Section-level tools toolbar for PIE assessment player",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/pie-framework/pie-players.git"
|
|
8
|
+
"url": "git+https://github.com/pie-framework/pie-players.git",
|
|
9
|
+
"directory": "packages/section-tools-toolbar"
|
|
9
10
|
},
|
|
10
11
|
"publishConfig": {
|
|
11
12
|
"access": "public"
|
|
@@ -40,16 +41,10 @@
|
|
|
40
41
|
"unpkg": "./dist/section-tools-toolbar.js",
|
|
41
42
|
"jsdelivr": "./dist/section-tools-toolbar.js",
|
|
42
43
|
"dependencies": {
|
|
43
|
-
"@pie-players/pie-assessment-toolkit": "0.2.
|
|
44
|
-
"@pie-players/pie-
|
|
45
|
-
"@pie-players/pie-
|
|
46
|
-
"@pie-players/pie-
|
|
47
|
-
"@pie-players/pie-tool-line-reader": "0.1.8",
|
|
48
|
-
"@pie-players/pie-tool-magnifier": "0.1.8",
|
|
49
|
-
"@pie-players/pie-tool-periodic-table": "0.1.8",
|
|
50
|
-
"@pie-players/pie-tool-protractor": "0.1.8",
|
|
51
|
-
"@pie-players/pie-tool-ruler": "0.1.8",
|
|
52
|
-
"@sveltejs/kit": "^2.52.0",
|
|
44
|
+
"@pie-players/pie-assessment-toolkit": "0.2.9",
|
|
45
|
+
"@pie-players/pie-context": "0.1.1",
|
|
46
|
+
"@pie-players/pie-default-tool-loaders": "0.1.1",
|
|
47
|
+
"@pie-players/pie-calculator-mathjs": "0.1.4",
|
|
53
48
|
"daisyui": "^5.5.18"
|
|
54
49
|
},
|
|
55
50
|
"types": "./dist/index.d.ts",
|
|
@@ -66,5 +61,13 @@
|
|
|
66
61
|
"typescript": "^5.7.0",
|
|
67
62
|
"vite": "^7.0.8",
|
|
68
63
|
"vite-plugin-dts": "^4.5.3"
|
|
69
|
-
}
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/pie-framework/pie-players/tree/master/packages/section-tools-toolbar#readme",
|
|
66
|
+
"bugs": {
|
|
67
|
+
"url": "https://github.com/pie-framework/pie-players/issues"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=18.0.0"
|
|
71
|
+
},
|
|
72
|
+
"sideEffects": true
|
|
70
73
|
}
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
props: {
|
|
6
6
|
enabledTools: { type: 'String', attribute: 'enabled-tools' },
|
|
7
7
|
position: { type: 'String', attribute: 'position' },
|
|
8
|
-
|
|
9
|
-
toolCoordinator: { type: 'Object', reflect: false },
|
|
10
|
-
toolProviderRegistry: { type: 'Object', reflect: false }
|
|
8
|
+
toolCoordinator: { type: 'Object', reflect: false }
|
|
11
9
|
}
|
|
12
10
|
}}
|
|
13
11
|
/>
|
|
@@ -28,67 +26,123 @@
|
|
|
28
26
|
Similar to SchoolCity pattern - section-wide tools independent of item navigation.
|
|
29
27
|
-->
|
|
30
28
|
<script lang="ts">
|
|
29
|
+
import {
|
|
30
|
+
connectAssessmentToolkitRuntimeContext,
|
|
31
|
+
createDefaultToolRegistry,
|
|
32
|
+
normalizeToolList,
|
|
33
|
+
normalizeToolsConfig,
|
|
34
|
+
parseToolList,
|
|
35
|
+
resolveToolsForLevel,
|
|
36
|
+
createScopedToolId,
|
|
37
|
+
} from '@pie-players/pie-assessment-toolkit';
|
|
31
38
|
import type {
|
|
39
|
+
AssessmentToolkitRuntimeContext,
|
|
32
40
|
IToolCoordinator,
|
|
33
|
-
|
|
41
|
+
ToolContext,
|
|
34
42
|
} from '@pie-players/pie-assessment-toolkit';
|
|
43
|
+
import { registerSectionToolModuleLoaders } from '@pie-players/pie-default-tool-loaders';
|
|
35
44
|
import { onDestroy, onMount } from 'svelte';
|
|
36
45
|
|
|
37
46
|
const isBrowser = typeof window !== 'undefined';
|
|
47
|
+
const toolRegistry = createDefaultToolRegistry();
|
|
48
|
+
registerSectionToolModuleLoaders(toolRegistry);
|
|
38
49
|
|
|
39
50
|
// Props
|
|
40
51
|
let {
|
|
41
|
-
enabledTools = '
|
|
52
|
+
enabledTools = '',
|
|
42
53
|
position = 'bottom',
|
|
43
|
-
toolCoordinator
|
|
44
|
-
toolProviderRegistry
|
|
54
|
+
toolCoordinator = null as IToolCoordinator | null
|
|
45
55
|
}: {
|
|
46
56
|
enabledTools?: string;
|
|
47
57
|
position?: 'top' | 'right' | 'bottom' | 'left' | 'none';
|
|
48
|
-
toolCoordinator?: IToolCoordinator;
|
|
49
|
-
toolProviderRegistry?: ToolProviderRegistry;
|
|
58
|
+
toolCoordinator?: IToolCoordinator | null;
|
|
50
59
|
} = $props();
|
|
60
|
+
let toolbarRootElement = $state<HTMLElement | null>(null);
|
|
61
|
+
let runtimeContext = $state<AssessmentToolkitRuntimeContext | null>(null);
|
|
62
|
+
const effectiveToolCoordinator = $derived(
|
|
63
|
+
(toolCoordinator as IToolCoordinator | null) ||
|
|
64
|
+
(runtimeContext?.toolCoordinator as IToolCoordinator | undefined),
|
|
65
|
+
);
|
|
51
66
|
|
|
52
|
-
|
|
67
|
+
const effectiveSectionId = $derived(runtimeContext?.sectionId || 'default');
|
|
68
|
+
const requestedEnabledToolsList = $derived(parseToolList(enabledTools));
|
|
69
|
+
const effectiveToolsConfig = $derived.by(() => {
|
|
70
|
+
const coordinatorConfig = runtimeContext?.toolkitCoordinator?.config?.tools as any;
|
|
71
|
+
return normalizeToolsConfig(coordinatorConfig || {});
|
|
72
|
+
});
|
|
73
|
+
const placementTools = $derived.by(() =>
|
|
74
|
+
normalizeToolList(resolveToolsForLevel(effectiveToolsConfig, 'section'))
|
|
75
|
+
);
|
|
53
76
|
let enabledToolsList = $derived(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.filter(Boolean)
|
|
77
|
+
requestedEnabledToolsList.length > 0
|
|
78
|
+
? requestedEnabledToolsList
|
|
79
|
+
: placementTools
|
|
58
80
|
);
|
|
59
81
|
let hasEnabledTools = $derived(enabledToolsList.length > 0);
|
|
82
|
+
const sectionToolContext = $derived.by((): ToolContext => ({
|
|
83
|
+
level: 'section',
|
|
84
|
+
assessment: {} as any,
|
|
85
|
+
section: {} as any,
|
|
86
|
+
}));
|
|
60
87
|
|
|
61
88
|
// Tool visibility state (reactive to coordinator changes)
|
|
62
89
|
let showGraph = $state(false);
|
|
90
|
+
let showCalculator = $state(false);
|
|
63
91
|
let showPeriodicTable = $state(false);
|
|
64
92
|
let showProtractor = $state(false);
|
|
65
93
|
let showLineReader = $state(false);
|
|
66
|
-
let showMagnifier = $state(false);
|
|
67
94
|
let showRuler = $state(false);
|
|
95
|
+
let toolActiveById = $state<Record<string, boolean>>({});
|
|
68
96
|
let statusMessage = $state('');
|
|
97
|
+
type SectionButtonMeta = {
|
|
98
|
+
toolId: string;
|
|
99
|
+
label: string;
|
|
100
|
+
ariaLabel: string;
|
|
101
|
+
tooltip?: string;
|
|
102
|
+
icon: string;
|
|
103
|
+
onClick: () => void;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
function toScopedToolId(toolId: string): string {
|
|
107
|
+
return createScopedToolId(toolId, 'section', effectiveSectionId);
|
|
108
|
+
}
|
|
69
109
|
|
|
70
110
|
// Update visibility state from coordinator
|
|
71
111
|
function updateToolVisibility() {
|
|
72
|
-
if (!
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
showRuler =
|
|
112
|
+
if (!effectiveToolCoordinator) return;
|
|
113
|
+
showCalculator = effectiveToolCoordinator.isToolVisible(toScopedToolId('calculator'));
|
|
114
|
+
showGraph = effectiveToolCoordinator.isToolVisible(toScopedToolId('graph'));
|
|
115
|
+
showPeriodicTable = effectiveToolCoordinator.isToolVisible(toScopedToolId('periodicTable'));
|
|
116
|
+
showProtractor = effectiveToolCoordinator.isToolVisible(toScopedToolId('protractor'));
|
|
117
|
+
showLineReader = effectiveToolCoordinator.isToolVisible(toScopedToolId('lineReader'));
|
|
118
|
+
showRuler = effectiveToolCoordinator.isToolVisible(toScopedToolId('ruler'));
|
|
119
|
+
toolActiveById = {
|
|
120
|
+
calculator: showCalculator,
|
|
121
|
+
graph: showGraph,
|
|
122
|
+
periodicTable: showPeriodicTable,
|
|
123
|
+
protractor: showProtractor,
|
|
124
|
+
lineReader: showLineReader,
|
|
125
|
+
ruler: showRuler
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isToolActive(toolId: string): boolean {
|
|
130
|
+
return toolActiveById[toolId] === true;
|
|
79
131
|
}
|
|
80
132
|
|
|
81
133
|
// Toggle tool visibility
|
|
82
|
-
function toggleTool(toolId: string) {
|
|
83
|
-
if (!
|
|
84
|
-
|
|
134
|
+
async function toggleTool(toolId: string) {
|
|
135
|
+
if (!effectiveToolCoordinator) return;
|
|
136
|
+
await toolRegistry.ensureToolModuleLoaded(toolId);
|
|
137
|
+
const scopedToolId = toScopedToolId(toolId);
|
|
138
|
+
effectiveToolCoordinator.toggleTool(scopedToolId);
|
|
85
139
|
updateToolVisibility();
|
|
86
140
|
|
|
87
141
|
// Get tool name for status message
|
|
88
|
-
const tool =
|
|
142
|
+
const tool = visibleButtons.find((t) => t.toolId === toolId);
|
|
89
143
|
if (tool) {
|
|
90
|
-
const isVisible =
|
|
91
|
-
statusMessage = `${tool.
|
|
144
|
+
const isVisible = effectiveToolCoordinator.isToolVisible(scopedToolId);
|
|
145
|
+
statusMessage = `${tool.ariaLabel} ${isVisible ? 'opened' : 'closed'}`;
|
|
92
146
|
}
|
|
93
147
|
}
|
|
94
148
|
|
|
@@ -96,120 +150,76 @@
|
|
|
96
150
|
let unsubscribe: (() => void) | null = null;
|
|
97
151
|
|
|
98
152
|
onMount(() => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
console.error('[SectionToolsToolbar] Failed to load tool web components:', err);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
153
|
+
updateToolVisibility();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
$effect(() => {
|
|
157
|
+
if (!toolbarRootElement) return;
|
|
158
|
+
return connectAssessmentToolkitRuntimeContext(
|
|
159
|
+
toolbarRootElement,
|
|
160
|
+
(value: AssessmentToolkitRuntimeContext) => {
|
|
161
|
+
runtimeContext = value;
|
|
162
|
+
},
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
$effect(() => {
|
|
167
|
+
unsubscribe?.();
|
|
168
|
+
unsubscribe = null;
|
|
169
|
+
if (!effectiveToolCoordinator) return;
|
|
119
170
|
|
|
120
|
-
|
|
171
|
+
updateToolVisibility();
|
|
172
|
+
unsubscribe = effectiveToolCoordinator.subscribe(() => {
|
|
121
173
|
updateToolVisibility();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return () => {
|
|
177
|
+
unsubscribe?.();
|
|
178
|
+
unsubscribe = null;
|
|
179
|
+
};
|
|
126
180
|
});
|
|
127
181
|
|
|
128
182
|
onDestroy(() => {
|
|
129
183
|
unsubscribe?.();
|
|
130
184
|
});
|
|
131
185
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
ariaLabel: 'Angle measurement tool',
|
|
151
|
-
visible: showProtractor,
|
|
152
|
-
enabled: enabledToolsList.includes('protractor'),
|
|
153
|
-
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m6.75 21-.25-2.2 2.85-7.85a3.95 3.95 0 0 0 1.75.95l-2.75 7.55L6.75 21Zm10.5 0-1.6-1.55-2.75-7.55a3.948 3.948 0 0 0 1.75-.95l2.85 7.85-.25 2.2ZM12 11a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 9 8c0-.65.188-1.23.563-1.737A2.935 2.935 0 0 1 11 5.2V3h2v2.2c.583.2 1.063.554 1.438 1.063C14.812 6.77 15 7.35 15 8c0 .833-.292 1.542-.875 2.125A2.893 2.893 0 0 1 12 11Zm0-2c.283 0 .52-.096.713-.287A.967.967 0 0 0 13 8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8c0 .283.096.52.287.713.192.191.43.287.713.287Z" fill="currentColor"/></svg>'
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
id: 'lineReader',
|
|
157
|
-
ariaLabel: 'Line reading guide',
|
|
158
|
-
visible: showLineReader,
|
|
159
|
-
enabled: enabledToolsList.includes('lineReader'),
|
|
160
|
-
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.85 15c.517 0 .98-.15 1.388-.45.408-.3.695-.692.862-1.175l.375-1.15c.267-.8.2-1.537-.2-2.213C8.875 9.337 8.3 9 7.55 9H4.025l.475 3.925c.083.583.346 1.075.787 1.475.442.4.963.6 1.563.6Zm10.3 0c.6 0 1.12-.2 1.563-.6.441-.4.704-.892.787-1.475L19.975 9h-3.5c-.75 0-1.325.342-1.725 1.025-.4.683-.467 1.425-.2 2.225l.35 1.125c.167.483.454.875.862 1.175.409.3.871.45 1.388.45Zm-10.3 2c-1.1 0-2.063-.363-2.887-1.088a4.198 4.198 0 0 1-1.438-2.737L2 9H1V7h6.55c.733 0 1.404.18 2.013.537A3.906 3.906 0 0 1 11 9h2.025c.35-.617.83-1.104 1.438-1.463A3.892 3.892 0 0 1 16.474 7H23v2h-1l-.525 4.175a4.198 4.198 0 0 1-1.438 2.737A4.238 4.238 0 0 1 17.15 17c-.95 0-1.804-.27-2.562-.813A4.234 4.234 0 0 1 13 14.026l-.375-1.125a21.35 21.35 0 0 1-.1-.363 4.926 4.926 0 0 1-.1-.537h-.85c-.033.2-.067.363-.1.488a21.35 21.35 0 0 1-.1.362L11 14a4.3 4.3 0 0 1-1.588 2.175A4.258 4.258 0 0 1 6.85 17Z" fill="currentColor"/></svg>'
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
id: 'magnifier',
|
|
164
|
-
ariaLabel: 'Text magnification tool',
|
|
165
|
-
visible: showMagnifier,
|
|
166
|
-
enabled: enabledToolsList.includes('magnifier'),
|
|
167
|
-
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.5 5.5c-1.813 0-3.438.969-4.344 2.5a4.937 4.937 0 0 0 0 5 4.974 4.974 0 0 0 4.344 2.5 4.96 4.96 0 0 0 4.313-2.5 4.937 4.937 0 0 0 0-5c-.908-1.531-2.533-2.5-4.313-2.5Zm0 11.5A6.495 6.495 0 0 1 4 10.5C4 6.937 6.906 4 10.5 4c3.563 0 6.5 2.938 6.5 6.5a6.597 6.597 0 0 1-1.406 4.063l4.156 4.187a.685.685 0 0 1 0 1.031.685.685 0 0 1-1.031 0l-4.188-4.156A6.548 6.548 0 0 1 10.5 17Zm-.75-3.75v-2h-2A.723.723 0 0 1 7 10.5a.74.74 0 0 1 .75-.75h2v-2A.74.74 0 0 1 10.5 7a.76.76 0 0 1 .75.75v2h2a.76.76 0 0 1 .696 1.039.741.741 0 0 1-.696.461h-2v2a.74.74 0 0 1-.75.75.723.723 0 0 1-.75-.75Z" fill="currentColor"/></svg>'
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
id: 'ruler',
|
|
171
|
-
ariaLabel: 'Measurement ruler',
|
|
172
|
-
visible: showRuler,
|
|
173
|
-
enabled: enabledToolsList.includes('ruler'),
|
|
174
|
-
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m8.8 10.95 2.15-2.175-1.4-1.425-1.1 1.1-1.4-1.4 1.075-1.1L7 4.825 4.825 7 8.8 10.95Zm8.2 8.225L19.175 17l-1.125-1.125-1.1 1.075-1.4-1.4 1.075-1.1-1.425-1.4-2.15 2.15L17 19.175ZM7.25 21H3v-4.25l4.375-4.375L2 7l5-5 5.4 5.4 3.775-3.8c.2-.2.425-.35.675-.45a2.068 2.068 0 0 1 1.55 0c.25.1.475.25.675.45L20.4 4.95c.2.2.35.425.45.675.1.25.15.508.15.775a1.975 1.975 0 0 1-.6 1.425l-3.775 3.8L22 17l-5 5-5.375-5.375L7.25 21ZM5 19h1.4l9.8-9.775L14.775 7.8 5 17.6V19Z" fill="currentColor"/></svg>'
|
|
175
|
-
}
|
|
176
|
-
]);
|
|
186
|
+
const visibleButtons = $derived.by((): SectionButtonMeta[] => {
|
|
187
|
+
return enabledToolsList
|
|
188
|
+
.map((toolId: string) => toolRegistry.get(toolId))
|
|
189
|
+
.filter((tool): tool is NonNullable<ReturnType<typeof toolRegistry.get>> => Boolean(tool))
|
|
190
|
+
.map((tool) => {
|
|
191
|
+
const icon = typeof tool.icon === 'function' ? tool.icon(sectionToolContext) : tool.icon;
|
|
192
|
+
return {
|
|
193
|
+
toolId: tool.toolId,
|
|
194
|
+
label: tool.name,
|
|
195
|
+
ariaLabel: tool.name,
|
|
196
|
+
tooltip: tool.name,
|
|
197
|
+
icon,
|
|
198
|
+
onClick: () => {
|
|
199
|
+
void toggleTool(tool.toolId);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
});
|
|
177
204
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
205
|
+
function resolveIconMarkup(icon: string): string {
|
|
206
|
+
if (icon.startsWith('<svg')) return icon;
|
|
207
|
+
const iconMap: Record<string, string> = {
|
|
208
|
+
calculator: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7,2H17A2,2 0 0,1 19,4V20A2,2 0 0,1 17,22H7A2,2 0 0,1 5,20V4A2,2 0 0,1 7,2M7,4V8H17V4H7M7,10V12H9V10H7M11,10V12H13V10H11M15,10V12H17V10H15M7,14V16H9V14H7M11,14V16H13V14H11M15,14V16H17V14H15M7,18V20H9V18H7M11,18V20H13V18H11M15,18V20H17V18H15Z" fill="currentColor"/></svg>',
|
|
209
|
+
'chart-bar': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4.75 5a.76.76 0 0 1 .75.75v11c0 .438.313.75.75.75h13a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-13C5 19 4 18 4 16.75v-11A.74.74 0 0 1 4.75 5ZM8 8.25a.74.74 0 0 1 .75-.75h6.5a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-6.5A.722.722 0 0 1 8 8.25Zm.75 2.25h4.5a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-4.5a.723.723 0 0 1-.75-.75.74.74 0 0 1 .75-.75Zm0 3h8.5a.76.76 0 0 1 .696 1.039.74.74 0 0 1-.696.461h-8.5a.723.723 0 0 1-.75-.75.74.74 0 0 1 .75-.75Z" fill="currentColor"/></svg>',
|
|
210
|
+
beaker: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 21c-.85 0-1.454-.38-1.813-1.137-.358-.759-.27-1.463.263-2.113L9 11V5H8a.968.968 0 0 1-.713-.287A.968.968 0 0 1 7 4c0-.283.096-.52.287-.712A.968.968 0 0 1 8 3h8c.283 0 .52.096.712.288.192.191.288.429.288.712s-.096.52-.288.713A.968.968 0 0 1 16 5h-1v6l5.55 6.75c.533.65.62 1.354.262 2.113C20.454 20.62 19.85 21 19 21H5Zm2-3h10l-3.4-4h-3.2L7 18Zm-2 1h14l-6-7.3V5h-2v6.7L5 19Z" fill="currentColor"/></svg>',
|
|
211
|
+
protractor: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m6.75 21-.25-2.2 2.85-7.85a3.95 3.95 0 0 0 1.75.95l-2.75 7.55L6.75 21Zm10.5 0-1.6-1.55-2.75-7.55a3.948 3.948 0 0 0 1.75-.95l2.85 7.85-.25 2.2ZM12 11a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 9 8c0-.65.188-1.23.563-1.737A2.935 2.935 0 0 1 11 5.2V3h2v2.2c.583.2 1.063.554 1.438 1.063C14.812 6.77 15 7.35 15 8c0 .833-.292 1.542-.875 2.125A2.893 2.893 0 0 1 12 11Zm0-2c.283 0 .52-.096.713-.287A.967.967 0 0 0 13 8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8c0 .283.096.52.287.713.192.191.43.287.713.287Z" fill="currentColor"/></svg>',
|
|
212
|
+
'bars-3': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.85 15c.517 0 .98-.15 1.388-.45.408-.3.695-.692.862-1.175l.375-1.15c.267-.8.2-1.537-.2-2.213C8.875 9.337 8.3 9 7.55 9H4.025l.475 3.925c.083.583.346 1.075.787 1.475.442.4.963.6 1.563.6Zm10.3 0c.6 0 1.12-.2 1.563-.6.441-.4.704-.892.787-1.475L19.975 9h-3.5c-.75 0-1.325.342-1.725 1.025-.4.683-.467 1.425-.2 2.225l.35 1.125c.167.483.454.875.862 1.175.409.3.871.45 1.388.45Zm-10.3 2c-1.1 0-2.063-.363-2.887-1.088a4.198 4.198 0 0 1-1.438-2.737L2 9H1V7h6.55c.733 0 1.404.18 2.013.537A3.906 3.906 0 0 1 11 9h2.025c.35-.617.83-1.104 1.438-1.463A3.892 3.892 0 0 1 16.474 7H23v2h-1l-.525 4.175a4.198 4.198 0 0 1-1.438 2.737A4.238 4.238 0 0 1 17.15 17c-.95 0-1.804-.27-2.562-.813A4.234 4.234 0 0 1 13 14.026l-.375-1.125a21.35 21.35 0 0 1-.1-.363 4.926 4.926 0 0 1-.1-.537h-.85c-.033.2-.067.363-.1.488a21.35 21.35 0 0 1-.1.362L11 14a4.3 4.3 0 0 1-1.588 2.175A4.258 4.258 0 0 1 6.85 17Z" fill="currentColor"/></svg>',
|
|
213
|
+
ruler: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m8.8 10.95 2.15-2.175-1.4-1.425-1.1 1.1-1.4-1.4 1.075-1.1L7 4.825 4.825 7 8.8 10.95Zm8.2 8.225L19.175 17l-1.125-1.125-1.1 1.075-1.4-1.4 1.075-1.1-1.425-1.4-2.15 2.15L17 19.175ZM7.25 21H3v-4.25l4.375-4.375L2 7l5-5 5.4 5.4 3.775-3.8c.2-.2.425-.35.675-.45a2.068 2.068 0 0 1 1.55 0c.25.1.475.25.675.45L20.4 4.95c.2.2.35.425.45.675.1.25.15.508.15.775a1.975 1.975 0 0 1-.6 1.425l-3.775 3.8L22 17l-5 5-5.375-5.375L7.25 21ZM5 19h1.4l9.8-9.775L14.775 7.8 5 17.6V19Z" fill="currentColor"/></svg>',
|
|
214
|
+
};
|
|
215
|
+
return iconMap[icon] || '';
|
|
216
|
+
}
|
|
185
217
|
|
|
186
|
-
// Bind coordinator to tool elements
|
|
187
|
-
$effect(() => {
|
|
188
|
-
if (toolCoordinator) {
|
|
189
|
-
if (graphElement) {
|
|
190
|
-
(graphElement as any).coordinator = toolCoordinator;
|
|
191
|
-
}
|
|
192
|
-
if (periodicTableElement) {
|
|
193
|
-
(periodicTableElement as any).coordinator = toolCoordinator;
|
|
194
|
-
}
|
|
195
|
-
if (protractorElement) {
|
|
196
|
-
(protractorElement as any).coordinator = toolCoordinator;
|
|
197
|
-
}
|
|
198
|
-
if (lineReaderElement) {
|
|
199
|
-
(lineReaderElement as any).coordinator = toolCoordinator;
|
|
200
|
-
}
|
|
201
|
-
if (magnifierElement) {
|
|
202
|
-
(magnifierElement as any).coordinator = toolCoordinator;
|
|
203
|
-
}
|
|
204
|
-
if (rulerElement) {
|
|
205
|
-
(rulerElement as any).coordinator = toolCoordinator;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
218
|
</script>
|
|
210
219
|
|
|
211
220
|
{#if isBrowser && position !== 'none' && hasEnabledTools}
|
|
212
221
|
<div
|
|
222
|
+
bind:this={toolbarRootElement}
|
|
213
223
|
class="section-tools-toolbar section-tools-toolbar--{position}"
|
|
214
224
|
class:section-tools-toolbar--top={position === 'top'}
|
|
215
225
|
class:section-tools-toolbar--right={position === 'right'}
|
|
@@ -220,20 +230,18 @@
|
|
|
220
230
|
aria-label="Assessment tools"
|
|
221
231
|
>
|
|
222
232
|
<div class="tools-buttons">
|
|
223
|
-
{#each
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
</button>
|
|
236
|
-
{/if}
|
|
233
|
+
{#each visibleButtons as button (button.toolId)}
|
|
234
|
+
<button
|
|
235
|
+
type="button"
|
|
236
|
+
class="tool-button"
|
|
237
|
+
class:active={isToolActive(button.toolId)}
|
|
238
|
+
onclick={button.onClick}
|
|
239
|
+
title={button.tooltip || button.label}
|
|
240
|
+
aria-label={button.ariaLabel}
|
|
241
|
+
aria-pressed={isToolActive(button.toolId)}
|
|
242
|
+
>
|
|
243
|
+
{@html resolveIconMarkup(button.icon)}
|
|
244
|
+
</button>
|
|
237
245
|
{/each}
|
|
238
246
|
</div>
|
|
239
247
|
</div>
|
|
@@ -243,49 +251,44 @@
|
|
|
243
251
|
|
|
244
252
|
{#if enabledToolsList.includes('graph')}
|
|
245
253
|
<pie-tool-graph
|
|
246
|
-
bind:this={graphElement}
|
|
247
254
|
visible={showGraph}
|
|
248
|
-
tool-id=
|
|
255
|
+
tool-id={toScopedToolId('graph')}
|
|
249
256
|
></pie-tool-graph>
|
|
250
257
|
{/if}
|
|
251
258
|
|
|
259
|
+
{#if enabledToolsList.includes('calculator')}
|
|
260
|
+
<pie-tool-calculator
|
|
261
|
+
visible={showCalculator}
|
|
262
|
+
tool-id={toScopedToolId('calculator')}
|
|
263
|
+
calculator-type="scientific"
|
|
264
|
+
></pie-tool-calculator>
|
|
265
|
+
{/if}
|
|
266
|
+
|
|
252
267
|
{#if enabledToolsList.includes('periodicTable')}
|
|
253
268
|
<pie-tool-periodic-table
|
|
254
|
-
bind:this={periodicTableElement}
|
|
255
269
|
visible={showPeriodicTable}
|
|
256
|
-
tool-id=
|
|
270
|
+
tool-id={toScopedToolId('periodicTable')}
|
|
257
271
|
></pie-tool-periodic-table>
|
|
258
272
|
{/if}
|
|
259
273
|
|
|
260
274
|
{#if enabledToolsList.includes('protractor')}
|
|
261
275
|
<pie-tool-protractor
|
|
262
|
-
bind:this={protractorElement}
|
|
263
276
|
visible={showProtractor}
|
|
264
|
-
tool-id=
|
|
277
|
+
tool-id={toScopedToolId('protractor')}
|
|
265
278
|
></pie-tool-protractor>
|
|
266
279
|
{/if}
|
|
267
280
|
|
|
268
281
|
{#if enabledToolsList.includes('lineReader')}
|
|
269
282
|
<pie-tool-line-reader
|
|
270
|
-
bind:this={lineReaderElement}
|
|
271
283
|
visible={showLineReader}
|
|
272
|
-
tool-id=
|
|
284
|
+
tool-id={toScopedToolId('lineReader')}
|
|
273
285
|
></pie-tool-line-reader>
|
|
274
286
|
{/if}
|
|
275
287
|
|
|
276
|
-
{#if enabledToolsList.includes('magnifier')}
|
|
277
|
-
<pie-tool-magnifier
|
|
278
|
-
bind:this={magnifierElement}
|
|
279
|
-
visible={showMagnifier}
|
|
280
|
-
tool-id="magnifier"
|
|
281
|
-
></pie-tool-magnifier>
|
|
282
|
-
{/if}
|
|
283
|
-
|
|
284
288
|
{#if enabledToolsList.includes('ruler')}
|
|
285
289
|
<pie-tool-ruler
|
|
286
|
-
bind:this={rulerElement}
|
|
287
290
|
visible={showRuler}
|
|
288
|
-
tool-id=
|
|
291
|
+
tool-id={toScopedToolId('ruler')}
|
|
289
292
|
></pie-tool-ruler>
|
|
290
293
|
{/if}
|
|
291
294
|
|
|
@@ -374,7 +377,7 @@
|
|
|
374
377
|
transition: all 0.15s ease;
|
|
375
378
|
}
|
|
376
379
|
|
|
377
|
-
.tool-button svg {
|
|
380
|
+
.tool-button :global(svg) {
|
|
378
381
|
width: 100%;
|
|
379
382
|
height: 100%;
|
|
380
383
|
}
|