matterviz 0.1.0 → 0.1.2
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/ControlPanel.svelte +43 -34
- package/dist/ControlPanel.svelte.d.ts +2 -1
- package/dist/api.js +12 -2
- package/dist/composition/parse.d.ts +4 -0
- package/dist/composition/parse.js +6 -6
- package/dist/element/ElementTile.svelte +58 -73
- package/dist/icons.d.ts +8 -24
- package/dist/icons.js +8 -24
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/io/decompress.d.ts +0 -1
- package/dist/io/decompress.js +1 -3
- package/dist/io/export.d.ts +5 -1
- package/dist/io/export.js +112 -101
- package/dist/io/index.d.ts +3 -0
- package/dist/io/index.js +3 -0
- package/dist/io/parse.d.ts +3 -0
- package/dist/io/parse.js +130 -1
- package/dist/labels.d.ts +4 -3
- package/dist/labels.js +38 -60
- package/dist/math.d.ts +3 -2
- package/dist/math.js +4 -2
- package/dist/plot/ColorBar.svelte +10 -9
- package/dist/plot/Histogram.svelte +319 -0
- package/dist/plot/Histogram.svelte.d.ts +40 -0
- package/dist/plot/ScatterPlot.svelte +79 -230
- package/dist/plot/ScatterPlot.svelte.d.ts +9 -4
- package/dist/plot/ScatterPlotControls.svelte +25 -34
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte +4 -4
- package/dist/plot/data-transform.d.ts +13 -0
- package/dist/plot/data-transform.js +35 -0
- package/dist/plot/formatting.d.ts +1 -0
- package/dist/plot/formatting.js +40 -0
- package/dist/plot/index.d.ts +1 -1
- package/dist/plot/index.js +1 -2
- package/dist/plot/interactions.d.ts +5 -0
- package/dist/plot/interactions.js +15 -0
- package/dist/plot/layout.d.ts +13 -0
- package/dist/plot/layout.js +14 -0
- package/dist/plot/scales.d.ts +16 -0
- package/dist/plot/scales.js +167 -0
- package/dist/structure/Bond.svelte +4 -3
- package/dist/structure/Bond.svelte.d.ts +4 -5
- package/dist/structure/Lattice.svelte +7 -8
- package/dist/structure/Structure.svelte +161 -79
- package/dist/structure/Structure.svelte.d.ts +3 -5
- package/dist/structure/StructureCard.svelte +6 -2
- package/dist/structure/StructureControls.svelte +182 -27
- package/dist/structure/StructureControls.svelte.d.ts +18 -5
- package/dist/structure/StructureLegend.svelte +13 -72
- package/dist/structure/StructureLegend.svelte.d.ts +2 -6
- package/dist/structure/StructureScene.svelte +31 -10
- package/dist/structure/StructureScene.svelte.d.ts +11 -7
- package/dist/structure/StructureSidebar.svelte +402 -0
- package/dist/structure/StructureSidebar.svelte.d.ts +9 -0
- package/dist/structure/Vector.svelte +37 -0
- package/dist/structure/Vector.svelte.d.ts +13 -0
- package/dist/structure/index.d.ts +24 -14
- package/dist/structure/index.js +33 -30
- package/dist/structure/pbc.js +3 -3
- package/dist/trajectory/Trajectory.svelte +360 -218
- package/dist/trajectory/Trajectory.svelte.d.ts +8 -4
- package/dist/trajectory/{Sidebar.svelte → TrajectorySidebar.svelte} +5 -6
- package/dist/trajectory/{Sidebar.svelte.d.ts → TrajectorySidebar.svelte.d.ts} +3 -3
- package/dist/trajectory/extract.js +24 -2
- package/dist/trajectory/index.d.ts +1 -1
- package/dist/trajectory/index.js +1 -1
- package/dist/trajectory/parse.d.ts +7 -10
- package/dist/trajectory/parse.js +597 -958
- package/dist/trajectory/plotting.d.ts +16 -5
- package/dist/trajectory/plotting.js +290 -58
- package/package.json +11 -13
- package/readme.md +20 -2
package/dist/ControlPanel.svelte
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">import { Icon } from './';
|
|
2
|
-
let { controls_open = $bindable(false), show_controls = true, controls_content, toggle_button = {}, panel_props = {}, show_toggle_button = true, open_icon = `Cross`, closed_icon = `Settings`, toggle_controls_btn,
|
|
2
|
+
let { controls_open = $bindable(false), show_controls = true, controls_content, toggle_button = {}, panel_props = {}, show_toggle_button = true, open_icon = `Cross`, closed_icon = `Settings`, toggle_controls_btn, controls_div, icon_style = `width: 24px; height: 24px`, } = $props();
|
|
3
|
+
const [panel_class, toggle_class] = [`controls-panel`, `controls-toggle`];
|
|
3
4
|
function on_keydown(event) {
|
|
4
5
|
if (event.key === `Escape`)
|
|
5
6
|
controls_open = false;
|
|
@@ -7,9 +8,20 @@ function on_keydown(event) {
|
|
|
7
8
|
function toggle_controls() {
|
|
8
9
|
controls_open = !controls_open;
|
|
9
10
|
}
|
|
11
|
+
function handle_click_outside(event) {
|
|
12
|
+
if (!controls_open)
|
|
13
|
+
return;
|
|
14
|
+
const target = event.target;
|
|
15
|
+
const control_panel = target.closest(`.${panel_class}`);
|
|
16
|
+
const toggle_btn = target.closest(`.${toggle_class}`);
|
|
17
|
+
// Don't close if clicking inside panel or on toggle button
|
|
18
|
+
if (!control_panel && !toggle_btn)
|
|
19
|
+
controls_open = false;
|
|
20
|
+
}
|
|
10
21
|
</script>
|
|
11
22
|
|
|
12
23
|
<svelte:window onkeydown={on_keydown} />
|
|
24
|
+
<svelte:document onclick={handle_click_outside} />
|
|
13
25
|
|
|
14
26
|
{#if show_controls}
|
|
15
27
|
{#if show_toggle_button}
|
|
@@ -20,21 +32,18 @@ function toggle_controls() {
|
|
|
20
32
|
aria-controls="controls-panel"
|
|
21
33
|
title={toggle_button.title ?? (controls_open ? `Close controls` : `Open controls`)}
|
|
22
34
|
{...toggle_button}
|
|
23
|
-
class="
|
|
35
|
+
class="{toggle_class} {toggle_button.class ?? ``}"
|
|
24
36
|
>
|
|
25
|
-
<Icon
|
|
26
|
-
icon={controls_open ? open_icon : closed_icon}
|
|
27
|
-
style="width: 24px; height: 24px"
|
|
28
|
-
/>
|
|
37
|
+
<Icon icon={controls_open ? open_icon : closed_icon} style={icon_style} />
|
|
29
38
|
</button>
|
|
30
39
|
{/if}
|
|
31
40
|
|
|
32
41
|
<div
|
|
33
42
|
class:controls-open={controls_open}
|
|
34
|
-
bind:this={
|
|
43
|
+
bind:this={controls_div}
|
|
35
44
|
role="dialog"
|
|
36
45
|
{...panel_props}
|
|
37
|
-
class="
|
|
46
|
+
class="{panel_class} {panel_props.class ?? ``}"
|
|
38
47
|
>
|
|
39
48
|
{#if controls_content}
|
|
40
49
|
{@render controls_content()}
|
|
@@ -45,16 +54,18 @@ function toggle_controls() {
|
|
|
45
54
|
<style>
|
|
46
55
|
.controls-toggle {
|
|
47
56
|
background-color: transparent;
|
|
48
|
-
|
|
49
|
-
height:
|
|
50
|
-
padding: 0.125rem 0.25rem;
|
|
51
|
-
font-size: 0.8rem;
|
|
57
|
+
width: 30px;
|
|
58
|
+
height: 30px;
|
|
52
59
|
box-sizing: border-box;
|
|
60
|
+
display: flex;
|
|
61
|
+
place-items: center;
|
|
62
|
+
padding: 4pt 4pt;
|
|
63
|
+
border-radius: 50%;
|
|
53
64
|
}
|
|
54
65
|
.controls-toggle:hover {
|
|
55
|
-
background-color:
|
|
66
|
+
background-color: rgba(255, 255, 255, 0.1);
|
|
56
67
|
}
|
|
57
|
-
.controls {
|
|
68
|
+
.controls-panel {
|
|
58
69
|
position: absolute;
|
|
59
70
|
left: unset;
|
|
60
71
|
background: transparent;
|
|
@@ -62,16 +73,14 @@ function toggle_controls() {
|
|
|
62
73
|
display: grid;
|
|
63
74
|
gap: var(--controls-gap, 4pt);
|
|
64
75
|
text-align: var(--controls-text-align, left);
|
|
65
|
-
transition:
|
|
66
|
-
visibility var(--controls-transition-duration, 0.3s),
|
|
67
|
-
opacity var(--controls-transition-duration, 0.3s);
|
|
76
|
+
transition: var(--controls-transition, 0.3s);
|
|
68
77
|
box-sizing: border-box;
|
|
69
|
-
top: var(--controls-top,
|
|
78
|
+
top: var(--controls-top, 20pt);
|
|
70
79
|
right: var(--controls-right, 6pt);
|
|
71
80
|
background: var(--controls-bg, rgba(10, 10, 10, 0.95));
|
|
72
81
|
padding: var(--controls-padding, 6pt 9pt);
|
|
73
82
|
border-radius: var(--controls-border-radius, 3pt);
|
|
74
|
-
width: var(--controls-width,
|
|
83
|
+
width: var(--controls-width, 28em);
|
|
75
84
|
max-width: var(--controls-max-width, 90cqw);
|
|
76
85
|
color: var(--controls-text-color);
|
|
77
86
|
overflow: auto;
|
|
@@ -81,31 +90,31 @@ function toggle_controls() {
|
|
|
81
90
|
z-index: var(--controls-z-index, 1);
|
|
82
91
|
pointer-events: none;
|
|
83
92
|
}
|
|
84
|
-
.controls.controls-open {
|
|
93
|
+
.controls-panel.controls-open {
|
|
85
94
|
visibility: visible !important;
|
|
86
95
|
opacity: 1 !important;
|
|
87
96
|
pointer-events: auto !important;
|
|
88
97
|
}
|
|
89
|
-
.controls :global(hr) {
|
|
98
|
+
.controls-panel :global(hr) {
|
|
90
99
|
border: none;
|
|
91
100
|
background: var(--controls-hr-bg, gray);
|
|
92
101
|
margin: var(--controls-hr-margin, 0);
|
|
93
102
|
height: var(--controls-hr-height, 0.5px);
|
|
94
103
|
}
|
|
95
|
-
.controls :global(label) {
|
|
104
|
+
.controls-panel :global(label) {
|
|
96
105
|
display: flex;
|
|
97
106
|
align-items: center;
|
|
98
107
|
gap: var(--controls-label-gap, 2pt);
|
|
99
108
|
}
|
|
100
|
-
.controls :global(input[type='range']) {
|
|
109
|
+
.controls-panel :global(input[type='range']) {
|
|
101
110
|
margin-left: auto;
|
|
102
111
|
width: var(--controls-input-range-width, 100px);
|
|
103
112
|
flex-shrink: 0;
|
|
104
113
|
}
|
|
105
|
-
.controls :global(.slider-control input[type='range']) {
|
|
114
|
+
.controls-panel :global(.slider-control input[type='range']) {
|
|
106
115
|
margin-left: 0;
|
|
107
116
|
}
|
|
108
|
-
.controls :global(input[type='number']) {
|
|
117
|
+
.controls-panel :global(input[type='number']) {
|
|
109
118
|
box-sizing: border-box;
|
|
110
119
|
text-align: center;
|
|
111
120
|
border-radius: var(--controls-input-num-border-radius, 3pt);
|
|
@@ -116,43 +125,43 @@ function toggle_controls() {
|
|
|
116
125
|
margin-left: var(--controls-input-num-margin-left, 6pt);
|
|
117
126
|
flex-shrink: 0;
|
|
118
127
|
}
|
|
119
|
-
.controls :global(input::-webkit-inner-spin-button) {
|
|
128
|
+
.controls-panel :global(input::-webkit-inner-spin-button) {
|
|
120
129
|
display: none;
|
|
121
130
|
}
|
|
122
|
-
.controls :global(button) {
|
|
131
|
+
.controls-panel :global(button) {
|
|
123
132
|
width: max-content;
|
|
124
133
|
background-color: var(--controls-btn-bg, rgba(255, 255, 255, 0.2));
|
|
125
134
|
}
|
|
126
|
-
.controls :global(select) {
|
|
135
|
+
.controls-panel :global(select) {
|
|
127
136
|
margin: var(--controls-select-margin, 0 0 0 5pt);
|
|
128
137
|
color: var(--controls-select-color, white);
|
|
129
138
|
background-color: var(--controls-select-bg, rgba(255, 255, 255, 0.1));
|
|
130
139
|
}
|
|
131
|
-
.controls :global(input[type='color']) {
|
|
140
|
+
.controls-panel :global(input[type='color']) {
|
|
132
141
|
width: var(--input-color-width, 40px);
|
|
133
142
|
height: var(--input-color-height, 16px);
|
|
134
143
|
margin: var(--input-color-margin, 0 0 0 5pt);
|
|
135
144
|
border: var(--input-color-border, 1px solid rgba(255, 255, 255, 0.05));
|
|
136
145
|
box-sizing: border-box;
|
|
137
146
|
}
|
|
138
|
-
.controls :global(.section-heading) {
|
|
147
|
+
.controls-panel :global(.section-heading) {
|
|
139
148
|
margin: 8pt 0 2pt;
|
|
140
149
|
font-size: 0.9em;
|
|
141
150
|
color: var(--text-muted, #ccc);
|
|
142
151
|
}
|
|
143
|
-
.controls :global(.control-row) {
|
|
152
|
+
.controls-panel :global(.control-row) {
|
|
144
153
|
display: flex;
|
|
145
154
|
gap: 4pt;
|
|
146
155
|
align-items: flex-start;
|
|
147
156
|
}
|
|
148
|
-
.controls :global(.control-row label) {
|
|
157
|
+
.controls-panel :global(.control-row label) {
|
|
149
158
|
min-width: 0;
|
|
150
159
|
}
|
|
151
|
-
.controls :global(.control-row label.compact) {
|
|
160
|
+
.controls-panel :global(.control-row label.compact) {
|
|
152
161
|
flex: 0 0 auto;
|
|
153
162
|
margin-right: 8pt;
|
|
154
163
|
}
|
|
155
|
-
.controls :global(.control-row label.slider-control) {
|
|
164
|
+
.controls-panel :global(.control-row label.slider-control) {
|
|
156
165
|
flex: 1;
|
|
157
166
|
}
|
|
158
167
|
</style>
|
|
@@ -11,7 +11,8 @@ interface Props {
|
|
|
11
11
|
open_icon?: IconName;
|
|
12
12
|
closed_icon?: IconName;
|
|
13
13
|
toggle_controls_btn?: HTMLButtonElement;
|
|
14
|
-
|
|
14
|
+
controls_div?: HTMLDivElement;
|
|
15
|
+
icon_style?: string;
|
|
15
16
|
}
|
|
16
17
|
declare const ControlPanel: import("svelte").Component<Props, {}, "controls_open">;
|
|
17
18
|
type ControlPanel = ReturnType<typeof ControlPanel>;
|
package/dist/api.js
CHANGED
|
@@ -15,8 +15,8 @@ export async function fetch_zipped(url, { unzip = true } = {}) {
|
|
|
15
15
|
return (await response.blob());
|
|
16
16
|
return JSON.parse(await decompress(response.body));
|
|
17
17
|
}
|
|
18
|
-
//
|
|
19
|
-
|
|
18
|
+
// Original download implementation
|
|
19
|
+
function default_download(data, filename, type) {
|
|
20
20
|
const file = new Blob([data], { type });
|
|
21
21
|
const link = document.createElement(`a`);
|
|
22
22
|
const url = URL.createObjectURL(file);
|
|
@@ -28,3 +28,13 @@ export function download(data, filename, type) {
|
|
|
28
28
|
link.remove();
|
|
29
29
|
URL.revokeObjectURL(url);
|
|
30
30
|
}
|
|
31
|
+
// Function to download data to a file - checks for global override first
|
|
32
|
+
export function download(data, filename, type) {
|
|
33
|
+
// Check if there's a global download override (used by VSCode extension)
|
|
34
|
+
const global_download = globalThis.download;
|
|
35
|
+
if (typeof global_download === `function` && global_download !== download) {
|
|
36
|
+
return global_download(data, filename, type);
|
|
37
|
+
}
|
|
38
|
+
// Use default browser download
|
|
39
|
+
return default_download(data, filename, type);
|
|
40
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { CompositionType, ElementSymbol } from '..';
|
|
2
|
+
export declare const atomic_number_to_symbol: Partial<Record<number, ElementSymbol>>;
|
|
3
|
+
export declare const symbol_to_atomic_number: Partial<Record<ElementSymbol, number>>;
|
|
4
|
+
export declare const atomic_weights: Map<"K" | "H" | "He" | "Li" | "Be" | "B" | "C" | "N" | "O" | "F" | "Ne" | "Na" | "Mg" | "Al" | "Si" | "P" | "S" | "Cl" | "Ar" | "Ca" | "Sc" | "Ti" | "V" | "Cr" | "Mn" | "Fe" | "Co" | "Ni" | "Cu" | "Zn" | "Ga" | "Ge" | "As" | "Se" | "Br" | "Kr" | "Rb" | "Sr" | "Y" | "Zr" | "Nb" | "Mo" | "Tc" | "Ru" | "Rh" | "Pd" | "Ag" | "Cd" | "In" | "Sn" | "Sb" | "Te" | "I" | "Xe" | "Cs" | "Ba" | "La" | "Ce" | "Pr" | "Nd" | "Pm" | "Sm" | "Eu" | "Gd" | "Tb" | "Dy" | "Ho" | "Er" | "Tm" | "Yb" | "Lu" | "Hf" | "Ta" | "W" | "Re" | "Os" | "Ir" | "Pt" | "Au" | "Hg" | "Tl" | "Pb" | "Bi" | "Po" | "At" | "Rn" | "Fr" | "Ra" | "Ac" | "Th" | "Pa" | "U" | "Np" | "Pu" | "Am" | "Cm" | "Bk" | "Cf" | "Es" | "Fm" | "Md" | "No" | "Lr" | "Rf" | "Db" | "Sg" | "Bh" | "Hs" | "Mt" | "Ds" | "Rg" | "Cn" | "Nh" | "Fl" | "Mc" | "Lv" | "Ts" | "Og", number>;
|
|
5
|
+
export declare const element_electronegativity_map: Map<"K" | "H" | "He" | "Li" | "Be" | "B" | "C" | "N" | "O" | "F" | "Ne" | "Na" | "Mg" | "Al" | "Si" | "P" | "S" | "Cl" | "Ar" | "Ca" | "Sc" | "Ti" | "V" | "Cr" | "Mn" | "Fe" | "Co" | "Ni" | "Cu" | "Zn" | "Ga" | "Ge" | "As" | "Se" | "Br" | "Kr" | "Rb" | "Sr" | "Y" | "Zr" | "Nb" | "Mo" | "Tc" | "Ru" | "Rh" | "Pd" | "Ag" | "Cd" | "In" | "Sn" | "Sb" | "Te" | "I" | "Xe" | "Cs" | "Ba" | "La" | "Ce" | "Pr" | "Nd" | "Pm" | "Sm" | "Eu" | "Gd" | "Tb" | "Dy" | "Ho" | "Er" | "Tm" | "Yb" | "Lu" | "Hf" | "Ta" | "W" | "Re" | "Os" | "Ir" | "Pt" | "Au" | "Hg" | "Tl" | "Pb" | "Bi" | "Po" | "At" | "Rn" | "Fr" | "Ra" | "Ac" | "Th" | "Pa" | "U" | "Np" | "Pu" | "Am" | "Cm" | "Bk" | "Cf" | "Es" | "Fm" | "Md" | "No" | "Lr" | "Rf" | "Db" | "Sg" | "Bh" | "Hs" | "Mt" | "Ds" | "Rg" | "Cn" | "Nh" | "Fl" | "Mc" | "Lv" | "Ts" | "Og", number>;
|
|
2
6
|
export declare function atomic_number_to_element_symbol(atomic_number: number): ElementSymbol | null;
|
|
3
7
|
export declare function element_symbol_to_atomic_number(symbol: ElementSymbol): number | null;
|
|
4
8
|
export declare function convert_atomic_numbers_to_symbols(atomic_composition: Record<number, number>): CompositionType;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { elem_symbols } from '..';
|
|
2
2
|
import element_data from '../element/data';
|
|
3
3
|
// Create a mapping from atomic numbers to element symbols
|
|
4
|
-
const atomic_number_to_symbol = {};
|
|
5
|
-
const symbol_to_atomic_number = {};
|
|
4
|
+
export const atomic_number_to_symbol = {};
|
|
5
|
+
export const symbol_to_atomic_number = {};
|
|
6
6
|
// Create mass/electronegativity maps for O(1) lookups in loops below
|
|
7
|
-
const
|
|
8
|
-
const element_electronegativity_map = new Map();
|
|
7
|
+
export const atomic_weights = new Map();
|
|
8
|
+
export const element_electronegativity_map = new Map();
|
|
9
9
|
// Populate maps at module load time
|
|
10
10
|
for (const element of element_data) {
|
|
11
11
|
atomic_number_to_symbol[element.number] = element.symbol;
|
|
12
12
|
symbol_to_atomic_number[element.symbol] = element.number;
|
|
13
|
-
|
|
13
|
+
atomic_weights.set(element.symbol, element.atomic_mass);
|
|
14
14
|
element_electronegativity_map.set(element.symbol, element.electronegativity ?? 0);
|
|
15
15
|
}
|
|
16
16
|
// Convert atomic number to element symbol
|
|
@@ -134,7 +134,7 @@ export function composition_to_percentages(composition, by_weight = false) {
|
|
|
134
134
|
// Calculate weight for each element
|
|
135
135
|
for (const [element, amount] of Object.entries(composition)) {
|
|
136
136
|
if (typeof amount === `number` && amount > 0) {
|
|
137
|
-
const atomic_mass =
|
|
137
|
+
const atomic_mass = atomic_weights.get(element);
|
|
138
138
|
if (atomic_mass === undefined) {
|
|
139
139
|
throw new Error(`Unknown element: ${element}`);
|
|
140
140
|
}
|
|
@@ -8,14 +8,14 @@ let category = $derived(element.category.replaceAll(` `, `-`));
|
|
|
8
8
|
// background color defaults to category color (initialized in colors/index.ts, user editable in PeriodicTableControls.svelte)
|
|
9
9
|
let fallback_bg_color = $derived(bg_color ?? default_category_colors[category] ?? `var(--${category}-bg-color)`);
|
|
10
10
|
let contrast_bg_color = $derived(bg_color ?? default_category_colors[category]);
|
|
11
|
-
// Determine if we should show the atomic number
|
|
11
|
+
// Determine if we should show the atomic number
|
|
12
12
|
const should_show_number = $derived.by(() => {
|
|
13
13
|
if (show_number !== undefined)
|
|
14
14
|
return show_number;
|
|
15
|
-
//
|
|
15
|
+
// Hide number for multi-value splits to prevent overlap with value labels
|
|
16
16
|
if (Array.isArray(value) && value.length > 1)
|
|
17
17
|
return false;
|
|
18
|
-
return true;
|
|
18
|
+
return true;
|
|
19
19
|
});
|
|
20
20
|
// Helper function to format values appropriately
|
|
21
21
|
const format_value = (val) => {
|
|
@@ -40,84 +40,69 @@ const format_value = (val) => {
|
|
|
40
40
|
const should_show_values = $derived.by(() => {
|
|
41
41
|
if (show_values !== undefined)
|
|
42
42
|
return show_values;
|
|
43
|
-
if (Array.isArray(value))
|
|
43
|
+
if (Array.isArray(value))
|
|
44
44
|
return !value.some((v) => is_color(v));
|
|
45
|
-
}
|
|
46
45
|
return !is_color(value);
|
|
47
46
|
});
|
|
48
|
-
// Determine the actual layout to use based on value count and split_layout prop
|
|
49
|
-
const actual_layout = $derived.by(() => {
|
|
50
|
-
if (!Array.isArray(value))
|
|
51
|
-
return null;
|
|
52
|
-
if (split_layout)
|
|
53
|
-
return split_layout;
|
|
54
|
-
// Auto-determine layout based on value count (backwards compatibility)
|
|
55
|
-
const layout_map = { 2: `diagonal`, 3: `horizontal`, 4: `quadrant` };
|
|
56
|
-
if (value.length in layout_map) {
|
|
57
|
-
return layout_map[value.length];
|
|
58
|
-
}
|
|
59
|
-
console.error(`Only 2, 3, or 4 values are supported for split_layout`);
|
|
60
|
-
return null;
|
|
61
|
-
});
|
|
62
47
|
// Get the appropriate CSS classes for segments and positions based on layout
|
|
63
48
|
const layout_config = $derived.by(() => {
|
|
64
|
-
if (!Array.isArray(value)
|
|
49
|
+
if (!Array.isArray(value))
|
|
65
50
|
return null;
|
|
66
51
|
const count = value.length;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
segments: [
|
|
93
|
-
`triangle-top`,
|
|
94
|
-
`triangle-right`,
|
|
95
|
-
`triangle-bottom`,
|
|
96
|
-
`triangle-left`,
|
|
97
|
-
],
|
|
98
|
-
positions: [
|
|
99
|
-
`triangle-top-pos`,
|
|
100
|
-
`triangle-right-pos`,
|
|
101
|
-
`triangle-bottom-pos`,
|
|
102
|
-
`triangle-left-pos`,
|
|
103
|
-
],
|
|
104
|
-
}
|
|
105
|
-
: null;
|
|
106
|
-
case `quadrant`:
|
|
107
|
-
return count === 4
|
|
108
|
-
? {
|
|
109
|
-
segments: [`quadrant-tl`, `quadrant-tr`, `quadrant-bl`, `quadrant-br`],
|
|
110
|
-
positions: [
|
|
111
|
-
`value-quadrant-tl`,
|
|
112
|
-
`value-quadrant-tr`,
|
|
113
|
-
`value-quadrant-bl`,
|
|
114
|
-
`value-quadrant-br`,
|
|
115
|
-
],
|
|
116
|
-
}
|
|
117
|
-
: null;
|
|
118
|
-
default:
|
|
119
|
-
return null;
|
|
52
|
+
// Use explicit split_layout or auto-determine based on count
|
|
53
|
+
const layout = split_layout ?? {
|
|
54
|
+
2: `diagonal`,
|
|
55
|
+
3: `horizontal`,
|
|
56
|
+
4: `quadrant`,
|
|
57
|
+
}[count];
|
|
58
|
+
if (!layout)
|
|
59
|
+
return null;
|
|
60
|
+
if (layout === `diagonal` && count === 2) {
|
|
61
|
+
return {
|
|
62
|
+
segments: [`diagonal-top`, `diagonal-bottom`],
|
|
63
|
+
positions: [`top-left`, `bottom-right`],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (layout === `horizontal` && count === 3) {
|
|
67
|
+
return {
|
|
68
|
+
segments: [`horizontal-top`, `horizontal-middle`, `horizontal-bottom`],
|
|
69
|
+
positions: [`bar-top-left`, `bar-middle-right`, `bar-bottom-left`],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (layout === `vertical` && count === 3) {
|
|
73
|
+
return {
|
|
74
|
+
segments: [`vertical-left`, `vertical-middle`, `vertical-right`],
|
|
75
|
+
positions: [`bar-left-top`, `bar-middle-bottom`, `bar-right-top`],
|
|
76
|
+
};
|
|
120
77
|
}
|
|
78
|
+
if (layout === `triangular` && count === 4) {
|
|
79
|
+
return {
|
|
80
|
+
segments: [
|
|
81
|
+
`triangle-top`,
|
|
82
|
+
`triangle-right`,
|
|
83
|
+
`triangle-bottom`,
|
|
84
|
+
`triangle-left`,
|
|
85
|
+
],
|
|
86
|
+
positions: [
|
|
87
|
+
`triangle-top-pos`,
|
|
88
|
+
`triangle-right-pos`,
|
|
89
|
+
`triangle-bottom-pos`,
|
|
90
|
+
`triangle-left-pos`,
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (layout === `quadrant` && count === 4) {
|
|
95
|
+
return {
|
|
96
|
+
segments: [`quadrant-tl`, `quadrant-tr`, `quadrant-bl`, `quadrant-br`],
|
|
97
|
+
positions: [
|
|
98
|
+
`value-quadrant-tl`,
|
|
99
|
+
`value-quadrant-tr`,
|
|
100
|
+
`value-quadrant-bl`,
|
|
101
|
+
`value-quadrant-br`,
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
121
106
|
});
|
|
122
107
|
</script>
|
|
123
108
|
|
package/dist/icons.d.ts
CHANGED
|
@@ -77,24 +77,12 @@ export declare const icon_data: {
|
|
|
77
77
|
readonly height: "24";
|
|
78
78
|
readonly path: "M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4M9 18c-4.51 2-5-2-7-2";
|
|
79
79
|
};
|
|
80
|
-
readonly Contact: {
|
|
81
|
-
readonly viewBox: "0 0 24 24";
|
|
82
|
-
readonly width: "24";
|
|
83
|
-
readonly height: "24";
|
|
84
|
-
readonly path: "M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zM22 7l-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7";
|
|
85
|
-
};
|
|
86
80
|
readonly Changelog: {
|
|
87
81
|
readonly viewBox: "0 0 24 24";
|
|
88
82
|
readonly width: "24";
|
|
89
83
|
readonly height: "24";
|
|
90
84
|
readonly path: "M13 3a9 9 0 0 0-9 9H1l4 4l4-4H6c0-3.87 3.13-7 7-7s7 3.13 7 7s-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.95 8.95 0 0 0 13 21a9 9 0 0 0 0-18m-1 5v5l4.25 2.52l.77-1.28l-3.52-2.09V8z";
|
|
91
85
|
};
|
|
92
|
-
readonly GitHubMark: {
|
|
93
|
-
readonly viewBox: "0 0 16 16";
|
|
94
|
-
readonly width: "24";
|
|
95
|
-
readonly height: "24";
|
|
96
|
-
readonly path: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z";
|
|
97
|
-
};
|
|
98
86
|
readonly Info: {
|
|
99
87
|
readonly viewBox: "0 0 24 24";
|
|
100
88
|
readonly width: "24";
|
|
@@ -107,18 +95,6 @@ export declare const icon_data: {
|
|
|
107
95
|
readonly height: "24";
|
|
108
96
|
readonly path: "M14 21v-1.65q0-.2.075-.387t.225-.338l5.225-5.2q.225-.225.5-.325t.55-.1q.3 0 .575.113t.5.337l.925.925q.2.225.313.5t.112.55t-.1.563t-.325.512l-5.2 5.2q-.15.15-.337.225T16.65 22H15q-.425 0-.712-.287T14 21m7.5-5.575l-.925-.925zm-6 5.075h.95l3.025-3.05l-.925-.925l-3.05 3.025zM6 22q-.825 0-1.412-.587T4 20V4q0-.825.588-1.412T6 2h7.175q.4 0 .763.15t.637.425l4.85 4.85q.275.275.425.638t.15.762v1.425q0 .425-.288.713T19 11.25t-.712-.288T18 10.25V9h-4q-.425 0-.712-.288T13 8V4H6v16h5q.425 0 .713.288T12 21t-.288.713T11 22zm0-2V4zm13.025-3.025l-.475-.45l.925.925z";
|
|
109
97
|
};
|
|
110
|
-
readonly Mail: {
|
|
111
|
-
readonly viewBox: "0 0 24 24";
|
|
112
|
-
readonly width: "24";
|
|
113
|
-
readonly height: "24";
|
|
114
|
-
readonly path: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z M22 6l-10 7L2 6";
|
|
115
|
-
};
|
|
116
|
-
readonly Globe: {
|
|
117
|
-
readonly viewBox: "0 0 24 24";
|
|
118
|
-
readonly width: "24";
|
|
119
|
-
readonly height: "24";
|
|
120
|
-
readonly path: "M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zM2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z";
|
|
121
|
-
};
|
|
122
98
|
readonly CheckCircle: {
|
|
123
99
|
readonly viewBox: "0 0 24 24";
|
|
124
100
|
readonly width: "24";
|
|
@@ -431,5 +407,13 @@ export declare const icon_data: {
|
|
|
431
407
|
readonly height: "24";
|
|
432
408
|
readonly path: "M2 2h2v18h18v2H2zm7 8a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3m4-8a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3m5 10a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3";
|
|
433
409
|
};
|
|
410
|
+
readonly Histogram: {
|
|
411
|
+
readonly viewBox: "0 0 48 48";
|
|
412
|
+
readonly width: "24";
|
|
413
|
+
readonly height: "24";
|
|
414
|
+
readonly stroke: "currentColor";
|
|
415
|
+
readonly fill: "currentColor";
|
|
416
|
+
readonly path: "M4 42h40z M4 42h40 M8 28h6v14H8zm13-10h6v24h-6zM34 6h6v36h-6z";
|
|
417
|
+
};
|
|
434
418
|
};
|
|
435
419
|
export type IconName = keyof typeof icon_data;
|
package/dist/icons.js
CHANGED
|
@@ -78,24 +78,12 @@ export const icon_data = {
|
|
|
78
78
|
height: `24`,
|
|
79
79
|
path: `M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4M9 18c-4.51 2-5-2-7-2`,
|
|
80
80
|
},
|
|
81
|
-
Contact: {
|
|
82
|
-
viewBox: `0 0 24 24`,
|
|
83
|
-
width: `24`,
|
|
84
|
-
height: `24`,
|
|
85
|
-
path: `M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zM22 7l-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7`,
|
|
86
|
-
},
|
|
87
81
|
Changelog: {
|
|
88
82
|
viewBox: `0 0 24 24`,
|
|
89
83
|
width: `24`,
|
|
90
84
|
height: `24`,
|
|
91
85
|
path: `M13 3a9 9 0 0 0-9 9H1l4 4l4-4H6c0-3.87 3.13-7 7-7s7 3.13 7 7s-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.95 8.95 0 0 0 13 21a9 9 0 0 0 0-18m-1 5v5l4.25 2.52l.77-1.28l-3.52-2.09V8z`,
|
|
92
86
|
},
|
|
93
|
-
GitHubMark: {
|
|
94
|
-
viewBox: `0 0 16 16`,
|
|
95
|
-
width: `24`,
|
|
96
|
-
height: `24`,
|
|
97
|
-
path: `M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z`,
|
|
98
|
-
},
|
|
99
87
|
Info: {
|
|
100
88
|
viewBox: `0 0 24 24`,
|
|
101
89
|
width: `24`,
|
|
@@ -108,18 +96,6 @@ export const icon_data = {
|
|
|
108
96
|
height: `24`,
|
|
109
97
|
path: `M14 21v-1.65q0-.2.075-.387t.225-.338l5.225-5.2q.225-.225.5-.325t.55-.1q.3 0 .575.113t.5.337l.925.925q.2.225.313.5t.112.55t-.1.563t-.325.512l-5.2 5.2q-.15.15-.337.225T16.65 22H15q-.425 0-.712-.287T14 21m7.5-5.575l-.925-.925zm-6 5.075h.95l3.025-3.05l-.925-.925l-3.05 3.025zM6 22q-.825 0-1.412-.587T4 20V4q0-.825.588-1.412T6 2h7.175q.4 0 .763.15t.637.425l4.85 4.85q.275.275.425.638t.15.762v1.425q0 .425-.288.713T19 11.25t-.712-.288T18 10.25V9h-4q-.425 0-.712-.288T13 8V4H6v16h5q.425 0 .713.288T12 21t-.288.713T11 22zm0-2V4zm13.025-3.025l-.475-.45l.925.925z`,
|
|
110
98
|
},
|
|
111
|
-
Mail: {
|
|
112
|
-
viewBox: `0 0 24 24`,
|
|
113
|
-
width: `24`,
|
|
114
|
-
height: `24`,
|
|
115
|
-
path: `M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z M22 6l-10 7L2 6`,
|
|
116
|
-
},
|
|
117
|
-
Globe: {
|
|
118
|
-
viewBox: `0 0 24 24`,
|
|
119
|
-
width: `24`,
|
|
120
|
-
height: `24`,
|
|
121
|
-
path: `M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zM2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z`,
|
|
122
|
-
},
|
|
123
99
|
CheckCircle: {
|
|
124
100
|
viewBox: `0 0 24 24`,
|
|
125
101
|
width: `24`,
|
|
@@ -432,4 +408,12 @@ export const icon_data = {
|
|
|
432
408
|
height: `24`,
|
|
433
409
|
path: `M2 2h2v18h18v2H2zm7 8a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3m4-8a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3m5 10a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3`,
|
|
434
410
|
},
|
|
411
|
+
Histogram: {
|
|
412
|
+
viewBox: `0 0 48 48`,
|
|
413
|
+
width: `24`,
|
|
414
|
+
height: `24`,
|
|
415
|
+
stroke: `currentColor`,
|
|
416
|
+
fill: `currentColor`,
|
|
417
|
+
path: `M4 42h40z M4 42h40 M8 28h6v14H8zm13-10h6v24h-6zM34 6h6v36h-6z`,
|
|
418
|
+
},
|
|
435
419
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -13,9 +13,9 @@ export { default as Nucleus } from './Nucleus.svelte';
|
|
|
13
13
|
export * from './periodic-table';
|
|
14
14
|
export * from './plot';
|
|
15
15
|
export { default as Spinner } from './Spinner.svelte';
|
|
16
|
+
export * from './structure';
|
|
16
17
|
export { default as Structure } from './structure/Structure.svelte';
|
|
17
18
|
export { default as Trajectory } from './trajectory/Trajectory.svelte';
|
|
18
|
-
export * from './structure';
|
|
19
19
|
export type Category = (typeof categories)[number];
|
|
20
20
|
export type ElementSymbol = (typeof elem_symbols)[number];
|
|
21
21
|
export type CompositionType = Partial<Record<ElementSymbol, number>>;
|
package/dist/index.js
CHANGED
|
@@ -12,9 +12,9 @@ export { default as Nucleus } from './Nucleus.svelte';
|
|
|
12
12
|
export * from './periodic-table';
|
|
13
13
|
export * from './plot';
|
|
14
14
|
export { default as Spinner } from './Spinner.svelte';
|
|
15
|
+
export * from './structure';
|
|
15
16
|
export { default as Structure } from './structure/Structure.svelte';
|
|
16
17
|
export { default as Trajectory } from './trajectory/Trajectory.svelte';
|
|
17
|
-
export * from './structure';
|
|
18
18
|
export const crystal_systems = [
|
|
19
19
|
`triclinic`,
|
|
20
20
|
`monoclinic`,
|
package/dist/io/decompress.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export declare function is_compressed_file(filename: string): boolean;
|
|
|
8
8
|
export declare function remove_compression_extension(filename: string): string;
|
|
9
9
|
export declare function detect_compression_format(filename: string): CompressionFormat | null;
|
|
10
10
|
export declare function decompress_data(data: ArrayBuffer, format: CompressionFormat): Promise<string>;
|
|
11
|
-
export declare const decompress_gzip: (data: ArrayBuffer) => Promise<string>;
|
|
12
11
|
export declare function decompress_file(file: File): Promise<{
|
|
13
12
|
content: string;
|
|
14
13
|
filename: string;
|
package/dist/io/decompress.js
CHANGED
|
@@ -40,8 +40,6 @@ export async function decompress_data(data, format) {
|
|
|
40
40
|
throw `Failed to decompress ${format} file: ${error}`;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
// Legacy compatibility
|
|
44
|
-
export const decompress_gzip = (data) => decompress_data(data, `gzip`);
|
|
45
43
|
export function decompress_file(file) {
|
|
46
44
|
const compressed = is_compressed_file(file.name);
|
|
47
45
|
return new Promise((resolve, reject) => {
|
|
@@ -69,7 +67,7 @@ export function decompress_file(file) {
|
|
|
69
67
|
reject(error);
|
|
70
68
|
}
|
|
71
69
|
};
|
|
72
|
-
reader.onerror = () => reject(new Error(`Failed to read file`));
|
|
70
|
+
reader.onerror = () => reject(new Error(`Failed to read file ${file.name}`));
|
|
73
71
|
if (compressed)
|
|
74
72
|
reader.readAsArrayBuffer(file);
|
|
75
73
|
else
|
package/dist/io/export.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { AnyStructure } from '..';
|
|
2
|
+
import type * as THREE from 'three';
|
|
2
3
|
import { WebGLRenderer } from 'three';
|
|
3
4
|
export interface CanvasWithRenderer extends HTMLCanvasElement {
|
|
4
5
|
__customRenderer?: WebGLRenderer;
|
|
5
6
|
}
|
|
6
7
|
export declare function generate_structure_filename(structure: AnyStructure | undefined, extension: string): string;
|
|
8
|
+
export declare function generate_xyz_content(structure?: AnyStructure): string;
|
|
9
|
+
export declare function generate_json_content(structure?: AnyStructure): string;
|
|
10
|
+
export declare function copy_to_clipboard(text: string): Promise<void>;
|
|
7
11
|
export declare function export_xyz(structure?: AnyStructure): void;
|
|
8
12
|
export declare function export_json(structure?: AnyStructure): void;
|
|
9
|
-
export declare function export_png(canvas: HTMLCanvasElement | null, structure: AnyStructure | undefined, png_dpi?: number): void;
|
|
13
|
+
export declare function export_png(canvas: HTMLCanvasElement | null, structure: AnyStructure | undefined, png_dpi?: number, scene?: THREE.Scene | null, camera?: THREE.Camera | null): void;
|