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.
Files changed (131) hide show
  1. package/dist/BohrAtom.svelte +105 -0
  2. package/dist/BohrAtom.svelte.d.ts +21 -0
  3. package/dist/ControlPanel.svelte +158 -0
  4. package/dist/ControlPanel.svelte.d.ts +18 -0
  5. package/dist/Icon.svelte +23 -0
  6. package/dist/Icon.svelte.d.ts +8 -0
  7. package/dist/InfoCard.svelte +79 -0
  8. package/dist/InfoCard.svelte.d.ts +23 -0
  9. package/dist/Nucleus.svelte +64 -0
  10. package/dist/Nucleus.svelte.d.ts +16 -0
  11. package/dist/Spinner.svelte +44 -0
  12. package/dist/Spinner.svelte.d.ts +7 -0
  13. package/dist/api.d.ts +6 -0
  14. package/dist/api.js +30 -0
  15. package/dist/colors/alloy-colors.json +111 -0
  16. package/dist/colors/dark-mode-colors.json +111 -0
  17. package/dist/colors/index.d.ts +26 -0
  18. package/dist/colors/index.js +72 -0
  19. package/dist/colors/jmol-colors.json +111 -0
  20. package/dist/colors/muted-colors.json +111 -0
  21. package/dist/colors/pastel-colors.json +111 -0
  22. package/dist/colors/vesta-colors.json +111 -0
  23. package/dist/composition/BarChart.svelte +260 -0
  24. package/dist/composition/BarChart.svelte.d.ts +33 -0
  25. package/dist/composition/BubbleChart.svelte +166 -0
  26. package/dist/composition/BubbleChart.svelte.d.ts +30 -0
  27. package/dist/composition/Composition.svelte +73 -0
  28. package/dist/composition/Composition.svelte.d.ts +27 -0
  29. package/dist/composition/PieChart.svelte +236 -0
  30. package/dist/composition/PieChart.svelte.d.ts +36 -0
  31. package/dist/composition/index.d.ts +5 -0
  32. package/dist/composition/index.js +5 -0
  33. package/dist/composition/parse.d.ts +14 -0
  34. package/dist/composition/parse.js +307 -0
  35. package/dist/element/ElementHeading.svelte +21 -0
  36. package/dist/element/ElementHeading.svelte.d.ts +8 -0
  37. package/dist/element/ElementPhoto.svelte +56 -0
  38. package/dist/element/ElementPhoto.svelte.d.ts +9 -0
  39. package/dist/element/ElementStats.svelte +73 -0
  40. package/dist/element/ElementStats.svelte.d.ts +8 -0
  41. package/dist/element/ElementTile.svelte +449 -0
  42. package/dist/element/ElementTile.svelte.d.ts +25 -0
  43. package/dist/element/data.d.ts +4958 -0
  44. package/dist/element/data.js +5628 -0
  45. package/dist/element/index.d.ts +4 -0
  46. package/dist/element/index.js +4 -0
  47. package/dist/icons.d.ts +435 -0
  48. package/dist/icons.js +435 -0
  49. package/dist/index.d.ts +82 -0
  50. package/dist/index.js +43 -0
  51. package/dist/io/decompress.d.ts +16 -0
  52. package/dist/io/decompress.js +78 -0
  53. package/dist/io/export.d.ts +9 -0
  54. package/dist/io/export.js +205 -0
  55. package/dist/io/parse.d.ts +53 -0
  56. package/dist/io/parse.js +747 -0
  57. package/dist/labels.d.ts +31 -0
  58. package/dist/labels.js +209 -0
  59. package/dist/material/MaterialCard.svelte +135 -0
  60. package/dist/material/MaterialCard.svelte.d.ts +10 -0
  61. package/dist/material/SymmetryCard.svelte +23 -0
  62. package/dist/material/SymmetryCard.svelte.d.ts +9 -0
  63. package/dist/material/index.d.ts +2 -0
  64. package/dist/material/index.js +2 -0
  65. package/dist/math.d.ts +24 -0
  66. package/dist/math.js +216 -0
  67. package/dist/periodic-table/PeriodicTable.svelte +284 -0
  68. package/dist/periodic-table/PeriodicTable.svelte.d.ts +50 -0
  69. package/dist/periodic-table/PropertySelect.svelte +20 -0
  70. package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
  71. package/dist/periodic-table/TableInset.svelte +18 -0
  72. package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
  73. package/dist/periodic-table/index.d.ts +9 -0
  74. package/dist/periodic-table/index.js +3 -0
  75. package/dist/plot/ColorBar.svelte +414 -0
  76. package/dist/plot/ColorBar.svelte.d.ts +22 -0
  77. package/dist/plot/ColorScaleSelect.svelte +31 -0
  78. package/dist/plot/ColorScaleSelect.svelte.d.ts +15 -0
  79. package/dist/plot/ElementScatter.svelte +38 -0
  80. package/dist/plot/ElementScatter.svelte.d.ts +14 -0
  81. package/dist/plot/Line.svelte +42 -0
  82. package/dist/plot/Line.svelte.d.ts +15 -0
  83. package/dist/plot/PlotLegend.svelte +206 -0
  84. package/dist/plot/PlotLegend.svelte.d.ts +18 -0
  85. package/dist/plot/ScatterPlot.svelte +1753 -0
  86. package/dist/plot/ScatterPlot.svelte.d.ts +114 -0
  87. package/dist/plot/ScatterPlotControls.svelte +505 -0
  88. package/dist/plot/ScatterPlotControls.svelte.d.ts +33 -0
  89. package/dist/plot/ScatterPoint.svelte +72 -0
  90. package/dist/plot/ScatterPoint.svelte.d.ts +17 -0
  91. package/dist/plot/index.d.ts +168 -0
  92. package/dist/plot/index.js +46 -0
  93. package/dist/state.svelte.d.ts +12 -0
  94. package/dist/state.svelte.js +11 -0
  95. package/dist/structure/Bond.svelte +68 -0
  96. package/dist/structure/Bond.svelte.d.ts +13 -0
  97. package/dist/structure/Lattice.svelte +115 -0
  98. package/dist/structure/Lattice.svelte.d.ts +15 -0
  99. package/dist/structure/Structure.svelte +298 -0
  100. package/dist/structure/Structure.svelte.d.ts +28 -0
  101. package/dist/structure/StructureCard.svelte +26 -0
  102. package/dist/structure/StructureCard.svelte.d.ts +9 -0
  103. package/dist/structure/StructureControls.svelte +383 -0
  104. package/dist/structure/StructureControls.svelte.d.ts +23 -0
  105. package/dist/structure/StructureLegend.svelte +130 -0
  106. package/dist/structure/StructureLegend.svelte.d.ts +17 -0
  107. package/dist/structure/StructureScene.svelte +331 -0
  108. package/dist/structure/StructureScene.svelte.d.ts +47 -0
  109. package/dist/structure/bonding.d.ts +16 -0
  110. package/dist/structure/bonding.js +150 -0
  111. package/dist/structure/index.d.ts +98 -0
  112. package/dist/structure/index.js +114 -0
  113. package/dist/structure/pbc.d.ts +6 -0
  114. package/dist/structure/pbc.js +72 -0
  115. package/dist/trajectory/Sidebar.svelte +412 -0
  116. package/dist/trajectory/Sidebar.svelte.d.ts +14 -0
  117. package/dist/trajectory/Trajectory.svelte +1084 -0
  118. package/dist/trajectory/Trajectory.svelte.d.ts +49 -0
  119. package/dist/trajectory/TrajectoryError.svelte +120 -0
  120. package/dist/trajectory/TrajectoryError.svelte.d.ts +12 -0
  121. package/dist/trajectory/extract.d.ts +5 -0
  122. package/dist/trajectory/extract.js +157 -0
  123. package/dist/trajectory/index.d.ts +16 -0
  124. package/dist/trajectory/index.js +49 -0
  125. package/dist/trajectory/parse.d.ts +13 -0
  126. package/dist/trajectory/parse.js +1093 -0
  127. package/dist/trajectory/plotting.d.ts +12 -0
  128. package/dist/trajectory/plotting.js +148 -0
  129. package/license +21 -0
  130. package/package.json +131 -0
  131. package/readme.md +95 -0
@@ -0,0 +1,105 @@
1
+ <script lang="ts">"use strict";
2
+ let { symbol = ``, name = ``, shells, adapt_size = false, shell_width = 20, size = adapt_size ? (shells.length + 1) * 2 * shell_width + 50 : 270, base_fill = `white`, orbital_period = 3, nucleus_props = {}, shell_props = {}, electron_props = {}, highlight_shell = null, style = ``, number_electrons = false, electron_label_props = {}, ...rest } = $props();
3
+ // Bohr atom electron orbital period is given by
4
+ // T = (n^3 h^3) / (4pi^2 m K e^4 Z^2) = 1.52 * 10^-16 * n^3 / Z^2 s
5
+ // with n the shell number, Z the atomic number, m the mass of the electron
6
+ let _nucleus_props = $derived({
7
+ r: 20,
8
+ fill: `white`,
9
+ 'fill-opacity': `0.3`,
10
+ ...nucleus_props,
11
+ });
12
+ let _shell_props = $derived({
13
+ stroke: `white`,
14
+ 'stroke-width': 1,
15
+ fill: `none`,
16
+ ...shell_props,
17
+ });
18
+ let _electron_props = $derived({
19
+ r: 3,
20
+ stroke: `white`,
21
+ 'stroke-width': 1,
22
+ fill: `blue`,
23
+ ...electron_props,
24
+ });
25
+ </script>
26
+
27
+ <svg
28
+ fill={base_fill}
29
+ viewBox="-{size / 2}, -{size / 2}, {size}, {size}"
30
+ role="presentation"
31
+ {style}
32
+ {...rest}
33
+ >
34
+ <!-- nucleus -->
35
+ <circle class="nucleus" {..._nucleus_props}>
36
+ {#if name}
37
+ <title>{name}</title>
38
+ {/if}
39
+ </circle>
40
+ {#if symbol}
41
+ <text>{symbol}</text>
42
+ {/if}
43
+
44
+ <!-- electron orbitals -->
45
+ {#each shells as electrons, shell_idx ([electrons, shell_idx])}
46
+ {@const n = shell_idx + 1}
47
+ {@const shell_radius = _nucleus_props.r + n * shell_width}
48
+ {@const active = n === highlight_shell}
49
+ <g class="shell" style:animation-duration="{orbital_period * n ** 1.5}s">
50
+ <circle
51
+ r={shell_radius}
52
+ {..._shell_props}
53
+ style:stroke-width={active ? 2 : 1}
54
+ style:stroke={active ? `yellow` : `white`}
55
+ />
56
+
57
+ <!-- electrons -->
58
+ {#each Array(electrons) as _, elec_idx (elec_idx)}
59
+ {@const elec_x = Math.cos((2 * Math.PI * elec_idx) / electrons) * shell_radius}
60
+ {@const elec_y = Math.sin((2 * Math.PI * elec_idx) / electrons) * shell_radius}
61
+ <circle class="electron" cx={elec_x} cy={elec_y} {..._electron_props}>
62
+ <title>Electron {elec_idx + 1}</title>
63
+ </circle>
64
+ {#if number_electrons}
65
+ <text
66
+ x={elec_x}
67
+ y={elec_y}
68
+ {...electron_label_props}
69
+ transform="rotate({(elec_idx * 360) / electrons} {elec_x} {elec_y})"
70
+ >
71
+ {#if typeof number_electrons === `function`}
72
+ {number_electrons(elec_idx)}
73
+ {:else if number_electrons === `hierarchical`}
74
+ {shell_idx + 1}.{elec_idx + 1}
75
+ <!-- {:else if [`sequential`, true].includes(number_electrons)} -->
76
+ {:else}
77
+ {@const nth_electron = shells.slice(0, shell_idx).reduce((a, b) => a + b, 0) +
78
+ elec_idx + 1}
79
+ {nth_electron}
80
+ {/if}
81
+ </text>
82
+ {/if}
83
+ {/each}
84
+ </g>
85
+ {/each}
86
+ </svg>
87
+
88
+ <style>
89
+ svg {
90
+ overflow: visible;
91
+ width: 100%;
92
+ }
93
+ g.shell {
94
+ animation: spin-right linear infinite;
95
+ }
96
+ text {
97
+ text-anchor: middle;
98
+ dominant-baseline: central;
99
+ }
100
+ @keyframes spin-right {
101
+ 100% {
102
+ transform: rotate(360deg);
103
+ }
104
+ }
105
+ </style>
@@ -0,0 +1,21 @@
1
+ interface Props {
2
+ symbol?: string;
3
+ name?: string;
4
+ shells: number[];
5
+ adapt_size?: boolean;
6
+ shell_width?: number;
7
+ size?: number;
8
+ base_fill?: string;
9
+ orbital_period?: number;
10
+ nucleus_props?: Record<string, string | number>;
11
+ shell_props?: Record<string, string | number>;
12
+ electron_props?: Record<string, string | number>;
13
+ highlight_shell?: number | null;
14
+ style?: string;
15
+ number_electrons?: boolean | `hierarchical` | `sequential` | ((idx: number) => string);
16
+ electron_label_props?: Record<string, string | number>;
17
+ [key: string]: unknown;
18
+ }
19
+ declare const BohrAtom: import("svelte").Component<Props, {}, "">;
20
+ type BohrAtom = ReturnType<typeof BohrAtom>;
21
+ export default BohrAtom;
@@ -0,0 +1,158 @@
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, controls, } = $props();
3
+ function on_keydown(event) {
4
+ if (event.key === `Escape`)
5
+ controls_open = false;
6
+ }
7
+ function toggle_controls() {
8
+ controls_open = !controls_open;
9
+ }
10
+ </script>
11
+
12
+ <svelte:window onkeydown={on_keydown} />
13
+
14
+ {#if show_controls}
15
+ {#if show_toggle_button}
16
+ <button
17
+ bind:this={toggle_controls_btn}
18
+ onclick={toggle_controls}
19
+ aria-expanded={controls_open}
20
+ aria-controls="controls-panel"
21
+ title={toggle_button.title ?? (controls_open ? `Close controls` : `Open controls`)}
22
+ {...toggle_button}
23
+ class="controls-toggle {toggle_button.class ?? ``}"
24
+ >
25
+ <Icon
26
+ icon={controls_open ? open_icon : closed_icon}
27
+ style="width: 24px; height: 24px"
28
+ />
29
+ </button>
30
+ {/if}
31
+
32
+ <div
33
+ class:controls-open={controls_open}
34
+ bind:this={controls}
35
+ role="dialog"
36
+ {...panel_props}
37
+ class="controls {panel_props.class ?? ``}"
38
+ >
39
+ {#if controls_content}
40
+ {@render controls_content()}
41
+ {/if}
42
+ </div>
43
+ {/if}
44
+
45
+ <style>
46
+ .controls-toggle {
47
+ background-color: transparent;
48
+ min-width: 28px;
49
+ height: 28px;
50
+ padding: 0.125rem 0.25rem;
51
+ font-size: 0.8rem;
52
+ box-sizing: border-box;
53
+ }
54
+ .controls-toggle:hover {
55
+ background-color: transparent !important;
56
+ }
57
+ .controls {
58
+ position: absolute;
59
+ left: unset;
60
+ background: transparent;
61
+ border: none;
62
+ display: grid;
63
+ gap: var(--controls-gap, 4pt);
64
+ 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);
68
+ box-sizing: border-box;
69
+ top: var(--controls-top, 30pt);
70
+ right: var(--controls-right, 6pt);
71
+ background: var(--controls-bg, rgba(10, 10, 10, 0.95));
72
+ padding: var(--controls-padding, 6pt 9pt);
73
+ border-radius: var(--controls-border-radius, 3pt);
74
+ width: var(--controls-width, 20em);
75
+ max-width: var(--controls-max-width, 90cqw);
76
+ color: var(--controls-text-color);
77
+ overflow: auto;
78
+ max-height: var(--controls-max-height, calc(100vh - 3em));
79
+ visibility: hidden;
80
+ opacity: 0;
81
+ z-index: var(--controls-z-index, 1);
82
+ pointer-events: none;
83
+ }
84
+ .controls.controls-open {
85
+ visibility: visible !important;
86
+ opacity: 1 !important;
87
+ pointer-events: auto !important;
88
+ }
89
+ .controls :global(hr) {
90
+ border: none;
91
+ background: var(--controls-hr-bg, gray);
92
+ margin: var(--controls-hr-margin, 0);
93
+ height: var(--controls-hr-height, 0.5px);
94
+ }
95
+ .controls :global(label) {
96
+ display: flex;
97
+ align-items: center;
98
+ gap: var(--controls-label-gap, 2pt);
99
+ }
100
+ .controls :global(input[type='range']) {
101
+ margin-left: auto;
102
+ width: var(--controls-input-range-width, 100px);
103
+ flex-shrink: 0;
104
+ }
105
+ .controls :global(.slider-control input[type='range']) {
106
+ margin-left: 0;
107
+ }
108
+ .controls :global(input[type='number']) {
109
+ box-sizing: border-box;
110
+ text-align: center;
111
+ border-radius: var(--controls-input-num-border-radius, 3pt);
112
+ width: var(--controls-input-num-width, 2.2em);
113
+ border: var(--controls-input-num-border, none);
114
+ background: var(--controls-input-num-bg, rgba(255, 255, 255, 0.15));
115
+ margin-right: 3pt;
116
+ margin-left: var(--controls-input-num-margin-left, 6pt);
117
+ flex-shrink: 0;
118
+ }
119
+ .controls :global(input::-webkit-inner-spin-button) {
120
+ display: none;
121
+ }
122
+ .controls :global(button) {
123
+ width: max-content;
124
+ background-color: var(--controls-btn-bg, rgba(255, 255, 255, 0.2));
125
+ }
126
+ .controls :global(select) {
127
+ margin: var(--controls-select-margin, 0 0 0 5pt);
128
+ color: var(--controls-select-color, white);
129
+ background-color: var(--controls-select-bg, rgba(255, 255, 255, 0.1));
130
+ }
131
+ .controls :global(input[type='color']) {
132
+ width: var(--input-color-width, 40px);
133
+ height: var(--input-color-height, 16px);
134
+ margin: var(--input-color-margin, 0 0 0 5pt);
135
+ border: var(--input-color-border, 1px solid rgba(255, 255, 255, 0.05));
136
+ box-sizing: border-box;
137
+ }
138
+ .controls :global(.section-heading) {
139
+ margin: 8pt 0 2pt;
140
+ font-size: 0.9em;
141
+ color: var(--text-muted, #ccc);
142
+ }
143
+ .controls :global(.control-row) {
144
+ display: flex;
145
+ gap: 4pt;
146
+ align-items: flex-start;
147
+ }
148
+ .controls :global(.control-row label) {
149
+ min-width: 0;
150
+ }
151
+ .controls :global(.control-row label.compact) {
152
+ flex: 0 0 auto;
153
+ margin-right: 8pt;
154
+ }
155
+ .controls :global(.control-row label.slider-control) {
156
+ flex: 1;
157
+ }
158
+ </style>
@@ -0,0 +1,18 @@
1
+ import type { IconName } from './icons';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ interface Props {
5
+ controls_open?: boolean;
6
+ show_controls?: boolean;
7
+ controls_content?: Snippet<[]>;
8
+ toggle_button?: HTMLAttributes<HTMLButtonElement>;
9
+ panel_props?: HTMLAttributes<HTMLDivElement>;
10
+ show_toggle_button?: boolean;
11
+ open_icon?: IconName;
12
+ closed_icon?: IconName;
13
+ toggle_controls_btn?: HTMLButtonElement;
14
+ controls?: HTMLDivElement;
15
+ }
16
+ declare const ControlPanel: import("svelte").Component<Props, {}, "controls_open">;
17
+ type ControlPanel = ReturnType<typeof ControlPanel>;
18
+ export default ControlPanel;
@@ -0,0 +1,23 @@
1
+ <script lang="ts">import { icon_data } from './icons';
2
+ let { icon, ...rest } = $props();
3
+ const data = $derived.by(() => {
4
+ if (!(icon in icon_data)) {
5
+ console.error(`Icon '${icon}' not found`);
6
+ return icon_data.Alert; // fallback
7
+ }
8
+ return icon_data[icon];
9
+ });
10
+ </script>
11
+
12
+ <svg viewBox={data.viewBox} fill="currentColor" {...rest}>
13
+ <path d={data.path} />
14
+ </svg>
15
+
16
+ <style>
17
+ svg {
18
+ width: 1em;
19
+ height: 1em;
20
+ display: inline-block;
21
+ vertical-align: middle;
22
+ }
23
+ </style>
@@ -0,0 +1,8 @@
1
+ import { type IconName } from './icons';
2
+ interface Props {
3
+ icon: IconName;
4
+ [key: string]: unknown;
5
+ }
6
+ declare const Icon: import("svelte").Component<Props, {}, "">;
7
+ type Icon = ReturnType<typeof Icon>;
8
+ export default Icon;
@@ -0,0 +1,79 @@
1
+ <script lang="ts">import { format_num } from './';
2
+ let { data = [], title = ``, fallback = ``, fmt = `.2f`, as = `section`, style = null, title_snippet, fallback_snippet, ...rest } = $props();
3
+ // rename fmt as default_fmt internally
4
+ let default_fmt = $derived(fmt);
5
+ </script>
6
+
7
+ <svelte:element this={as} class="info-card" {style} {...rest}>
8
+ {#if title || title_snippet}
9
+ <h2>
10
+ {#if title_snippet}{@render title_snippet()}{:else}
11
+ {@html title}
12
+ {/if}
13
+ </h2>
14
+ {/if}
15
+ {#each data.filter((itm) =>
16
+ (!(`condition` in itm) || itm?.condition) &&
17
+ ![undefined, null].includes(itm.value)
18
+ ) as
19
+ { title, value, unit, fmt = default_fmt, tooltip }
20
+ (title + value + unit + fmt)
21
+ }
22
+ <div>
23
+ <span class="title" {title}>
24
+ {@html title}
25
+ </span>
26
+ <strong title={tooltip ?? null}>
27
+ {@html typeof value == `number` ? format_num(value, fmt) : value}
28
+ {#if unit}
29
+ <small>{unit}</small>
30
+ {/if}
31
+ </strong>
32
+ </div>
33
+ {:else}
34
+ {#if fallback_snippet}{@render fallback_snippet()}{:else}
35
+ {fallback}
36
+ {/if}
37
+ {/each}
38
+ </svelte:element>
39
+
40
+ <style>
41
+ .info-card {
42
+ display: grid;
43
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
44
+ box-sizing: border-box;
45
+ border-radius: var(--ic-radius, 3pt);
46
+ padding: var(--ic-padding, 10pt 12pt);
47
+ margin: var(--ic-margin, 1em 0);
48
+ gap: var(--ic-gap, 10pt 5%);
49
+ background-color: var(--ic-bg, rgba(255, 255, 255, 0.1));
50
+ font-size: var(--ic-font-size);
51
+ width: var(--ic-width);
52
+ }
53
+ h2 {
54
+ grid-column: 1 / -1;
55
+ margin: 0;
56
+ border-bottom: 1px solid var(--ic-title-border-color, rgba(255, 255, 255, 0.3));
57
+ }
58
+ div {
59
+ display: flex;
60
+ justify-content: space-between;
61
+ align-items: center;
62
+ white-space: nowrap;
63
+ gap: var(--ic-value-gap);
64
+ }
65
+ div > span.title {
66
+ text-overflow: ellipsis;
67
+ overflow: hidden;
68
+ }
69
+ strong {
70
+ font-weight: 600;
71
+ margin: var(--ic-value-margin);
72
+ background-color: var(--ic-value-bg, rgba(255, 255, 255, 0.1));
73
+ padding: var(--ic-value-padding, 0 4pt);
74
+ border-radius: var(--ic-value-radius, 3pt);
75
+ }
76
+ strong small {
77
+ font-weight: normal;
78
+ }
79
+ </style>
@@ -0,0 +1,23 @@
1
+ import type { PropertyOrigin } from '../types';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ data?: {
5
+ title: string;
6
+ value?: string | number | number[] | null | PropertyOrigin;
7
+ unit?: string;
8
+ fmt?: string;
9
+ condition?: boolean | number | null;
10
+ tooltip?: string;
11
+ }[];
12
+ title?: string;
13
+ fallback?: string;
14
+ fmt?: string;
15
+ as?: string;
16
+ style?: string | null;
17
+ title_snippet?: Snippet;
18
+ fallback_snippet?: Snippet;
19
+ [key: string]: unknown;
20
+ }
21
+ declare const InfoCard: import("svelte").Component<Props, {}, "">;
22
+ type InfoCard = ReturnType<typeof InfoCard>;
23
+ export default InfoCard;
@@ -0,0 +1,64 @@
1
+ <script lang="ts">"use strict";
2
+ let { protons, neutrons, size = 100, radius = $bindable(size / 2), proton_color = `cornflowerblue`, neutron_color = `orange`, stroke = ``, proton_label = ` P`, neutron_label = ` N`, text_color = `white`, symbol = ``, } = $props();
3
+ $effect(() => {
4
+ radius = size / 2;
5
+ });
6
+ let proton_frac = $derived(protons / (protons + neutrons));
7
+ let neutron_frac = $derived(1 - proton_frac);
8
+ let proton_circ = $derived(Math.PI * radius * proton_frac);
9
+ let dash_array = $derived(`0 ${Math.PI * radius - proton_circ} ${proton_circ}`);
10
+ let text = $derived({
11
+ 'dominant-baseline': `middle`,
12
+ 'text-anchor': `middle`,
13
+ fill: text_color,
14
+ });
15
+ </script>
16
+
17
+ <svg width="100%" height="100%" viewBox="0 0 {size} {size}">
18
+ <circle r={radius} cx={radius} cy={radius} fill={neutron_color} {stroke}>
19
+ <title>Neutrons: {neutrons}</title>
20
+ </circle>
21
+
22
+ <circle
23
+ r={radius / 2}
24
+ cx={radius}
25
+ cy={radius}
26
+ fill={neutron_color}
27
+ stroke={proton_color}
28
+ stroke-width={radius}
29
+ stroke-dasharray={dash_array}
30
+ >
31
+ <title>Protons: {protons}</title>
32
+ </circle>
33
+
34
+ <text
35
+ x={radius + (radius / 2) * Math.cos(Math.PI * -proton_frac)}
36
+ y={radius + (radius / 2) * Math.sin(Math.PI * -proton_frac)}
37
+ {...text}
38
+ >
39
+ {protons} {proton_label}
40
+ </text>
41
+
42
+ <text
43
+ x={radius + (radius / 2) * Math.cos(Math.PI * neutron_frac)}
44
+ y={radius + (radius / 2) * Math.sin(Math.PI * neutron_frac)}
45
+ {...text}
46
+ >
47
+ {neutrons} {neutron_label}
48
+ </text>
49
+
50
+ {#if symbol}
51
+ <text class="symbol" x={radius} y={radius} {...text}>
52
+ {symbol}
53
+ </text>
54
+ {/if}
55
+ </svg>
56
+
57
+ <style>
58
+ text {
59
+ font-size: 11pt;
60
+ }
61
+ text.symbol {
62
+ font-size: 15pt;
63
+ }
64
+ </style>
@@ -0,0 +1,16 @@
1
+ interface Props {
2
+ protons: number;
3
+ neutrons: number;
4
+ radius?: number;
5
+ size?: number;
6
+ proton_color?: string;
7
+ neutron_color?: string;
8
+ stroke?: string;
9
+ proton_label?: string;
10
+ neutron_label?: string;
11
+ text_color?: string;
12
+ symbol?: string;
13
+ }
14
+ declare const Nucleus: import("svelte").Component<Props, {}, "radius">;
15
+ type Nucleus = ReturnType<typeof Nucleus>;
16
+ export default Nucleus;
@@ -0,0 +1,44 @@
1
+ <script lang="ts">"use strict";
2
+ let { text = `Loading...`, ...rest } = $props();
3
+ </script>
4
+
5
+ <div class="spinner-overlay" role="status" aria-live="polite" {...rest}>
6
+ <div class="spinner" aria-hidden="true"></div>
7
+ <p>{text}</p>
8
+ </div>
9
+
10
+ <style>
11
+ .spinner-overlay {
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ right: 0;
16
+ bottom: 0;
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: center;
20
+ justify-content: center;
21
+ background: var(--spinner-bg, rgba(255, 255, 255, 0.9));
22
+ color: var(--spinner-text-color, #333);
23
+ backdrop-filter: blur(4px);
24
+ z-index: var(--spinner-z-index, 10);
25
+ }
26
+ .spinner {
27
+ width: var(--spinner-size, 40px);
28
+ height: var(--spinner-size, 40px);
29
+ border: var(--spinner-border-width, 4px) solid var(--spinner-track-color, #f3f3f3);
30
+ border-top: var(--spinner-border-width, 4px) solid var(--spinner-color, #007acc);
31
+ border-radius: 50%;
32
+ animation: spin 1s linear infinite;
33
+ margin-bottom: 1rem;
34
+ box-sizing: border-box;
35
+ }
36
+ @keyframes spin {
37
+ 0% {
38
+ transform: rotate(0deg);
39
+ }
40
+ 100% {
41
+ transform: rotate(360deg);
42
+ }
43
+ }
44
+ </style>
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ text?: string;
3
+ [key: string]: unknown;
4
+ }
5
+ declare const Spinner: import("svelte").Component<Props, {}, "">;
6
+ type Spinner = ReturnType<typeof Spinner>;
7
+ export default Spinner;
package/dist/api.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare const mp_build_bucket = "https://materialsproject-build.s3.amazonaws.com/collections/2022-10-28";
2
+ export declare function decompress(blob: ReadableStream<Uint8Array> | null): Promise<string>;
3
+ export declare function fetch_zipped<T>(url: string, { unzip }?: {
4
+ unzip?: boolean | undefined;
5
+ }): Promise<T | null>;
6
+ export declare function download(data: string | Blob, filename: string, type: string): void;
package/dist/api.js ADDED
@@ -0,0 +1,30 @@
1
+ // TODO update to get MP details pages working again
2
+ export const mp_build_bucket = `https://materialsproject-build.s3.amazonaws.com/collections/2022-10-28`;
3
+ export async function decompress(blob) {
4
+ const unzip = new DecompressionStream(`gzip`);
5
+ const stream = blob?.pipeThrough(unzip);
6
+ return await new Response(stream).text();
7
+ }
8
+ export async function fetch_zipped(url, { unzip = true } = {}) {
9
+ const response = await fetch(url);
10
+ if (!response.ok) {
11
+ console.error(`${response.status} ${response.statusText} for ${response.url}`);
12
+ return null;
13
+ }
14
+ if (!unzip)
15
+ return (await response.blob());
16
+ return JSON.parse(await decompress(response.body));
17
+ }
18
+ // Function to download data to a file
19
+ export function download(data, filename, type) {
20
+ const file = new Blob([data], { type });
21
+ const link = document.createElement(`a`);
22
+ const url = URL.createObjectURL(file);
23
+ link.style.display = `none`;
24
+ link.href = url;
25
+ link.download = filename;
26
+ document.body.appendChild(link);
27
+ link.click();
28
+ link.remove();
29
+ URL.revokeObjectURL(url);
30
+ }