@pie-players/pie-tool-periodic-table 0.3.42 → 0.3.44

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/index.d.ts CHANGED
@@ -5,4 +5,3 @@
5
5
  * Import the built version for CDN usage, or the .svelte source for Svelte projects.
6
6
  */
7
7
  export {};
8
- //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-players/pie-tool-periodic-table",
3
- "version": "0.3.42",
3
+ "version": "0.3.44",
4
4
  "type": "module",
5
5
  "description": "Interactive periodic table reference tool for PIE assessment player",
6
6
  "repository": {
@@ -19,18 +19,15 @@
19
19
  "chemistry",
20
20
  "reference"
21
21
  ],
22
- "svelte": "./tool-periodic-table.svelte",
23
22
  "main": "./dist/tool-periodic-table.js",
24
23
  "exports": {
25
24
  ".": {
26
25
  "types": "./dist/index.d.ts",
27
- "import": "./dist/tool-periodic-table.js",
28
- "svelte": "./tool-periodic-table.svelte"
26
+ "import": "./dist/tool-periodic-table.js"
29
27
  }
30
28
  },
31
29
  "files": [
32
30
  "dist",
33
- "tool-periodic-table.svelte",
34
31
  "periodic-table-data.json",
35
32
  "package.json"
36
33
  ],
@@ -38,9 +35,9 @@
38
35
  "unpkg": "./dist/tool-periodic-table.js",
39
36
  "jsdelivr": "./dist/tool-periodic-table.js",
40
37
  "dependencies": {
41
- "@pie-players/pie-assessment-toolkit": "0.3.42",
42
- "@pie-players/pie-context": "0.3.42",
43
- "@pie-players/pie-players-shared": "0.3.42"
38
+ "@pie-players/pie-assessment-toolkit": "0.3.44",
39
+ "@pie-players/pie-context": "0.3.44",
40
+ "@pie-players/pie-players-shared": "0.3.44"
44
41
  },
45
42
  "types": "./dist/index.d.ts",
46
43
  "scripts": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,600 +0,0 @@
1
- <svelte:options
2
- customElement={{
3
- tag: 'pie-tool-periodic-table',
4
- shadow: 'open',
5
- props: {
6
- visible: { type: 'Boolean', attribute: 'visible' },
7
- toolId: { type: 'String', attribute: 'tool-id' }
8
- }
9
- }}
10
- />
11
-
12
- <script lang="ts">
13
-
14
- import periodicTableData from './periodic-table-data.json';
15
-
16
- // TypeScript interface matching production data structure
17
- interface Element {
18
- name: string;
19
- atomic_mass: number;
20
- category: string;
21
- number: number;
22
- period: number;
23
- group: number;
24
- phase: string;
25
- symbol: string;
26
- xpos: number;
27
- ypos: number;
28
- electron_configuration_semantic: string;
29
- }
30
-
31
- // Props
32
- let {
33
- visible = false,
34
- toolId = 'periodicTable'
35
- }: {
36
- visible?: boolean;
37
- toolId?: string;
38
- } = $props();
39
-
40
- // Get all elements from production JSON data
41
- const allElements: Element[] = (periodicTableData as any).elements;
42
-
43
- // Tool state
44
- let selectedElement = $state<Element | null>(allElements[0] || null); // Initialize with Hydrogen
45
- let selectedCategory = $state<string>('All');
46
-
47
- /**
48
- * Normalize category name (matching production implementation)
49
- */
50
- function normalizeCategory(category: string): string {
51
- const lower = category.toLowerCase();
52
- if (lower.indexOf('unknown') !== -1) {
53
- return 'Unknown';
54
- }
55
- // Map common category names to standard format
56
- const mappings: Record<string, string> = {
57
- 'alkali metal': 'Alkali Metal',
58
- 'alkaline earth': 'Alkaline Earth Metal',
59
- 'alkaline earth metal': 'Alkaline Earth Metal',
60
- 'transition metal': 'Transition Metal',
61
- 'post-transition metal': 'Post-transition Metal',
62
- 'metalloid': 'Metalloid',
63
- 'nonmetal': 'Diatomic Nonmetal',
64
- 'polyatomic nonmetal': 'Polyatomic Nonmetal',
65
- 'diatomic nonmetal': 'Diatomic Nonmetal',
66
- 'halogen': 'Diatomic Nonmetal', // Halogens are diatomic nonmetals
67
- 'noble gas': 'Noble Gas',
68
- 'lanthanide': 'Lanthanide',
69
- 'actinide': 'Actinide',
70
- 'metal': 'Post-transition Metal' // Some elements might just be 'metal'
71
- };
72
- return mappings[lower] || category;
73
- }
74
-
75
- /**
76
- * Format category name for display
77
- */
78
- function formatCategoryName(category: string): string {
79
- return category
80
- .split(' ')
81
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
82
- .join(' ');
83
- }
84
-
85
- // Use xpos/ypos directly from production data (no calculation needed)
86
-
87
- /**
88
- * Get unique normalized categories
89
- */
90
- let uniqueCategories = $derived.by(() => {
91
- const categories = new Set<string>();
92
- allElements.forEach((element) => {
93
- if (element.category) {
94
- categories.add(normalizeCategory(element.category));
95
- }
96
- });
97
- return Array.from(categories).sort();
98
- });
99
-
100
- /**
101
- * Filter elements by category
102
- */
103
- let displayedElements: Element[] = $derived.by(() => {
104
- if (selectedCategory === 'All') {
105
- return allElements;
106
- }
107
- return allElements.filter(
108
- (element: Element) => normalizeCategory(element.category) === selectedCategory
109
- );
110
- });
111
-
112
- /**
113
- * Select element
114
- */
115
- function showElementDetails(element: Element) {
116
- selectedElement = element;
117
- }
118
-
119
- /**
120
- * Set category filter
121
- */
122
- function setCategory(category: string) {
123
- selectedCategory = category;
124
- }
125
-
126
- </script>
127
-
128
- {#if visible}
129
- <div
130
- class="pie-tool-periodic-table"
131
- role="dialog"
132
- tabindex="-1"
133
- aria-label="Periodic Table - Click elements to view details"
134
- data-tool-id={toolId}
135
- >
136
- <!-- Content wrapper -->
137
- <div class="pie-tool-periodic-table__content">
138
- <div class="pie-tool-periodic-table__wrapper">
139
- <!-- Main grid -->
140
- <div
141
- class="pie-tool-periodic-table__grid"
142
- role="grid"
143
- aria-label="Periodic table elements"
144
- >
145
- <!-- Category filter badges in row 1 (matching production implementation) -->
146
- <div
147
- class="pie-tool-periodic-table__category-header pie-tool-periodic-table__category-badge-row"
148
- role="presentation"
149
- style="grid-row: 1; grid-column: 2 / span 16;"
150
- >
151
- <!-- "All" category -->
152
- <button
153
- class="pie-tool-periodic-table__category-badge"
154
- class:pie-tool-periodic-table__category-badge--active={selectedCategory === 'All'}
155
- onclick={() => setCategory('All')}
156
- aria-label="Show all elements"
157
- aria-pressed={selectedCategory === 'All'}
158
- >
159
- All Elements
160
- </button>
161
-
162
- <!-- Each category badge -->
163
- {#each uniqueCategories as category (category)}
164
- <button
165
- class="pie-tool-periodic-table__category-badge pie-tool-periodic-table__category--{category.replace(' ', '-').toLowerCase()}"
166
- class:pie-tool-periodic-table__category-badge--active={selectedCategory === category}
167
- onclick={() => setCategory(category)}
168
- aria-label="Filter by {category}"
169
- aria-pressed={selectedCategory === category}
170
- >
171
- {formatCategoryName(category)}
172
- </button>
173
- {/each}
174
- </div>
175
-
176
- <!-- Element overview section (rows 2-3, matching production implementation) -->
177
- {#if selectedElement}
178
- <div
179
- class="pie-tool-periodic-table__element-overview"
180
- style="grid-row: 2 / span 2; grid-column: 3 / span 10;"
181
- aria-live="polite"
182
- >
183
- <div
184
- class="pie-tool-periodic-table__selected-element pie-tool-periodic-table__selected-grid pie-tool-periodic-table__category--{normalizeCategory(selectedElement.category).replace(' ', '-').toLowerCase()}"
185
- >
186
- <!-- LEFT COLUMN: Large Symbol & Element Name -->
187
- <div class="pie-tool-periodic-table__left-col">
188
- <div class="pie-tool-periodic-table__symbol-center">{selectedElement.symbol}</div>
189
- <div class="pie-tool-periodic-table__element-name">{selectedElement.name}</div>
190
- </div>
191
-
192
- <!-- RIGHT COLUMN: Two rows with additional info -->
193
- <div class="pie-tool-periodic-table__right-col">
194
- <!-- TOP ROW: Atomic Mass, Atomic No -->
195
- <div class="pie-tool-periodic-table__top-row">
196
- <div class="pie-tool-periodic-table__info-block">
197
- <div class="pie-tool-periodic-table__label">Atomic Mass</div>
198
- <div class="pie-tool-periodic-table__value">{selectedElement.atomic_mass}</div>
199
- </div>
200
- <div class="pie-tool-periodic-table__info-block">
201
- <div class="pie-tool-periodic-table__label">Atomic No</div>
202
- <div class="pie-tool-periodic-table__value">{selectedElement.number}</div>
203
- </div>
204
- </div>
205
- <!-- BOTTOM ROW: Electron Configuration, Phase -->
206
- <div class="pie-tool-periodic-table__bottom-row">
207
- <div class="pie-tool-periodic-table__info-block">
208
- <div class="pie-tool-periodic-table__label">Electron Config</div>
209
- <div class="pie-tool-periodic-table__value">{selectedElement.electron_configuration_semantic}</div>
210
- </div>
211
- <div class="pie-tool-periodic-table__info-block">
212
- <div class="pie-tool-periodic-table__label">Phase</div>
213
- <div class="pie-tool-periodic-table__value">{selectedElement.phase}</div>
214
- </div>
215
- </div>
216
- </div>
217
- </div>
218
- </div>
219
- {/if}
220
-
221
- <!-- Periodic elements -->
222
- {#each displayedElements as element (element.symbol)}
223
- <button
224
- class="pie-tool-periodic-table__element pie-tool-periodic-table__category--{normalizeCategory(element.category).replace(' ', '-').toLowerCase()}"
225
- class:pie-tool-periodic-table__element--selected={selectedElement?.symbol === element.symbol}
226
- class:pie-tool-periodic-table__element--dim={selectedCategory !== 'All' && normalizeCategory(element.category) !== selectedCategory}
227
- style="grid-row: {element.ypos}; grid-column: {element.xpos};"
228
- tabindex="0"
229
- onclick={() => showElementDetails(element)}
230
- onkeydown={(e) => {
231
- if (e.key === 'Enter' || e.key === ' ') {
232
- e.preventDefault();
233
- showElementDetails(element);
234
- }
235
- }}
236
- title={element.name}
237
- aria-label="{element.name}, Symbol: {element.symbol}, Atomic number: {element.number}, Atomic mass: {element.atomic_mass.toFixed(3)}, Category: {element.category}"
238
- >
239
- <div class="pie-tool-periodic-table__atomic-number">{element.number}</div>
240
- <div class="pie-tool-periodic-table__symbol">{element.symbol}</div>
241
- <div class="pie-tool-periodic-table__name">{element.name}</div>
242
- <div class="pie-tool-periodic-table__atomic-mass">{element.atomic_mass.toFixed(3)}</div>
243
- </button>
244
- {/each}
245
- </div>
246
-
247
- <!-- Overlay for Group (Column) Labels -->
248
- <div class="pie-tool-periodic-table__group-labels" aria-hidden="true">
249
- {#each Array(18) as _, i}
250
- <div
251
- class="pie-tool-periodic-table__group-label"
252
- style="left: {(i) * (100 / 18)}%; width: {100 / 18}%;"
253
- >
254
- {i + 1}
255
- </div>
256
- {/each}
257
- </div>
258
-
259
- <!-- Overlay for Period (Row) Labels -->
260
- <!-- Covers the 10 grid rows: rows 1-3 are UI (no labels), rows 4-8 are periods 1-5, rows 9-10 are periods 6-7 -->
261
- <div class="pie-tool-periodic-table__period-labels" aria-hidden="true">
262
- {#each Array(10) as _, i}
263
- <div class="pie-tool-periodic-table__period-label">
264
- {#if i < 3}
265
- <!-- Rows 1-3: Category badges and overview (no period label) -->
266
-
267
- {:else if i === 8}
268
- <!-- Row 9 = Period 6 -->
269
- 6
270
- {:else if i === 9}
271
- <!-- Row 10 = Period 7 -->
272
- 7
273
- {:else}
274
- <!-- Rows 4-8 = Periods 1-5 -->
275
- {i - 2}
276
- {/if}
277
- </div>
278
- {/each}
279
- </div>
280
- </div>
281
- </div>
282
- </div>
283
- {/if}
284
-
285
- <style>
286
- .pie-tool-periodic-table {
287
- position: relative;
288
- background: var(--pie-background, #fff);
289
- color: var(--pie-text, #111827);
290
- width: 100%;
291
- height: 100%;
292
- min-height: 0;
293
- display: flex;
294
- flex-direction: column;
295
- overflow: hidden;
296
- }
297
-
298
- /* Content wrapper */
299
- .pie-tool-periodic-table__content {
300
- flex: 1;
301
- display: flex;
302
- flex-direction: column;
303
- min-height: 0;
304
- overflow: auto;
305
- padding: 10px 10px 0 16px; /* top | right | bottom | left */
306
- }
307
-
308
- /* Wrapper needed for absolute positioning of overlays */
309
- .pie-tool-periodic-table__wrapper {
310
- position: relative;
311
- }
312
-
313
- /* Main grid layout */
314
- .pie-tool-periodic-table__grid {
315
- display: grid;
316
- grid-gap: 3px;
317
- grid-template-columns: repeat(18, minmax(35px, 1fr));
318
- grid-template-rows: repeat(10, minmax(35px, 1fr));
319
- margin: 0 auto;
320
- width: 100%;
321
- }
322
-
323
- /* Category badge row (matching production implementation) */
324
- .pie-tool-periodic-table__category-header.pie-tool-periodic-table__category-badge-row {
325
- align-items: center;
326
- background-color: transparent;
327
- display: flex;
328
- flex-wrap: wrap;
329
- gap: 6px;
330
- justify-content: center;
331
- padding: 0.5rem;
332
- }
333
-
334
- .pie-tool-periodic-table__category-badge {
335
- border: 1px solid color-mix(in srgb, var(--pie-border-dark, #000) 12%, transparent);
336
- border-radius: 1rem;
337
- cursor: pointer;
338
- font-size: 0.7rem;
339
- line-height: 1;
340
- padding: 4px 6px;
341
- transition: background-color 0.2s ease, color 0.2s ease;
342
- white-space: nowrap;
343
- background: var(--pie-button-bg, #fff);
344
- color: var(--pie-button-color, var(--pie-text, #333));
345
- }
346
-
347
- .pie-tool-periodic-table__category-badge:hover {
348
- background: var(--pie-button-hover-bg, #f3f4f6);
349
- }
350
-
351
- .pie-tool-periodic-table__category-badge.pie-tool-periodic-table__category-badge--active {
352
- background-color: var(--pie-primary-dark, #2c3e50);
353
- border-color: var(--pie-primary-dark, #2c3e50);
354
- color: var(--pie-white, #fff);
355
- }
356
-
357
- /* Element overview section (matching production implementation) */
358
- .pie-tool-periodic-table__element-overview {
359
- align-items: center;
360
- display: flex;
361
- height: 100%;
362
- justify-content: center;
363
- padding: 6px;
364
- z-index: 2;
365
- }
366
-
367
- .pie-tool-periodic-table__selected-element.pie-tool-periodic-table__selected-grid {
368
- align-items: center;
369
- border: 2px solid var(--pie-border-dark, #000);
370
- border-radius: 8px;
371
- box-sizing: border-box;
372
- display: flex;
373
- gap: 16px;
374
- padding: 12px;
375
- background: var(--pie-background, #fff);
376
- }
377
-
378
- .pie-tool-periodic-table__left-col {
379
- align-items: center;
380
- display: flex;
381
- flex-direction: column;
382
- min-width: 0;
383
- }
384
-
385
- .pie-tool-periodic-table__symbol-center {
386
- font-size: 2rem;
387
- font-weight: bold;
388
- line-height: 1.2;
389
- margin-bottom: 4px;
390
- }
391
-
392
- .pie-tool-periodic-table__element-name {
393
- color: var(--pie-text, #333);
394
- font-size: 1rem;
395
- font-weight: 500;
396
- overflow: hidden;
397
- text-align: center;
398
- text-overflow: ellipsis;
399
- white-space: nowrap;
400
- }
401
-
402
- .pie-tool-periodic-table__right-col {
403
- display: flex;
404
- flex-direction: column;
405
- gap: 8px;
406
- justify-content: space-between;
407
- min-width: 0;
408
- }
409
-
410
- .pie-tool-periodic-table__top-row,
411
- .pie-tool-periodic-table__bottom-row {
412
- display: flex;
413
- gap: 8px;
414
- justify-content: space-between;
415
- min-width: 0;
416
- }
417
-
418
- .pie-tool-periodic-table__info-block {
419
- display: flex;
420
- flex-direction: column;
421
- min-width: 0;
422
- text-align: left;
423
- }
424
-
425
- .pie-tool-periodic-table__info-block .pie-tool-periodic-table__label {
426
- color: var(--pie-text, #444);
427
- font-size: 0.75rem;
428
- font-weight: bold;
429
- margin-bottom: 2px;
430
- }
431
-
432
- .pie-tool-periodic-table__info-block .pie-tool-periodic-table__value {
433
- color: var(--pie-text, #000);
434
- font-size: 0.85rem;
435
- overflow: hidden;
436
- text-overflow: ellipsis;
437
- white-space: nowrap;
438
- }
439
-
440
- /* Element styles */
441
- .pie-tool-periodic-table__element {
442
- background-color: var(--pie-background, #fff);
443
- border: 1px solid color-mix(in srgb, var(--pie-border-dark, #000) 12%, transparent);
444
- border-radius: 4px;
445
- box-sizing: border-box;
446
- cursor: pointer;
447
- display: flex;
448
- flex-direction: column;
449
- min-height: 50px;
450
- padding: 3px;
451
- position: relative;
452
- transition: transform 0.1s ease-in-out;
453
- }
454
-
455
- .pie-tool-periodic-table__element:hover {
456
- border-color: var(--pie-primary-dark, #2c3e50);
457
- transform: scale(1.03);
458
- z-index: 10;
459
- }
460
-
461
- .pie-tool-periodic-table__element:focus {
462
- outline: 2px solid var(--pie-primary-dark, #2c3e50);
463
- outline-offset: 2px;
464
- z-index: 10;
465
- }
466
-
467
- .pie-tool-periodic-table__element.pie-tool-periodic-table__element--selected {
468
- border-color: var(--pie-primary-dark, #2c3e50);
469
- box-shadow: 0 0 0 2px color-mix(in srgb, var(--pie-border-dark, #000) 12%, transparent);
470
- z-index: 11;
471
- }
472
-
473
- /* Dim out elements not in the selected category */
474
- .pie-tool-periodic-table__element.pie-tool-periodic-table__element--dim {
475
- filter: grayscale(80%);
476
- opacity: 0.4;
477
- }
478
-
479
- /* Text inside each element box */
480
- .pie-tool-periodic-table__atomic-number {
481
- font-size: 9px;
482
- opacity: 0.8;
483
- text-align: left;
484
- }
485
-
486
- .pie-tool-periodic-table__symbol {
487
- font-size: 14px;
488
- font-weight: bold;
489
- margin: 2px 0;
490
- text-align: center;
491
- }
492
-
493
- .pie-tool-periodic-table__name {
494
- font-size: 8px;
495
- opacity: 0.9;
496
- overflow: hidden;
497
- text-align: center;
498
- white-space: nowrap;
499
- }
500
-
501
- .pie-tool-periodic-table__atomic-mass {
502
- font-size: 9px;
503
- opacity: 0.8;
504
- text-align: right;
505
- }
506
-
507
- /* Overlay for Group (column) labels */
508
- .pie-tool-periodic-table__group-labels {
509
- color: var(--pie-text, #333);
510
- display: flex;
511
- font-size: 0.65rem;
512
- font-weight: bold;
513
- left: 0;
514
- pointer-events: none;
515
- position: absolute;
516
- top: -1.2em;
517
- width: 100%;
518
- }
519
-
520
- .pie-tool-periodic-table__group-label {
521
- text-align: center;
522
- }
523
-
524
- /* Overlay for Period (row) labels */
525
- .pie-tool-periodic-table__period-labels {
526
- color: var(--pie-text, #333);
527
- display: flex;
528
- flex-direction: column;
529
- font-size: 0.65rem;
530
- font-weight: bold;
531
- height: 100%;
532
- justify-content: space-evenly;
533
- left: -1.2em;
534
- pointer-events: none;
535
- position: absolute;
536
- top: 0;
537
- }
538
-
539
- .pie-tool-periodic-table__period-label {
540
- padding-right: 0.2em;
541
- text-align: right;
542
- }
543
-
544
- /* Category-based background colors (matching production implementation) */
545
- .pie-tool-periodic-table__category--alkali-metal {
546
- background-color: #ff9e9e;
547
- }
548
-
549
- .pie-tool-periodic-table__category--alkaline-earth-metal {
550
- background-color: #ffdc8a;
551
- }
552
-
553
- .pie-tool-periodic-table__category--alkaline-earth {
554
- background-color: #ffdc8a; /* Also handle without "-metal" suffix */
555
- }
556
-
557
- .pie-tool-periodic-table__category--lanthanide {
558
- background-color: #f9a8d4;
559
- }
560
-
561
- .pie-tool-periodic-table__category--actinide {
562
- background-color: #e0aaff;
563
- }
564
-
565
- .pie-tool-periodic-table__category--transition-metal {
566
- background-color: #a3d8f4;
567
- }
568
-
569
- .pie-tool-periodic-table__category--post-transition-metal {
570
- background-color: #b4f8c8;
571
- }
572
-
573
- .pie-tool-periodic-table__category--metalloid {
574
- background-color: #d9f99d;
575
- }
576
-
577
- .pie-tool-periodic-table__category--diatomic-nonmetal {
578
- background-color: #f5f5f5;
579
- }
580
-
581
- .pie-tool-periodic-table__category--noble-gas {
582
- background-color: #c4b5fd;
583
- }
584
-
585
- .pie-tool-periodic-table__category--polyatomic-nonmetal {
586
- background-color: #fbcfe8;
587
- }
588
-
589
- .pie-tool-periodic-table__category--nonmetal {
590
- background-color: #f0f0f0; /* Production implementation also has this */
591
- }
592
-
593
- .pie-tool-periodic-table__category--halogen {
594
- background-color: #8ef5d0; /* Production implementation has halogen color */
595
- }
596
-
597
- .pie-tool-periodic-table__category--unknown {
598
- background-color: #f5f5f5;
599
- }
600
- </style>