matterviz 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BohrAtom.svelte +105 -0
- package/dist/BohrAtom.svelte.d.ts +21 -0
- package/dist/ControlPanel.svelte +158 -0
- package/dist/ControlPanel.svelte.d.ts +18 -0
- package/dist/Icon.svelte +23 -0
- package/dist/Icon.svelte.d.ts +8 -0
- package/dist/InfoCard.svelte +79 -0
- package/dist/InfoCard.svelte.d.ts +23 -0
- package/dist/Nucleus.svelte +64 -0
- package/dist/Nucleus.svelte.d.ts +16 -0
- package/dist/Spinner.svelte +44 -0
- package/dist/Spinner.svelte.d.ts +7 -0
- package/dist/api.d.ts +6 -0
- package/dist/api.js +30 -0
- package/dist/colors/alloy-colors.json +111 -0
- package/dist/colors/dark-mode-colors.json +111 -0
- package/dist/colors/index.d.ts +26 -0
- package/dist/colors/index.js +72 -0
- package/dist/colors/jmol-colors.json +111 -0
- package/dist/colors/muted-colors.json +111 -0
- package/dist/colors/pastel-colors.json +111 -0
- package/dist/colors/vesta-colors.json +111 -0
- package/dist/composition/BarChart.svelte +260 -0
- package/dist/composition/BarChart.svelte.d.ts +33 -0
- package/dist/composition/BubbleChart.svelte +166 -0
- package/dist/composition/BubbleChart.svelte.d.ts +30 -0
- package/dist/composition/Composition.svelte +73 -0
- package/dist/composition/Composition.svelte.d.ts +27 -0
- package/dist/composition/PieChart.svelte +236 -0
- package/dist/composition/PieChart.svelte.d.ts +36 -0
- package/dist/composition/index.d.ts +5 -0
- package/dist/composition/index.js +5 -0
- package/dist/composition/parse.d.ts +14 -0
- package/dist/composition/parse.js +307 -0
- package/dist/element/ElementHeading.svelte +21 -0
- package/dist/element/ElementHeading.svelte.d.ts +8 -0
- package/dist/element/ElementPhoto.svelte +56 -0
- package/dist/element/ElementPhoto.svelte.d.ts +9 -0
- package/dist/element/ElementStats.svelte +73 -0
- package/dist/element/ElementStats.svelte.d.ts +8 -0
- package/dist/element/ElementTile.svelte +449 -0
- package/dist/element/ElementTile.svelte.d.ts +25 -0
- package/dist/element/data.d.ts +4958 -0
- package/dist/element/data.js +5628 -0
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +4 -0
- package/dist/icons.d.ts +435 -0
- package/dist/icons.js +435 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +43 -0
- package/dist/io/decompress.d.ts +16 -0
- package/dist/io/decompress.js +78 -0
- package/dist/io/export.d.ts +9 -0
- package/dist/io/export.js +205 -0
- package/dist/io/parse.d.ts +53 -0
- package/dist/io/parse.js +747 -0
- package/dist/labels.d.ts +31 -0
- package/dist/labels.js +209 -0
- package/dist/material/MaterialCard.svelte +135 -0
- package/dist/material/MaterialCard.svelte.d.ts +10 -0
- package/dist/material/SymmetryCard.svelte +23 -0
- package/dist/material/SymmetryCard.svelte.d.ts +9 -0
- package/dist/material/index.d.ts +2 -0
- package/dist/material/index.js +2 -0
- package/dist/math.d.ts +24 -0
- package/dist/math.js +216 -0
- package/dist/periodic-table/PeriodicTable.svelte +284 -0
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +50 -0
- package/dist/periodic-table/PropertySelect.svelte +20 -0
- package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
- package/dist/periodic-table/TableInset.svelte +18 -0
- package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
- package/dist/periodic-table/index.d.ts +9 -0
- package/dist/periodic-table/index.js +3 -0
- package/dist/plot/ColorBar.svelte +414 -0
- package/dist/plot/ColorBar.svelte.d.ts +22 -0
- package/dist/plot/ColorScaleSelect.svelte +31 -0
- package/dist/plot/ColorScaleSelect.svelte.d.ts +15 -0
- package/dist/plot/ElementScatter.svelte +38 -0
- package/dist/plot/ElementScatter.svelte.d.ts +14 -0
- package/dist/plot/Line.svelte +42 -0
- package/dist/plot/Line.svelte.d.ts +15 -0
- package/dist/plot/PlotLegend.svelte +206 -0
- package/dist/plot/PlotLegend.svelte.d.ts +18 -0
- package/dist/plot/ScatterPlot.svelte +1753 -0
- package/dist/plot/ScatterPlot.svelte.d.ts +114 -0
- package/dist/plot/ScatterPlotControls.svelte +505 -0
- package/dist/plot/ScatterPlotControls.svelte.d.ts +33 -0
- package/dist/plot/ScatterPoint.svelte +72 -0
- package/dist/plot/ScatterPoint.svelte.d.ts +17 -0
- package/dist/plot/index.d.ts +168 -0
- package/dist/plot/index.js +46 -0
- package/dist/state.svelte.d.ts +12 -0
- package/dist/state.svelte.js +11 -0
- package/dist/structure/Bond.svelte +68 -0
- package/dist/structure/Bond.svelte.d.ts +13 -0
- package/dist/structure/Lattice.svelte +115 -0
- package/dist/structure/Lattice.svelte.d.ts +15 -0
- package/dist/structure/Structure.svelte +298 -0
- package/dist/structure/Structure.svelte.d.ts +28 -0
- package/dist/structure/StructureCard.svelte +26 -0
- package/dist/structure/StructureCard.svelte.d.ts +9 -0
- package/dist/structure/StructureControls.svelte +383 -0
- package/dist/structure/StructureControls.svelte.d.ts +23 -0
- package/dist/structure/StructureLegend.svelte +130 -0
- package/dist/structure/StructureLegend.svelte.d.ts +17 -0
- package/dist/structure/StructureScene.svelte +331 -0
- package/dist/structure/StructureScene.svelte.d.ts +47 -0
- package/dist/structure/bonding.d.ts +16 -0
- package/dist/structure/bonding.js +150 -0
- package/dist/structure/index.d.ts +98 -0
- package/dist/structure/index.js +114 -0
- package/dist/structure/pbc.d.ts +6 -0
- package/dist/structure/pbc.js +72 -0
- package/dist/trajectory/Sidebar.svelte +412 -0
- package/dist/trajectory/Sidebar.svelte.d.ts +14 -0
- package/dist/trajectory/Trajectory.svelte +1084 -0
- package/dist/trajectory/Trajectory.svelte.d.ts +49 -0
- package/dist/trajectory/TrajectoryError.svelte +120 -0
- package/dist/trajectory/TrajectoryError.svelte.d.ts +12 -0
- package/dist/trajectory/extract.d.ts +5 -0
- package/dist/trajectory/extract.js +157 -0
- package/dist/trajectory/index.d.ts +16 -0
- package/dist/trajectory/index.js +49 -0
- package/dist/trajectory/parse.d.ts +13 -0
- package/dist/trajectory/parse.js +1093 -0
- package/dist/trajectory/plotting.d.ts +12 -0
- package/dist/trajectory/plotting.js +148 -0
- package/license +21 -0
- package/package.json +131 -0
- package/readme.md +95 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">import { Icon } from '..';
|
|
2
|
+
let { element, style = null, missing_msg = `No image for ` } = $props();
|
|
3
|
+
let { name, number } = $derived(element ?? {});
|
|
4
|
+
let file = $derived(`elements/${number}-${name?.toLowerCase()}.avif`);
|
|
5
|
+
let hidden = $state(false);
|
|
6
|
+
$effect.pre(() => {
|
|
7
|
+
if (file)
|
|
8
|
+
hidden = false;
|
|
9
|
+
}); // reset hidden to false when file changes
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if name && number}
|
|
13
|
+
<img
|
|
14
|
+
src="https://github.com/janosh/matterviz/raw/main/static/{file}"
|
|
15
|
+
alt={name}
|
|
16
|
+
onerror={() => (hidden = true)}
|
|
17
|
+
{style}
|
|
18
|
+
{hidden}
|
|
19
|
+
/>
|
|
20
|
+
{#if hidden && missing_msg}
|
|
21
|
+
<div {style}>
|
|
22
|
+
<span>
|
|
23
|
+
<Icon icon="NoImage" /> {missing_msg} {name}
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
26
|
+
{/if}
|
|
27
|
+
{/if}
|
|
28
|
+
|
|
29
|
+
<style>
|
|
30
|
+
img {
|
|
31
|
+
width: 100%;
|
|
32
|
+
object-fit: cover;
|
|
33
|
+
margin: 0;
|
|
34
|
+
border-radius: 4pt;
|
|
35
|
+
}
|
|
36
|
+
div {
|
|
37
|
+
aspect-ratio: 1;
|
|
38
|
+
text-align: center;
|
|
39
|
+
display: flex;
|
|
40
|
+
padding: 3pt;
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
place-items: center;
|
|
43
|
+
background-image: linear-gradient(
|
|
44
|
+
to top left,
|
|
45
|
+
rgba(0, 100, 0, 0.5),
|
|
46
|
+
rgba(0, 0, 100, 0.3)
|
|
47
|
+
);
|
|
48
|
+
color: var(--text-color);
|
|
49
|
+
border-radius: 4pt;
|
|
50
|
+
width: 100%;
|
|
51
|
+
container-type: inline-size;
|
|
52
|
+
}
|
|
53
|
+
div > span {
|
|
54
|
+
font-size: 15cqw;
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ChemicalElement } from '..';
|
|
2
|
+
interface Props {
|
|
3
|
+
element: ChemicalElement;
|
|
4
|
+
style?: string | null;
|
|
5
|
+
missing_msg?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const ElementPhoto: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type ElementPhoto = ReturnType<typeof ElementPhoto>;
|
|
9
|
+
export default ElementPhoto;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts">import { ElementHeading, format_num, Icon } from '..';
|
|
2
|
+
let { element, style = `` } = $props();
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
{#if element}
|
|
6
|
+
<div {style}>
|
|
7
|
+
<ElementHeading
|
|
8
|
+
{element}
|
|
9
|
+
style="font-size: min(3vw, 3em); grid-column: 1/-1; margin: auto 0 0"
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
<section>
|
|
13
|
+
<p>
|
|
14
|
+
Atomic Mass
|
|
15
|
+
<abbr title="Dalton aka atomic mass unit">(u)</abbr>
|
|
16
|
+
</p>
|
|
17
|
+
<strong>
|
|
18
|
+
<Icon icon="Weight" /> {format_num(element.atomic_mass)}
|
|
19
|
+
</strong>
|
|
20
|
+
</section>
|
|
21
|
+
<section>
|
|
22
|
+
<p>
|
|
23
|
+
Density
|
|
24
|
+
<abbr title="grams per cubic centimeter">(g/cm³)</abbr>
|
|
25
|
+
</p>
|
|
26
|
+
<strong>
|
|
27
|
+
<Icon icon="Scale" /> {format_num(element.density)}
|
|
28
|
+
</strong>
|
|
29
|
+
</section>
|
|
30
|
+
<section>
|
|
31
|
+
<p>Phase</p>
|
|
32
|
+
<strong>
|
|
33
|
+
<Icon icon={element.phase} /> {element.phase}</strong>
|
|
34
|
+
</section>
|
|
35
|
+
<section>
|
|
36
|
+
<p>Year of Discovery</p>
|
|
37
|
+
<strong>
|
|
38
|
+
<Icon icon="CalendarBlank" /> {element.year}
|
|
39
|
+
</strong>
|
|
40
|
+
</section>
|
|
41
|
+
</div>
|
|
42
|
+
{:else}
|
|
43
|
+
<h3 style="text-align: center">Try hovering an element!</h3>
|
|
44
|
+
{/if}
|
|
45
|
+
|
|
46
|
+
<style>
|
|
47
|
+
div {
|
|
48
|
+
display: grid;
|
|
49
|
+
grid-template: auto auto / repeat(4, 1fr);
|
|
50
|
+
place-items: center;
|
|
51
|
+
text-align: center;
|
|
52
|
+
container-type: inline-size;
|
|
53
|
+
}
|
|
54
|
+
div > section > strong {
|
|
55
|
+
display: block;
|
|
56
|
+
margin-top: 1ex;
|
|
57
|
+
font-size: 3.5cqw;
|
|
58
|
+
}
|
|
59
|
+
div > section > p {
|
|
60
|
+
margin: 0;
|
|
61
|
+
font-weight: lighter;
|
|
62
|
+
font-size: 3cqw;
|
|
63
|
+
}
|
|
64
|
+
div > section > p > abbr {
|
|
65
|
+
font-size: 2cqw;
|
|
66
|
+
text-decoration: none;
|
|
67
|
+
}
|
|
68
|
+
h3 {
|
|
69
|
+
font-size: clamp(9pt, 3vw, 20pt);
|
|
70
|
+
white-space: nowrap;
|
|
71
|
+
align-self: center;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ChemicalElement } from '..';
|
|
2
|
+
interface Props {
|
|
3
|
+
element: ChemicalElement | null;
|
|
4
|
+
style?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const ElementStats: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type ElementStats = ReturnType<typeof ElementStats>;
|
|
8
|
+
export default ElementStats;
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
<script lang="ts">import { choose_bw_for_contrast, format_num } from '..';
|
|
2
|
+
import { default_category_colors, is_color } from '../colors';
|
|
3
|
+
import { selected } from '../state.svelte';
|
|
4
|
+
let { element, bg_color = null, show_symbol = true, show_number = undefined, // auto-determine based on multi-value splits
|
|
5
|
+
show_name = true, value = undefined, symbol_style = ``, active = false, href = null, text_color_threshold = 0.7, text_color = $bindable(null), precision = undefined, node = $bindable(null), label = null, bg_colors = [], show_values = undefined, split_layout = undefined, // auto-determine based on value count if not specified
|
|
6
|
+
...rest } = $props();
|
|
7
|
+
let category = $derived(element.category.replaceAll(` `, `-`));
|
|
8
|
+
// background color defaults to category color (initialized in colors/index.ts, user editable in PeriodicTableControls.svelte)
|
|
9
|
+
let fallback_bg_color = $derived(bg_color ?? default_category_colors[category] ?? `var(--${category}-bg-color)`);
|
|
10
|
+
let contrast_bg_color = $derived(bg_color ?? default_category_colors[category]);
|
|
11
|
+
// Determine if we should show the atomic number - default to false for multi-value splits to avoid overlap
|
|
12
|
+
const should_show_number = $derived.by(() => {
|
|
13
|
+
if (show_number !== undefined)
|
|
14
|
+
return show_number;
|
|
15
|
+
// Auto-hide number for multi-value splits to prevent overlap with value labels
|
|
16
|
+
if (Array.isArray(value) && value.length > 1)
|
|
17
|
+
return false;
|
|
18
|
+
return true; // default to true for single values
|
|
19
|
+
});
|
|
20
|
+
// Helper function to format values appropriately
|
|
21
|
+
const format_value = (val) => {
|
|
22
|
+
if (is_color(val)) {
|
|
23
|
+
return show_values === true ? val.toString() : ``;
|
|
24
|
+
}
|
|
25
|
+
// Handle numeric values
|
|
26
|
+
if (typeof val === `number`)
|
|
27
|
+
return format_num(val, precision);
|
|
28
|
+
// Handle string values - check if it's a numeric string
|
|
29
|
+
if (typeof val === `string`) {
|
|
30
|
+
const parsed_num = parseFloat(val);
|
|
31
|
+
if (!isNaN(parsed_num) && isFinite(parsed_num)) {
|
|
32
|
+
return format_num(parsed_num, precision);
|
|
33
|
+
}
|
|
34
|
+
// If show_values is true, return the string as-is to preserve non-numeric strings
|
|
35
|
+
return show_values === true ? val : ``;
|
|
36
|
+
}
|
|
37
|
+
return ``;
|
|
38
|
+
};
|
|
39
|
+
// Determine if we should show values - default to false if any array element is a color
|
|
40
|
+
const should_show_values = $derived.by(() => {
|
|
41
|
+
if (show_values !== undefined)
|
|
42
|
+
return show_values;
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
return !value.some((v) => is_color(v));
|
|
45
|
+
}
|
|
46
|
+
return !is_color(value);
|
|
47
|
+
});
|
|
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
|
+
// Get the appropriate CSS classes for segments and positions based on layout
|
|
63
|
+
const layout_config = $derived.by(() => {
|
|
64
|
+
if (!Array.isArray(value) || !actual_layout)
|
|
65
|
+
return null;
|
|
66
|
+
const count = value.length;
|
|
67
|
+
switch (actual_layout) {
|
|
68
|
+
case `diagonal`:
|
|
69
|
+
return count === 2
|
|
70
|
+
? {
|
|
71
|
+
segments: [`diagonal-top`, `diagonal-bottom`],
|
|
72
|
+
positions: [`top-left`, `bottom-right`],
|
|
73
|
+
}
|
|
74
|
+
: null;
|
|
75
|
+
case `horizontal`:
|
|
76
|
+
return count === 3
|
|
77
|
+
? {
|
|
78
|
+
segments: [`horizontal-top`, `horizontal-middle`, `horizontal-bottom`],
|
|
79
|
+
positions: [`bar-top-left`, `bar-middle-right`, `bar-bottom-left`],
|
|
80
|
+
}
|
|
81
|
+
: null;
|
|
82
|
+
case `vertical`:
|
|
83
|
+
return count === 3
|
|
84
|
+
? {
|
|
85
|
+
segments: [`vertical-left`, `vertical-middle`, `vertical-right`],
|
|
86
|
+
positions: [`bar-left-top`, `bar-middle-bottom`, `bar-right-top`],
|
|
87
|
+
}
|
|
88
|
+
: null;
|
|
89
|
+
case `triangular`:
|
|
90
|
+
return count === 4
|
|
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;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<svelte:element
|
|
125
|
+
this={href ? `a` : `div`}
|
|
126
|
+
bind:this={node}
|
|
127
|
+
{href}
|
|
128
|
+
data-sveltekit-noscroll
|
|
129
|
+
class="element-tile {category}"
|
|
130
|
+
class:active
|
|
131
|
+
class:last-active={selected.last_element === element}
|
|
132
|
+
style:background-color={Array.isArray(value) && bg_colors?.length > 1 ? `transparent` : fallback_bg_color}
|
|
133
|
+
style:color={text_color ??
|
|
134
|
+
choose_bw_for_contrast(node, contrast_bg_color, text_color_threshold)}
|
|
135
|
+
role="link"
|
|
136
|
+
tabindex="0"
|
|
137
|
+
{...rest}
|
|
138
|
+
>
|
|
139
|
+
{#if should_show_number}
|
|
140
|
+
<span class="number">
|
|
141
|
+
{element.number}
|
|
142
|
+
</span>
|
|
143
|
+
{/if}
|
|
144
|
+
{#if show_symbol}
|
|
145
|
+
<span class="symbol" style={symbol_style}>
|
|
146
|
+
{element.symbol}
|
|
147
|
+
</span>
|
|
148
|
+
{/if}
|
|
149
|
+
{#if value && should_show_values}
|
|
150
|
+
{#if Array.isArray(value) && layout_config}
|
|
151
|
+
<!-- Multi-value positioning using layout config -->
|
|
152
|
+
{#each value as val, idx (idx)}
|
|
153
|
+
{#if val && format_value(val)}
|
|
154
|
+
<span
|
|
155
|
+
class="value multi-value {layout_config.positions[idx]}"
|
|
156
|
+
style:color={bg_colors?.[idx]
|
|
157
|
+
? choose_bw_for_contrast(null, bg_colors[idx], text_color_threshold)
|
|
158
|
+
: null}
|
|
159
|
+
>
|
|
160
|
+
{format_value(val)}
|
|
161
|
+
</span>
|
|
162
|
+
{/if}
|
|
163
|
+
{/each}
|
|
164
|
+
{:else if Array.isArray(value)}
|
|
165
|
+
<!-- Fallback for other array lengths -->
|
|
166
|
+
<span class="value">{
|
|
167
|
+
value
|
|
168
|
+
.map((v) => format_value(v))
|
|
169
|
+
.filter((v) => v)
|
|
170
|
+
.join(` / `)
|
|
171
|
+
}</span>
|
|
172
|
+
{:else}
|
|
173
|
+
<!-- Single value -->
|
|
174
|
+
<span class="value">{format_value(value)}</span>
|
|
175
|
+
{/if}
|
|
176
|
+
{:else if show_name}
|
|
177
|
+
<span class="name">
|
|
178
|
+
{label ?? element.name}
|
|
179
|
+
</span>
|
|
180
|
+
{/if}
|
|
181
|
+
|
|
182
|
+
<!-- Multi-segment backgrounds for heatmap arrays -->
|
|
183
|
+
{#if Array.isArray(value) && bg_colors && bg_colors.length > 1 && layout_config}
|
|
184
|
+
{#each bg_colors as bg_color, idx (idx)}
|
|
185
|
+
{#if layout_config.segments[idx]}
|
|
186
|
+
<div
|
|
187
|
+
class="segment {layout_config.segments[idx]}"
|
|
188
|
+
style:background-color={bg_color}
|
|
189
|
+
>
|
|
190
|
+
</div>
|
|
191
|
+
{/if}
|
|
192
|
+
{/each}
|
|
193
|
+
{/if}
|
|
194
|
+
</svelte:element>
|
|
195
|
+
|
|
196
|
+
<style>
|
|
197
|
+
.element-tile {
|
|
198
|
+
position: relative;
|
|
199
|
+
transition: background-color var(--elem-tile-transition-duration, 0.4s);
|
|
200
|
+
aspect-ratio: 1;
|
|
201
|
+
display: flex;
|
|
202
|
+
place-items: center;
|
|
203
|
+
place-content: center;
|
|
204
|
+
border-radius: var(--elem-tile-border-radius, 4pt);
|
|
205
|
+
box-sizing: border-box;
|
|
206
|
+
color: var(--elem-tile-text-color);
|
|
207
|
+
/* add persistent invisible border so content doesn't move on hover */
|
|
208
|
+
border: 1px solid transparent;
|
|
209
|
+
container-type: inline-size;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
width: var(--elem-tile-width);
|
|
212
|
+
height: var(--elem-tile-height);
|
|
213
|
+
}
|
|
214
|
+
.element-tile span {
|
|
215
|
+
line-height: 1em;
|
|
216
|
+
z-index: 10;
|
|
217
|
+
}
|
|
218
|
+
.element-tile.active,
|
|
219
|
+
.element-tile:hover {
|
|
220
|
+
border: var(--elem-tile-hover-border-width, 1px) solid;
|
|
221
|
+
}
|
|
222
|
+
.last-active {
|
|
223
|
+
border: 1px dotted;
|
|
224
|
+
}
|
|
225
|
+
.number {
|
|
226
|
+
font-size: var(--elem-number-font-size, 22cqw);
|
|
227
|
+
position: absolute;
|
|
228
|
+
top: 6cqw;
|
|
229
|
+
font-weight: var(--elem-number-font-weight, 300);
|
|
230
|
+
left: 6cqw;
|
|
231
|
+
}
|
|
232
|
+
.symbol {
|
|
233
|
+
font-size: var(--elem-symbol-font-size, 40cqw);
|
|
234
|
+
font-weight: var(--elem-symbol-font-weight, 400);
|
|
235
|
+
}
|
|
236
|
+
span.name,
|
|
237
|
+
span.value {
|
|
238
|
+
position: absolute;
|
|
239
|
+
bottom: 8cqw;
|
|
240
|
+
}
|
|
241
|
+
span.value {
|
|
242
|
+
font-size: var(--elem-value-font-size, 18cqw);
|
|
243
|
+
}
|
|
244
|
+
span.name {
|
|
245
|
+
font-size: var(--elem-name-font-size, 12cqw);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* Multi-value positioning */
|
|
249
|
+
.multi-value {
|
|
250
|
+
position: absolute;
|
|
251
|
+
font-size: var(--elem-multi-value-font-size, 14cqw);
|
|
252
|
+
font-weight: 600;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* 2-value diagonal positions */
|
|
256
|
+
.top-left {
|
|
257
|
+
top: 4cqw;
|
|
258
|
+
left: 4cqw;
|
|
259
|
+
}
|
|
260
|
+
.bottom-right {
|
|
261
|
+
bottom: 4cqw;
|
|
262
|
+
right: 4cqw;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* 3-value horizontal bar positions */
|
|
266
|
+
.bar-top-left {
|
|
267
|
+
top: 8cqw;
|
|
268
|
+
left: 4cqw;
|
|
269
|
+
}
|
|
270
|
+
.bar-middle-right {
|
|
271
|
+
top: calc(50% - 7cqw);
|
|
272
|
+
right: 4cqw;
|
|
273
|
+
}
|
|
274
|
+
.bar-bottom-left {
|
|
275
|
+
bottom: 8cqw;
|
|
276
|
+
left: 4cqw;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* 3-value vertical bar positions */
|
|
280
|
+
.bar-left-top {
|
|
281
|
+
top: 4cqw;
|
|
282
|
+
left: 8cqw;
|
|
283
|
+
}
|
|
284
|
+
.bar-middle-bottom {
|
|
285
|
+
bottom: 4cqw;
|
|
286
|
+
left: 50%;
|
|
287
|
+
transform: translateX(-50%);
|
|
288
|
+
}
|
|
289
|
+
.bar-right-top {
|
|
290
|
+
top: 4cqw;
|
|
291
|
+
right: 8cqw;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* 4-value triangular positions (tips meet in center) */
|
|
295
|
+
.triangle-top-pos {
|
|
296
|
+
top: 3cqw;
|
|
297
|
+
left: 50%;
|
|
298
|
+
transform: translateX(-50%);
|
|
299
|
+
}
|
|
300
|
+
.triangle-right-pos {
|
|
301
|
+
top: calc(50% - 7cqw);
|
|
302
|
+
right: 3cqw;
|
|
303
|
+
}
|
|
304
|
+
.triangle-bottom-pos {
|
|
305
|
+
bottom: 3cqw;
|
|
306
|
+
left: 50%;
|
|
307
|
+
transform: translate(-50%, 2px);
|
|
308
|
+
}
|
|
309
|
+
.triangle-left-pos {
|
|
310
|
+
top: calc(50% - 7cqw);
|
|
311
|
+
left: 3cqw;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* 4-value quadrant positions */
|
|
315
|
+
.value-quadrant-tl {
|
|
316
|
+
top: 4cqw;
|
|
317
|
+
left: 4cqw;
|
|
318
|
+
}
|
|
319
|
+
.value-quadrant-tr {
|
|
320
|
+
top: 4cqw;
|
|
321
|
+
right: 4cqw;
|
|
322
|
+
}
|
|
323
|
+
.value-quadrant-bl {
|
|
324
|
+
bottom: 4cqw;
|
|
325
|
+
left: 4cqw;
|
|
326
|
+
}
|
|
327
|
+
.value-quadrant-br {
|
|
328
|
+
bottom: 4cqw;
|
|
329
|
+
right: 4cqw;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* Multi-segment backgrounds */
|
|
333
|
+
.segment {
|
|
334
|
+
position: absolute;
|
|
335
|
+
z-index: 1;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Diagonal split (2 values) */
|
|
339
|
+
.diagonal-top {
|
|
340
|
+
top: 0;
|
|
341
|
+
left: 0;
|
|
342
|
+
width: 100%;
|
|
343
|
+
height: 100%;
|
|
344
|
+
clip-path: polygon(0 0, 100% 0, 0 100%);
|
|
345
|
+
}
|
|
346
|
+
.diagonal-bottom {
|
|
347
|
+
top: 0;
|
|
348
|
+
left: 0;
|
|
349
|
+
width: 100%;
|
|
350
|
+
height: 100%;
|
|
351
|
+
clip-path: polygon(100% 0, 100% 100%, 0 100%);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* Horizontal bars (3 values) */
|
|
355
|
+
.horizontal-top {
|
|
356
|
+
top: 0;
|
|
357
|
+
left: 0;
|
|
358
|
+
width: 100%;
|
|
359
|
+
height: 33.33%;
|
|
360
|
+
}
|
|
361
|
+
.horizontal-middle {
|
|
362
|
+
top: 33.33%;
|
|
363
|
+
left: 0;
|
|
364
|
+
width: 100%;
|
|
365
|
+
height: 33.33%;
|
|
366
|
+
}
|
|
367
|
+
.horizontal-bottom {
|
|
368
|
+
top: 66.66%;
|
|
369
|
+
left: 0;
|
|
370
|
+
width: 100%;
|
|
371
|
+
height: 33.34%;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* Vertical bars (3 values) */
|
|
375
|
+
.vertical-left {
|
|
376
|
+
top: 0;
|
|
377
|
+
left: 0;
|
|
378
|
+
width: 33.33%;
|
|
379
|
+
height: 100%;
|
|
380
|
+
}
|
|
381
|
+
.vertical-middle {
|
|
382
|
+
top: 0;
|
|
383
|
+
left: 33.33%;
|
|
384
|
+
width: 33.33%;
|
|
385
|
+
height: 100%;
|
|
386
|
+
}
|
|
387
|
+
.vertical-right {
|
|
388
|
+
top: 0;
|
|
389
|
+
left: 66.66%;
|
|
390
|
+
width: 33.34%;
|
|
391
|
+
height: 100%;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Triangular segments (4 values) - tips meet in center */
|
|
395
|
+
.triangle-top {
|
|
396
|
+
top: 0;
|
|
397
|
+
left: 0;
|
|
398
|
+
width: 100%;
|
|
399
|
+
height: 100%;
|
|
400
|
+
clip-path: polygon(0 0, 100% 0, 50% 50%);
|
|
401
|
+
}
|
|
402
|
+
.triangle-right {
|
|
403
|
+
top: 0;
|
|
404
|
+
left: 0;
|
|
405
|
+
width: 100%;
|
|
406
|
+
height: 100%;
|
|
407
|
+
clip-path: polygon(100% 0, 100% 100%, 50% 50%);
|
|
408
|
+
}
|
|
409
|
+
.triangle-bottom {
|
|
410
|
+
top: 0;
|
|
411
|
+
left: 0;
|
|
412
|
+
width: 100%;
|
|
413
|
+
height: 100%;
|
|
414
|
+
clip-path: polygon(100% 100%, 0 100%, 50% 50%);
|
|
415
|
+
}
|
|
416
|
+
.triangle-left {
|
|
417
|
+
top: 0;
|
|
418
|
+
left: 0;
|
|
419
|
+
width: 100%;
|
|
420
|
+
height: 100%;
|
|
421
|
+
clip-path: polygon(0 100%, 0 0, 50% 50%);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* Four quadrants (4 values) */
|
|
425
|
+
.quadrant-tl {
|
|
426
|
+
top: 0;
|
|
427
|
+
left: 0;
|
|
428
|
+
width: 50%;
|
|
429
|
+
height: 50%;
|
|
430
|
+
}
|
|
431
|
+
.quadrant-tr {
|
|
432
|
+
top: 0;
|
|
433
|
+
right: 0;
|
|
434
|
+
width: 50%;
|
|
435
|
+
height: 50%;
|
|
436
|
+
}
|
|
437
|
+
.quadrant-bl {
|
|
438
|
+
bottom: 0;
|
|
439
|
+
left: 0;
|
|
440
|
+
width: 50%;
|
|
441
|
+
height: 50%;
|
|
442
|
+
}
|
|
443
|
+
.quadrant-br {
|
|
444
|
+
bottom: 0;
|
|
445
|
+
right: 0;
|
|
446
|
+
width: 50%;
|
|
447
|
+
height: 50%;
|
|
448
|
+
}
|
|
449
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ChemicalElement } from '..';
|
|
2
|
+
type SplitLayout = `diagonal` | `horizontal` | `vertical` | `triangular` | `quadrant`;
|
|
3
|
+
interface Props {
|
|
4
|
+
element: ChemicalElement;
|
|
5
|
+
bg_color?: string | null;
|
|
6
|
+
show_symbol?: boolean;
|
|
7
|
+
show_number?: boolean;
|
|
8
|
+
show_name?: boolean;
|
|
9
|
+
value?: number | number[] | string | string[] | false | undefined;
|
|
10
|
+
symbol_style?: string;
|
|
11
|
+
active?: boolean;
|
|
12
|
+
href?: string | null;
|
|
13
|
+
text_color_threshold?: number;
|
|
14
|
+
text_color?: string | null;
|
|
15
|
+
precision?: string | undefined;
|
|
16
|
+
node?: HTMLElement | null;
|
|
17
|
+
label?: string | null;
|
|
18
|
+
bg_colors?: (string | null)[];
|
|
19
|
+
show_values?: boolean;
|
|
20
|
+
split_layout?: SplitLayout;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
declare const ElementTile: import("svelte").Component<Props, {}, "text_color" | "node">;
|
|
24
|
+
type ElementTile = ReturnType<typeof ElementTile>;
|
|
25
|
+
export default ElementTile;
|