@pie-players/pie-tool-periodic-table 0.3.3 → 0.3.5
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/tool-periodic-table.js +1819 -3332
- package/package.json +9 -13
- package/tool-periodic-table.svelte +11 -209
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-players/pie-tool-periodic-table",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive periodic table reference tool for PIE assessment player",
|
|
6
6
|
"repository": {
|
|
@@ -36,17 +36,13 @@
|
|
|
36
36
|
"periodic-table-data.json",
|
|
37
37
|
"package.json"
|
|
38
38
|
],
|
|
39
|
-
"peerDependencies": {
|
|
40
|
-
"svelte": "^5.51.0"
|
|
41
|
-
},
|
|
42
39
|
"license": "MIT",
|
|
43
40
|
"unpkg": "./dist/tool-periodic-table.js",
|
|
44
41
|
"jsdelivr": "./dist/tool-periodic-table.js",
|
|
45
42
|
"dependencies": {
|
|
46
|
-
"@pie-players/pie-assessment-toolkit": "0.3.
|
|
47
|
-
"@pie-players/pie-context": "0.3.
|
|
48
|
-
"@pie-players/pie-players-shared": "0.3.
|
|
49
|
-
"daisyui": "^5.5.18"
|
|
43
|
+
"@pie-players/pie-assessment-toolkit": "0.3.5",
|
|
44
|
+
"@pie-players/pie-context": "0.3.5",
|
|
45
|
+
"@pie-players/pie-players-shared": "0.3.5"
|
|
50
46
|
},
|
|
51
47
|
"types": "./dist/index.d.ts",
|
|
52
48
|
"scripts": {
|
|
@@ -57,11 +53,11 @@
|
|
|
57
53
|
},
|
|
58
54
|
"devDependencies": {
|
|
59
55
|
"@biomejs/biome": "^2.3.10",
|
|
60
|
-
"@sveltejs/vite-plugin-svelte": "^6.
|
|
61
|
-
"svelte": "^5.
|
|
62
|
-
"typescript": "^5.
|
|
63
|
-
"vite": "^7.
|
|
64
|
-
"vite-plugin-dts": "^4.5.
|
|
56
|
+
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
57
|
+
"svelte": "^5.53.7",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"vite": "^7.3.1",
|
|
60
|
+
"vite-plugin-dts": "^4.5.4"
|
|
65
61
|
},
|
|
66
62
|
"homepage": "https://github.com/pie-framework/pie-players/tree/master/packages/tool-periodic-table#readme",
|
|
67
63
|
"bugs": {
|
|
@@ -10,17 +10,7 @@
|
|
|
10
10
|
/>
|
|
11
11
|
|
|
12
12
|
<script lang="ts">
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
connectToolRuntimeContext,
|
|
16
|
-
ZIndexLayer,
|
|
17
|
-
} from '@pie-players/pie-assessment-toolkit';
|
|
18
|
-
import type {
|
|
19
|
-
AssessmentToolkitRuntimeContext,
|
|
20
|
-
IToolCoordinator,
|
|
21
|
-
} from '@pie-players/pie-assessment-toolkit';
|
|
22
|
-
import { createFocusTrap, safeLocalStorageGet, safeLocalStorageSet } from '@pie-players/pie-players-shared';
|
|
23
|
-
import { onMount } from 'svelte';
|
|
13
|
+
|
|
24
14
|
import periodicTableData from './periodic-table-data.json';
|
|
25
15
|
|
|
26
16
|
// TypeScript interface matching production data structure
|
|
@@ -47,26 +37,6 @@ import { onMount } from 'svelte';
|
|
|
47
37
|
toolId?: string;
|
|
48
38
|
} = $props();
|
|
49
39
|
|
|
50
|
-
// Check if running in browser
|
|
51
|
-
const isBrowser = typeof window !== 'undefined';
|
|
52
|
-
|
|
53
|
-
// State
|
|
54
|
-
let containerEl = $state<HTMLDivElement | undefined>();
|
|
55
|
-
let runtimeContext = $state<AssessmentToolkitRuntimeContext | null>(null);
|
|
56
|
-
const coordinator = $derived(
|
|
57
|
-
runtimeContext?.toolCoordinator as IToolCoordinator | undefined,
|
|
58
|
-
);
|
|
59
|
-
let isDragging = $state(false);
|
|
60
|
-
let x = $state(isBrowser ? window.innerWidth / 2 : 400);
|
|
61
|
-
let y = $state(isBrowser ? window.innerHeight / 2 : 300);
|
|
62
|
-
let width = $state(1100); // Increased to show all 18 columns without horizontal scrolling
|
|
63
|
-
let height = $state(750); // Increased to show all 10 rows without vertical scrolling
|
|
64
|
-
let dragStartX = $state(0);
|
|
65
|
-
let dragStartY = $state(0);
|
|
66
|
-
|
|
67
|
-
// Track registration state
|
|
68
|
-
let registered = $state(false);
|
|
69
|
-
|
|
70
40
|
// Get all elements from production JSON data
|
|
71
41
|
const allElements: Element[] = (periodicTableData as any).elements;
|
|
72
42
|
|
|
@@ -74,13 +44,6 @@ import { onMount } from 'svelte';
|
|
|
74
44
|
let selectedElement = $state<Element | null>(allElements[0] || null); // Initialize with Hydrogen
|
|
75
45
|
let selectedCategory = $state<string>('All');
|
|
76
46
|
|
|
77
|
-
$effect(() => {
|
|
78
|
-
if (!containerEl) return;
|
|
79
|
-
return connectToolRuntimeContext(containerEl, (value: AssessmentToolkitRuntimeContext) => {
|
|
80
|
-
runtimeContext = value;
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
47
|
/**
|
|
85
48
|
* Normalize category name (matching production implementation)
|
|
86
49
|
*/
|
|
@@ -160,120 +123,16 @@ import { onMount } from 'svelte';
|
|
|
160
123
|
selectedCategory = category;
|
|
161
124
|
}
|
|
162
125
|
|
|
163
|
-
function handleClose() {
|
|
164
|
-
coordinator?.hideTool(toolId);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function handlePointerDown(e: PointerEvent) {
|
|
168
|
-
const target = e.target as HTMLElement;
|
|
169
|
-
|
|
170
|
-
// Only start drag if clicking the header
|
|
171
|
-
if (!target.closest('.pie-tool-periodic-table__header')) return;
|
|
172
|
-
|
|
173
|
-
// Don't drag if clicking buttons
|
|
174
|
-
if (target.closest('button')) return;
|
|
175
|
-
|
|
176
|
-
isDragging = true;
|
|
177
|
-
dragStartX = e.clientX - x;
|
|
178
|
-
dragStartY = e.clientY - y;
|
|
179
|
-
|
|
180
|
-
if (containerEl) {
|
|
181
|
-
containerEl.setPointerCapture(e.pointerId);
|
|
182
|
-
coordinator?.bringToFront(containerEl);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function handlePointerMove(e: PointerEvent) {
|
|
187
|
-
if (!isDragging) return;
|
|
188
|
-
|
|
189
|
-
let newX = e.clientX - dragStartX;
|
|
190
|
-
let newY = e.clientY - dragStartY;
|
|
191
|
-
|
|
192
|
-
// Keep calculator on screen
|
|
193
|
-
const halfWidth = (containerEl?.offsetWidth || width) / 2;
|
|
194
|
-
const halfHeight = (containerEl?.offsetHeight || height) / 2;
|
|
195
|
-
|
|
196
|
-
x = Math.max(halfWidth, Math.min(newX, window.innerWidth - halfWidth));
|
|
197
|
-
y = Math.max(halfHeight, Math.min(newY, window.innerHeight - halfHeight));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function handlePointerUp(e: PointerEvent) {
|
|
201
|
-
if (isDragging && containerEl) {
|
|
202
|
-
isDragging = false;
|
|
203
|
-
containerEl.releasePointerCapture(e.pointerId);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function handleKeyDown(e: KeyboardEvent) {
|
|
208
|
-
if (e.key === 'Escape') {
|
|
209
|
-
handleClose();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Register with coordinator when it becomes available
|
|
214
|
-
$effect(() => {
|
|
215
|
-
if (coordinator && toolId && !registered) {
|
|
216
|
-
if (containerEl) {
|
|
217
|
-
coordinator.registerTool(toolId, 'Periodic Table', containerEl, ZIndexLayer.MODAL);
|
|
218
|
-
} else {
|
|
219
|
-
coordinator.registerTool(toolId, 'Periodic Table', undefined, ZIndexLayer.MODAL);
|
|
220
|
-
}
|
|
221
|
-
registered = true;
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// Update element reference when container becomes available
|
|
226
|
-
$effect(() => {
|
|
227
|
-
if (coordinator && containerEl && toolId) {
|
|
228
|
-
coordinator.updateToolElement(toolId, containerEl);
|
|
229
|
-
coordinator.bringToFront(containerEl);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
onMount(() => {
|
|
234
|
-
return () => {
|
|
235
|
-
if (coordinator && toolId) {
|
|
236
|
-
coordinator.unregisterTool(toolId);
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
});
|
|
240
126
|
</script>
|
|
241
127
|
|
|
242
128
|
{#if visible}
|
|
243
129
|
<div
|
|
244
|
-
bind:this={containerEl}
|
|
245
130
|
class="pie-tool-periodic-table"
|
|
246
131
|
role="dialog"
|
|
247
132
|
tabindex="-1"
|
|
248
133
|
aria-label="Periodic Table - Click elements to view details"
|
|
249
|
-
|
|
250
|
-
onpointerdown={handlePointerDown}
|
|
251
|
-
onpointermove={handlePointerMove}
|
|
252
|
-
onpointerup={handlePointerUp}
|
|
253
|
-
onlostpointercapture={handlePointerUp}
|
|
254
|
-
onkeydown={handleKeyDown}
|
|
134
|
+
data-tool-id={toolId}
|
|
255
135
|
>
|
|
256
|
-
<!-- Header (matching production implementation: dark teal) -->
|
|
257
|
-
<div class="pie-tool-periodic-table__header">
|
|
258
|
-
<h3 id="periodic-table-title" class="pie-tool-periodic-table__title">Periodic Table</h3>
|
|
259
|
-
<div class="pie-tool-periodic-table__header-controls">
|
|
260
|
-
<button class="pie-tool-periodic-table__close-btn" onclick={handleClose} aria-label="Close periodic table">
|
|
261
|
-
<svg
|
|
262
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
263
|
-
class="h-5 w-5"
|
|
264
|
-
viewBox="0 0 20 20"
|
|
265
|
-
fill="currentColor"
|
|
266
|
-
>
|
|
267
|
-
<path
|
|
268
|
-
fill-rule="evenodd"
|
|
269
|
-
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
|
270
|
-
clip-rule="evenodd"
|
|
271
|
-
/>
|
|
272
|
-
</svg>
|
|
273
|
-
</button>
|
|
274
|
-
</div>
|
|
275
|
-
</div>
|
|
276
|
-
|
|
277
136
|
<!-- Content wrapper -->
|
|
278
137
|
<div class="pie-tool-periodic-table__content">
|
|
279
138
|
<div class="pie-tool-periodic-table__wrapper">
|
|
@@ -281,7 +140,7 @@ import { onMount } from 'svelte';
|
|
|
281
140
|
<div
|
|
282
141
|
class="pie-tool-periodic-table__grid"
|
|
283
142
|
role="grid"
|
|
284
|
-
aria-
|
|
143
|
+
aria-label="Periodic table elements"
|
|
285
144
|
>
|
|
286
145
|
<!-- Category filter badges in row 1 (matching production implementation) -->
|
|
287
146
|
<div
|
|
@@ -425,73 +284,15 @@ import { onMount } from 'svelte';
|
|
|
425
284
|
|
|
426
285
|
<style>
|
|
427
286
|
.pie-tool-periodic-table {
|
|
428
|
-
position:
|
|
287
|
+
position: relative;
|
|
429
288
|
background: var(--pie-background, #fff);
|
|
430
289
|
color: var(--pie-text, #111827);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
touch-action: none;
|
|
435
|
-
border-radius: 12px;
|
|
436
|
-
overflow: visible; /* Changed from hidden to visible to show all content without clipping */
|
|
437
|
-
z-index: 2000; /* ZIndexLayer.MODAL */
|
|
438
|
-
min-width: 1100px; /* Match default width */
|
|
290
|
+
width: 100%;
|
|
291
|
+
height: 100%;
|
|
292
|
+
min-height: 0;
|
|
439
293
|
display: flex;
|
|
440
294
|
flex-direction: column;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
/* Header (matching production implementation: dark teal) */
|
|
444
|
-
.pie-tool-periodic-table__header {
|
|
445
|
-
padding: 12px 16px;
|
|
446
|
-
background: var(--pie-primary-dark, #2c3e50); /* Dark teal-like color */
|
|
447
|
-
color: var(--pie-white, #fff);
|
|
448
|
-
display: flex;
|
|
449
|
-
justify-content: space-between;
|
|
450
|
-
align-items: center;
|
|
451
|
-
cursor: move;
|
|
452
|
-
user-select: none;
|
|
453
|
-
border-radius: 12px 12px 0 0;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
.pie-tool-periodic-table__title {
|
|
457
|
-
font-weight: 600;
|
|
458
|
-
font-size: 16px;
|
|
459
|
-
color: var(--pie-white, #fff);
|
|
460
|
-
margin: 0;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
.pie-tool-periodic-table__header-controls {
|
|
464
|
-
display: flex;
|
|
465
|
-
gap: 8px;
|
|
466
|
-
align-items: center;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
.pie-tool-periodic-table__close-btn {
|
|
470
|
-
background: transparent;
|
|
471
|
-
border: none;
|
|
472
|
-
color: var(--pie-white, #fff);
|
|
473
|
-
cursor: pointer;
|
|
474
|
-
padding: 4px;
|
|
475
|
-
display: flex;
|
|
476
|
-
align-items: center;
|
|
477
|
-
justify-content: center;
|
|
478
|
-
border-radius: 4px;
|
|
479
|
-
transition: background-color 0.2s;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
.pie-tool-periodic-table__close-btn:hover {
|
|
483
|
-
background: color-mix(in srgb, var(--pie-white, #fff) 12%, transparent);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
.pie-tool-periodic-table__close-btn:focus-visible {
|
|
487
|
-
outline: 2px solid var(--pie-primary, #3f51b5);
|
|
488
|
-
outline-offset: 2px;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
.pie-tool-periodic-table__close-btn svg {
|
|
492
|
-
width: 20px;
|
|
493
|
-
height: 20px;
|
|
494
|
-
display: block;
|
|
295
|
+
overflow: hidden;
|
|
495
296
|
}
|
|
496
297
|
|
|
497
298
|
/* Content wrapper */
|
|
@@ -499,8 +300,9 @@ import { onMount } from 'svelte';
|
|
|
499
300
|
flex: 1;
|
|
500
301
|
display: flex;
|
|
501
302
|
flex-direction: column;
|
|
502
|
-
|
|
503
|
-
|
|
303
|
+
min-height: 0;
|
|
304
|
+
overflow: auto;
|
|
305
|
+
padding: 10px 10px 0 16px; /* top | right | bottom | left */
|
|
504
306
|
}
|
|
505
307
|
|
|
506
308
|
/* Wrapper needed for absolute positioning of overlays */
|