matterviz 0.1.8 → 0.1.10
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/ContextMenu.svelte +1 -1
- package/dist/ContextMenu.svelte.d.ts +3 -3
- package/dist/DraggablePane.svelte +38 -38
- package/dist/DraggablePane.svelte.d.ts +0 -1
- package/dist/FilePicker.svelte +42 -60
- package/dist/FilePicker.svelte.d.ts +3 -4
- package/dist/Icon.svelte +1 -1
- package/dist/Icon.svelte.d.ts +2 -2
- package/dist/InfoCard.svelte +4 -4
- package/dist/InfoCard.svelte.d.ts +4 -5
- package/dist/SettingsSection.svelte +2 -2
- package/dist/SettingsSection.svelte.d.ts +2 -2
- package/dist/Spinner.svelte +3 -3
- package/dist/Spinner.svelte.d.ts +2 -2
- package/dist/api/optimade.d.ts +2 -2
- package/dist/app.css +11 -8
- package/dist/colors/index.d.ts +9 -1
- package/dist/colors/index.js +19 -6
- package/dist/composition/BarChart.svelte +10 -6
- package/dist/composition/BarChart.svelte.d.ts +2 -2
- package/dist/composition/BubbleChart.svelte +3 -3
- package/dist/composition/BubbleChart.svelte.d.ts +2 -2
- package/dist/composition/Composition.svelte +24 -13
- package/dist/composition/Composition.svelte.d.ts +2 -2
- package/dist/composition/PieChart.svelte +2 -2
- package/dist/composition/PieChart.svelte.d.ts +2 -2
- package/dist/element/BohrAtom.svelte +10 -5
- package/dist/element/BohrAtom.svelte.d.ts +2 -2
- package/dist/element/ElementHeading.svelte.d.ts +2 -3
- package/dist/element/ElementPhoto.svelte +4 -9
- package/dist/element/ElementPhoto.svelte.d.ts +2 -2
- package/dist/element/ElementStats.svelte.d.ts +2 -2
- package/dist/element/ElementTile.svelte +19 -34
- package/dist/element/ElementTile.svelte.d.ts +6 -6
- package/dist/icons.d.ts +12 -0
- package/dist/icons.js +12 -0
- package/dist/index.d.ts +7 -0
- package/dist/labels.d.ts +2 -0
- package/dist/labels.js +39 -0
- package/dist/material/MaterialCard.svelte +4 -5
- package/dist/material/MaterialCard.svelte.d.ts +2 -2
- package/dist/material/index.d.ts +0 -1
- package/dist/material/index.js +0 -1
- package/dist/math.d.ts +2 -0
- package/dist/math.js +24 -12
- package/dist/periodic-table/PeriodicTable.svelte +1 -1
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +2 -2
- package/dist/periodic-table/PropertySelect.svelte +2 -3
- package/dist/periodic-table/PropertySelect.svelte.d.ts +2 -3
- package/dist/periodic-table/TableInset.svelte +3 -3
- package/dist/periodic-table/TableInset.svelte.d.ts +3 -3
- package/dist/plot/ColorBar.svelte +21 -29
- package/dist/plot/ColorBar.svelte.d.ts +6 -6
- package/dist/plot/ColorScaleSelect.svelte +1 -1
- package/dist/plot/ColorScaleSelect.svelte.d.ts +4 -4
- package/dist/plot/ElementScatter.svelte.d.ts +4 -4
- package/dist/plot/Histogram.svelte +34 -18
- package/dist/plot/Histogram.svelte.d.ts +3 -3
- package/dist/plot/HistogramControls.svelte +1 -2
- package/dist/plot/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/Line.svelte.d.ts +2 -2
- package/dist/plot/PlotLegend.svelte +3 -3
- package/dist/plot/PlotLegend.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot.svelte +21 -24
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlotControls.svelte +4 -6
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte.d.ts +2 -2
- package/dist/plot/data-transform.d.ts +3 -3
- package/dist/plot/data-transform.js +13 -13
- package/dist/settings.d.ts +2 -0
- package/dist/settings.js +10 -0
- package/dist/structure/CanvasTooltip.svelte +3 -3
- package/dist/structure/CanvasTooltip.svelte.d.ts +2 -2
- package/dist/structure/Lattice.svelte +5 -3
- package/dist/structure/Lattice.svelte.d.ts +4 -3
- package/dist/structure/Structure.svelte +40 -53
- package/dist/structure/Structure.svelte.d.ts +12 -10
- package/dist/structure/StructureControls.svelte +139 -72
- package/dist/structure/StructureControls.svelte.d.ts +3 -12
- package/dist/structure/StructureInfoPane.svelte +94 -33
- package/dist/structure/StructureInfoPane.svelte.d.ts +5 -3
- package/dist/structure/StructureLegend.svelte +9 -8
- package/dist/structure/StructureLegend.svelte.d.ts +2 -2
- package/dist/structure/StructureScene.svelte +438 -376
- package/dist/structure/StructureScene.svelte.d.ts +6 -3
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +87 -17
- package/dist/structure/parse.js +155 -79
- package/dist/structure/pbc.js +3 -0
- package/dist/symmetry/WyckoffTable.svelte +85 -0
- package/dist/symmetry/WyckoffTable.svelte.d.ts +10 -0
- package/dist/symmetry/index.d.ts +17 -0
- package/dist/symmetry/index.js +121 -0
- package/dist/theme/ThemeControl.svelte +2 -3
- package/dist/theme/ThemeControl.svelte.d.ts +2 -2
- package/dist/theme/themes.js +54 -88
- package/dist/trajectory/Trajectory.svelte +11 -10
- package/dist/trajectory/Trajectory.svelte.d.ts +2 -2
- package/dist/trajectory/TrajectoryInfoPane.svelte +14 -22
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +1 -2
- package/dist/trajectory/plotting.js +9 -8
- package/package.json +16 -15
- package/dist/material/SymmetryCard.svelte +0 -11
- package/dist/material/SymmetryCard.svelte.d.ts +0 -8
package/dist/ContextMenu.svelte
CHANGED
|
@@ -52,7 +52,7 @@ function handle_option_click(section_title, option) {
|
|
|
52
52
|
{#if visible}
|
|
53
53
|
{@const { x, y } = get_smart_position()}
|
|
54
54
|
{@const style = `position: absolute; left: ${x}px; top: ${y}px; ${rest.style ?? ``}`}
|
|
55
|
-
<div class="context-menu
|
|
55
|
+
<div {...rest} class="context-menu {rest.class ?? ``}" {style} bind:this={menu_element}>
|
|
56
56
|
{#each sections as { title, options } (title)}
|
|
57
57
|
<div class="section">
|
|
58
58
|
<div class="header">{title}</div>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
1
2
|
interface MenuOption {
|
|
2
3
|
value: string;
|
|
3
4
|
icon?: string;
|
|
4
5
|
label?: string;
|
|
5
6
|
disabled?: boolean;
|
|
6
7
|
}
|
|
7
|
-
interface Props {
|
|
8
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
8
9
|
sections: Readonly<{
|
|
9
10
|
title: string;
|
|
10
11
|
options: readonly MenuOption[];
|
|
@@ -17,8 +18,7 @@ interface Props {
|
|
|
17
18
|
};
|
|
18
19
|
visible: boolean;
|
|
19
20
|
on_close?: () => void;
|
|
20
|
-
menu_element?:
|
|
21
|
-
[key: string]: unknown;
|
|
21
|
+
menu_element?: HTMLDivElement;
|
|
22
22
|
}
|
|
23
23
|
declare const ContextMenu: import("svelte").Component<Props, {}, "menu_element">;
|
|
24
24
|
type ContextMenu = ReturnType<typeof ContextMenu>;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
<script lang="ts">import { Icon } from './';
|
|
2
2
|
import { draggable, tooltip } from 'svelte-multiselect/attachments';
|
|
3
|
-
let { show = $bindable(false), show_pane = true, children, toggle_props = {}, open_icon = `Cross`, closed_icon = `Settings`, icon_style = ``, offset = { x: 5, y: 5 }, max_width = `450px`, pane_props = {}, onclose = () => { }, on_drag_start = () => { },
|
|
3
|
+
let { show = $bindable(false), show_pane = true, children, toggle_props = {}, open_icon = `Cross`, closed_icon = `Settings`, icon_style = ``, offset = { x: 5, y: 5 }, max_width = `450px`, pane_props = {}, onclose = () => { }, on_drag_start = () => { }, toggle_pane_btn = $bindable(undefined), pane_div = $bindable(undefined), has_been_dragged = $bindable(false), currently_dragging = $bindable(false), } = $props();
|
|
4
4
|
let initial_position = $state({ left: `50px`, top: `50px` });
|
|
5
5
|
let show_control_buttons = $state(false);
|
|
6
|
-
// Keyboard shortcuts
|
|
7
|
-
function on_keydown(event) {
|
|
8
|
-
if (event.key === `Escape`) {
|
|
9
|
-
event.preventDefault();
|
|
10
|
-
close_pane();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
6
|
function toggle_pane() {
|
|
14
7
|
show = !show;
|
|
15
8
|
if (!show)
|
|
@@ -52,8 +45,7 @@ function calculate_position() {
|
|
|
52
45
|
const pane_width = pane_div?.getBoundingClientRect().width || 450;
|
|
53
46
|
const positioned_ancestor = toggle_pane_btn.offsetParent;
|
|
54
47
|
const ancestor_rect = positioned_ancestor?.getBoundingClientRect();
|
|
55
|
-
if (!ancestor_rect) {
|
|
56
|
-
// Fallback to document positioning
|
|
48
|
+
if (!ancestor_rect) { // Fallback to document positioning
|
|
57
49
|
const scroll_x = window.scrollX || document.documentElement.scrollLeft;
|
|
58
50
|
const scroll_y = window.scrollY || document.documentElement.scrollTop;
|
|
59
51
|
return {
|
|
@@ -61,11 +53,9 @@ function calculate_position() {
|
|
|
61
53
|
top: `${toggle_rect.bottom + (offset.y ?? 5) + scroll_y}px`,
|
|
62
54
|
};
|
|
63
55
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
top: `${toggle_rect.bottom - ancestor_rect.top + (offset.y ?? 5)}px`,
|
|
68
|
-
};
|
|
56
|
+
const left = `${toggle_rect.right - ancestor_rect.left - pane_width + (offset.x ?? 5)}px`;
|
|
57
|
+
const top = `${toggle_rect.bottom - ancestor_rect.top + (offset.y ?? 5)}px`;
|
|
58
|
+
return { left, top }; // Position relative to positioned ancestor
|
|
69
59
|
}
|
|
70
60
|
// Click outside handler
|
|
71
61
|
function handle_click_outside(event) {
|
|
@@ -79,11 +69,6 @@ function handle_click_outside(event) {
|
|
|
79
69
|
if (!is_toggle_button && !is_inside_pane && !currently_dragging)
|
|
80
70
|
close_pane();
|
|
81
71
|
}
|
|
82
|
-
// Button click handler
|
|
83
|
-
const handle_button_click = (action) => (event) => {
|
|
84
|
-
event.stopPropagation();
|
|
85
|
-
action();
|
|
86
|
-
};
|
|
87
72
|
// Debounced resize handler for better performance
|
|
88
73
|
let resize_timeout = $state(undefined);
|
|
89
74
|
function handle_resize() {
|
|
@@ -121,16 +106,23 @@ $effect(() => {
|
|
|
121
106
|
});
|
|
122
107
|
</script>
|
|
123
108
|
|
|
124
|
-
<svelte:window
|
|
109
|
+
<svelte:window
|
|
110
|
+
onkeydown={(event: KeyboardEvent) => {
|
|
111
|
+
if (event.key !== `Escape`) return
|
|
112
|
+
event.preventDefault()
|
|
113
|
+
close_pane()
|
|
114
|
+
}}
|
|
115
|
+
onresize={handle_resize}
|
|
116
|
+
/>
|
|
125
117
|
<svelte:document onclick={handle_click_outside} />
|
|
126
118
|
|
|
127
119
|
{#if show_pane}
|
|
128
120
|
<button
|
|
129
121
|
type="button"
|
|
130
122
|
bind:this={toggle_pane_btn}
|
|
131
|
-
onclick={handle_button_click(custom_toggle || toggle_pane)}
|
|
132
123
|
aria-expanded={show}
|
|
133
124
|
{...toggle_props}
|
|
125
|
+
onclick={toggle_pane}
|
|
134
126
|
class="pane-toggle {toggle_props.class ?? ``}"
|
|
135
127
|
{@attach tooltip({ content: toggle_props.title ?? (show ? `Close pane` : `Open pane`) })}
|
|
136
128
|
>
|
|
@@ -159,7 +151,7 @@ $effect(() => {
|
|
|
159
151
|
<button
|
|
160
152
|
type="button"
|
|
161
153
|
class="reset-button"
|
|
162
|
-
onclick={
|
|
154
|
+
onclick={reset_position}
|
|
163
155
|
title="Reset pane position"
|
|
164
156
|
aria-label="Reset pane position"
|
|
165
157
|
>
|
|
@@ -168,7 +160,7 @@ $effect(() => {
|
|
|
168
160
|
<button
|
|
169
161
|
type="button"
|
|
170
162
|
class="close-button"
|
|
171
|
-
onclick={
|
|
163
|
+
onclick={close_pane}
|
|
172
164
|
title="Close pane"
|
|
173
165
|
aria-label="Close pane"
|
|
174
166
|
>
|
|
@@ -194,8 +186,8 @@ $effect(() => {
|
|
|
194
186
|
padding: var(--pane-toggle-padding, 2pt);
|
|
195
187
|
border-radius: var(--pane-toggle-border-radius, 3pt);
|
|
196
188
|
background-color: transparent;
|
|
197
|
-
transition: background-color 0.2s;
|
|
198
|
-
font-size: var(--pane-toggle-font-size, clamp(
|
|
189
|
+
transition: var(--pane-toggle-transition, background-color 0.2s);
|
|
190
|
+
font-size: var(--pane-toggle-font-size, clamp(0.9em, 2cqmin, 1.4em));
|
|
199
191
|
}
|
|
200
192
|
button.pane-toggle:hover {
|
|
201
193
|
background-color: color-mix(in srgb, currentColor 8%, transparent);
|
|
@@ -204,21 +196,25 @@ $effect(() => {
|
|
|
204
196
|
position: absolute; /* Use absolute so pane scrolls with page content */
|
|
205
197
|
background: var(--pane-bg, var(--page-bg, light-dark(white, black)));
|
|
206
198
|
border: var(--pane-border, 1px solid rgba(255, 255, 255, 0.15));
|
|
207
|
-
border-radius: 6px;
|
|
199
|
+
border-radius: var(--pane-border-radius, 6px);
|
|
208
200
|
padding: var(--pane-padding, 1ex);
|
|
209
201
|
box-sizing: border-box;
|
|
210
202
|
z-index: var(--pane-z-index, 10);
|
|
211
203
|
display: grid;
|
|
212
|
-
gap: 4pt;
|
|
204
|
+
gap: var(--pane-gap, 4pt);
|
|
213
205
|
text-align: left;
|
|
214
206
|
/* Exclude position from being transitioned to prevent sluggish dragging */
|
|
215
207
|
transition: opacity 0.3s, background-color 0.3s, border-color 0.3s, box-shadow 0.3s;
|
|
216
208
|
width: 28em;
|
|
217
|
-
max-width:
|
|
218
|
-
overflow-x: hidden;
|
|
219
|
-
overflow-y: auto;
|
|
220
|
-
|
|
221
|
-
|
|
209
|
+
max-width: var(--pane-max-width, 80cqw);
|
|
210
|
+
overflow-x: var(--pane-overflow-x, hidden);
|
|
211
|
+
overflow-y: var(--pane-overflow-y, auto);
|
|
212
|
+
min-height: min(
|
|
213
|
+
var(--pane-min-height, 400px),
|
|
214
|
+
calc(100cqh - var(--pane-bottom-margin, 40px))
|
|
215
|
+
); /* Ensure pane never exceeds its query container, enabling internal scroll */
|
|
216
|
+
max-height: var(--pane-max-height, calc(100cqh - var(--pane-bottom-margin, 40px)));
|
|
217
|
+
overscroll-behavior: contain; /* Prevent scroll chaining to parent containers (e.g. Jupyter cells) */
|
|
222
218
|
}
|
|
223
219
|
:global(body.fullscreen) .draggable-pane {
|
|
224
220
|
position: fixed !important; /* In fullscreen, we want viewport-relative positioning */
|
|
@@ -228,23 +224,26 @@ $effect(() => {
|
|
|
228
224
|
}
|
|
229
225
|
/* Pane content styling */
|
|
230
226
|
.draggable-pane :global(h4) {
|
|
231
|
-
margin: 2pt 0;
|
|
232
|
-
font-size: 0.95em;
|
|
227
|
+
margin: var(--pane-h4-margin, 2pt 0);
|
|
228
|
+
font-size: var(--pane-h4-font-size, 0.95em);
|
|
233
229
|
}
|
|
234
230
|
.draggable-pane :global(hr) {
|
|
235
231
|
border: none;
|
|
236
232
|
background: var(--pane-hr-bg, rgba(255, 255, 255, 0.1));
|
|
237
|
-
margin: 4pt 0;
|
|
233
|
+
margin: var(--pane-hr-margin, 4pt 0);
|
|
238
234
|
height: 1px;
|
|
239
235
|
}
|
|
236
|
+
.draggable-pane :global(> section > div) {
|
|
237
|
+
text-align: right; /* right align long line-breaking trajectory file names */
|
|
238
|
+
}
|
|
240
239
|
.draggable-pane :global(label) {
|
|
241
240
|
display: flex;
|
|
242
241
|
align-items: center;
|
|
243
|
-
gap: 2pt;
|
|
242
|
+
gap: var(--pane-label-gap, 2pt);
|
|
244
243
|
}
|
|
245
244
|
.draggable-pane :global(input[type='text']) {
|
|
246
245
|
flex: 1;
|
|
247
|
-
padding: 4px 6px;
|
|
246
|
+
padding: var(--pane-input-padding, 4px 6px);
|
|
248
247
|
margin: var(--pane-input-margin, 0 0 0 5pt);
|
|
249
248
|
}
|
|
250
249
|
.draggable-pane :global(input[type='text'].invalid) {
|
|
@@ -321,6 +320,7 @@ $effect(() => {
|
|
|
321
320
|
margin-bottom: calc(-2 * 12pt);
|
|
322
321
|
box-sizing: border-box;
|
|
323
322
|
justify-self: end;
|
|
323
|
+
z-index: var(--pane-control-buttons-z-index, 1);
|
|
324
324
|
}
|
|
325
325
|
.draggable-pane :global(.drag-handle) {
|
|
326
326
|
width: 1.3em;
|
package/dist/FilePicker.svelte
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
<script lang="ts">
|
|
1
|
+
<script lang="ts">import { tooltip } from 'svelte-multiselect';
|
|
2
|
+
let { files, active_files = [], show_category_filters = false, on_drag_start, on_drag_end, type_mapper, file_type_colors = {
|
|
2
3
|
cif: `rgba(100, 149, 237, 0.8)`,
|
|
3
4
|
xyz: `rgba(50, 205, 50, 0.8)`,
|
|
4
5
|
extxyz: `rgba(50, 205, 50, 0.8)`,
|
|
@@ -14,23 +15,29 @@
|
|
|
14
15
|
let active_category_filter = $state(null);
|
|
15
16
|
let active_type_filter = $state(null);
|
|
16
17
|
// Helper function to get the base file type (removing .gz extension)
|
|
17
|
-
const get_base_file_type = (
|
|
18
|
+
const get_base_file_type = (file) => {
|
|
18
19
|
// Use custom type mapper if provided
|
|
19
20
|
if (type_mapper)
|
|
20
|
-
return type_mapper(
|
|
21
|
-
let base_name =
|
|
21
|
+
return type_mapper(file);
|
|
22
|
+
let base_name = file.name.toLowerCase();
|
|
22
23
|
// Remove .gz extension if present
|
|
23
24
|
if (base_name.endsWith(`.gz`))
|
|
24
25
|
base_name = base_name.slice(0, -3);
|
|
25
26
|
return base_name.split(`.`).pop() || `file`;
|
|
26
27
|
};
|
|
28
|
+
// Helper function to create normalized category identifier for filtering
|
|
29
|
+
const get_category_id = (file) => {
|
|
30
|
+
if (!file.category)
|
|
31
|
+
return `(uncategorized)`;
|
|
32
|
+
return `${file.category_icon ?? ``} ${file.category}`.trim();
|
|
33
|
+
};
|
|
27
34
|
// Filter files based on active filters
|
|
28
35
|
let filtered_files = $derived(files.filter((file) => {
|
|
29
|
-
if (active_category_filter
|
|
30
|
-
return file
|
|
36
|
+
if (active_category_filter) {
|
|
37
|
+
return get_category_id(file) === active_category_filter;
|
|
31
38
|
}
|
|
32
39
|
if (active_type_filter) {
|
|
33
|
-
const normalized_type = get_base_file_type(file
|
|
40
|
+
const normalized_type = get_base_file_type(file);
|
|
34
41
|
return normalized_type === active_type_filter;
|
|
35
42
|
}
|
|
36
43
|
return true;
|
|
@@ -50,7 +57,7 @@ const handle_drag_start = (file) => (event) => {
|
|
|
50
57
|
const payload = JSON.stringify({
|
|
51
58
|
name: file.name,
|
|
52
59
|
url: file_url,
|
|
53
|
-
type: file.type || get_base_file_type(file
|
|
60
|
+
type: file.type || get_base_file_type(file),
|
|
54
61
|
category: file.category,
|
|
55
62
|
});
|
|
56
63
|
// Set file data as JSON for applications that can handle it
|
|
@@ -59,37 +66,32 @@ const handle_drag_start = (file) => (event) => {
|
|
|
59
66
|
event.dataTransfer?.setData(`text/plain`, file_url);
|
|
60
67
|
on_drag_start?.(file, event);
|
|
61
68
|
};
|
|
62
|
-
// Get unique file types for format filters
|
|
63
|
-
let uniq_formats = $derived([...new Set(files.map(
|
|
64
|
-
|
|
65
|
-
let uniq_categories = $derived(show_category_filters
|
|
66
|
-
? [...new Set(files.map((file) => file.category))].sort().filter(Boolean)
|
|
67
|
-
: []);
|
|
68
|
-
export {};
|
|
69
|
+
// Get unique file types/categories for format/category filters
|
|
70
|
+
let uniq_formats = $derived([...new Set(files.map(get_base_file_type))].sort());
|
|
71
|
+
let uniq_categories = $derived([...new Set(files.map(get_category_id))].filter(Boolean).sort());
|
|
69
72
|
</script>
|
|
70
73
|
|
|
71
74
|
<div class="file-picker" {...rest}>
|
|
72
75
|
<div class="legend">
|
|
73
|
-
{#
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
{/if}
|
|
76
|
+
{#each show_category_filters ? uniq_categories : [] as category (category)}
|
|
77
|
+
{@const is_active = active_category_filter === category}
|
|
78
|
+
<span
|
|
79
|
+
class="legend-item"
|
|
80
|
+
class:active={is_active}
|
|
81
|
+
onclick={() => category && toggle_filter(`category`, category)}
|
|
82
|
+
onkeydown={(evt) =>
|
|
83
|
+
(evt.key === `Enter` || evt.key === ` `) &&
|
|
84
|
+
category &&
|
|
85
|
+
toggle_filter(`category`, category)}
|
|
86
|
+
role="button"
|
|
87
|
+
tabindex="0"
|
|
88
|
+
aria-pressed={is_active}
|
|
89
|
+
{@attach tooltip({ content: `Filter to show only ${category}` })}
|
|
90
|
+
>
|
|
91
|
+
{category}
|
|
92
|
+
</span>
|
|
93
|
+
{/each}
|
|
94
|
+
{#if uniq_categories.length > 0 && uniq_formats.length > 0} {/if}
|
|
93
95
|
|
|
94
96
|
{#each uniq_formats as format (format)}
|
|
95
97
|
{@const is_active = active_type_filter === format}
|
|
@@ -101,7 +103,7 @@ export {};
|
|
|
101
103
|
(evt.key === `Enter` || evt.key === ` `) && toggle_filter(`type`, format)}
|
|
102
104
|
role="button"
|
|
103
105
|
tabindex="0"
|
|
104
|
-
|
|
106
|
+
{@attach tooltip({ content: `Filter to show only ${format.toUpperCase()} files` })}
|
|
105
107
|
>
|
|
106
108
|
<span
|
|
107
109
|
class="format-circle"
|
|
@@ -112,12 +114,9 @@ export {};
|
|
|
112
114
|
|
|
113
115
|
{#if active_category_filter || active_type_filter}
|
|
114
116
|
<button
|
|
115
|
-
|
|
117
|
+
{@attach tooltip({ content: `Clear all filters` })}
|
|
116
118
|
class="clear-filter"
|
|
117
|
-
onclick={() =>
|
|
118
|
-
active_category_filter = null
|
|
119
|
-
active_type_filter = null
|
|
120
|
-
}}
|
|
119
|
+
onclick={() => [active_category_filter, active_type_filter] = [null, null]}
|
|
121
120
|
>
|
|
122
121
|
✕
|
|
123
122
|
</button>
|
|
@@ -125,7 +124,7 @@ export {};
|
|
|
125
124
|
</div>
|
|
126
125
|
|
|
127
126
|
{#each filtered_files as file (file.name)}
|
|
128
|
-
{@const base_type = get_base_file_type(file
|
|
127
|
+
{@const base_type = get_base_file_type(file)}
|
|
129
128
|
{@const is_compressed = file.name.toLowerCase().endsWith(`.gz`)}
|
|
130
129
|
<div
|
|
131
130
|
class="file-item"
|
|
@@ -139,13 +138,8 @@ export {};
|
|
|
139
138
|
tabindex="0"
|
|
140
139
|
title="Drag this {base_type.toUpperCase()} file"
|
|
141
140
|
>
|
|
142
|
-
<div class="drag-handle">
|
|
143
|
-
<div class="drag-bar"></div>
|
|
144
|
-
<div class="drag-bar"></div>
|
|
145
|
-
<div class="drag-bar"></div>
|
|
146
|
-
</div>
|
|
147
141
|
<div class="file-name">
|
|
148
|
-
{file.
|
|
142
|
+
{file.category ? `${file.category_icon} ` : ``}{file.name}
|
|
149
143
|
{#if is_compressed}<span class="compression-indicator">📦</span>{/if}
|
|
150
144
|
</div>
|
|
151
145
|
</div>
|
|
@@ -231,18 +225,6 @@ export {};
|
|
|
231
225
|
background: rgba(0, 122, 204, 0.2);
|
|
232
226
|
filter: brightness(1.1);
|
|
233
227
|
}
|
|
234
|
-
.drag-handle {
|
|
235
|
-
display: flex;
|
|
236
|
-
flex-direction: column;
|
|
237
|
-
gap: 2px;
|
|
238
|
-
opacity: 0.6;
|
|
239
|
-
}
|
|
240
|
-
.drag-bar {
|
|
241
|
-
width: 12px;
|
|
242
|
-
height: 2px;
|
|
243
|
-
background: currentColor;
|
|
244
|
-
border-radius: 1px;
|
|
245
|
-
}
|
|
246
228
|
.file-name {
|
|
247
229
|
font-size: 0.7em;
|
|
248
230
|
line-height: 1.1;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { FileInfo } from './';
|
|
2
|
-
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
3
4
|
files: FileInfo[];
|
|
4
5
|
active_files?: string[];
|
|
5
6
|
show_category_filters?: boolean;
|
|
6
|
-
category_labels?: Record<string, string>;
|
|
7
7
|
on_drag_start?: (file: FileInfo, event: DragEvent) => void;
|
|
8
8
|
on_drag_end?: () => void;
|
|
9
|
-
type_mapper?: (
|
|
9
|
+
type_mapper?: (file: FileInfo) => string;
|
|
10
10
|
file_type_colors?: Record<string, string>;
|
|
11
|
-
[key: string]: unknown;
|
|
12
11
|
}
|
|
13
12
|
declare const FilePicker: import("svelte").Component<Props, {}, "">;
|
|
14
13
|
type FilePicker = ReturnType<typeof FilePicker>;
|
package/dist/Icon.svelte
CHANGED
package/dist/Icon.svelte.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { SVGAttributes } from 'svelte/elements';
|
|
1
2
|
import { type IconName } from './icons';
|
|
2
|
-
interface Props {
|
|
3
|
+
interface Props extends SVGAttributes<SVGSVGElement> {
|
|
3
4
|
icon: IconName;
|
|
4
|
-
[key: string]: unknown;
|
|
5
5
|
}
|
|
6
6
|
declare const Icon: import("svelte").Component<Props, {}, "">;
|
|
7
7
|
type Icon = ReturnType<typeof Icon>;
|
package/dist/InfoCard.svelte
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script lang="ts">import { format_num } from './';
|
|
2
|
-
let { data = [], title = ``, fallback = ``, fmt = `.2f`, as = `section`,
|
|
2
|
+
let { data = [], title = ``, fallback = ``, fmt = `.2f`, as = `section`, title_snippet, fallback_snippet, ...rest } = $props();
|
|
3
3
|
// rename fmt as default_fmt internally
|
|
4
4
|
let default_fmt = $derived(fmt);
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
|
-
<svelte:element this={as} class="info-card
|
|
7
|
+
<svelte:element this={as} {...rest} class="info-card {rest.class ?? ``}">
|
|
8
8
|
{#if title || title_snippet}
|
|
9
9
|
<h2>
|
|
10
10
|
{#if title_snippet}{@render title_snippet()}{:else}
|
|
@@ -13,8 +13,8 @@ let default_fmt = $derived(fmt);
|
|
|
13
13
|
</h2>
|
|
14
14
|
{/if}
|
|
15
15
|
{#each data.filter((itm) =>
|
|
16
|
-
(!(`condition` in itm) || itm?.condition) &&
|
|
17
|
-
|
|
16
|
+
(!(`condition` in itm) || itm?.condition) && itm.value !== undefined &&
|
|
17
|
+
itm.value !== null
|
|
18
18
|
) as
|
|
19
19
|
{ title, value, unit, fmt = default_fmt, tooltip }
|
|
20
20
|
(title + value + unit + fmt)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props<T extends keyof HTMLElementTagNameMap = `section`> extends HTMLAttributes<HTMLElementTagNameMap[T]> {
|
|
3
4
|
data?: {
|
|
4
5
|
title: string;
|
|
5
6
|
value?: string | number | number[] | null;
|
|
@@ -11,12 +12,10 @@ interface Props {
|
|
|
11
12
|
title?: string;
|
|
12
13
|
fallback?: string;
|
|
13
14
|
fmt?: string;
|
|
14
|
-
as?:
|
|
15
|
-
style?: string | null;
|
|
15
|
+
as?: T;
|
|
16
16
|
title_snippet?: Snippet;
|
|
17
17
|
fallback_snippet?: Snippet;
|
|
18
|
-
[key: string]: unknown;
|
|
19
18
|
}
|
|
20
|
-
declare const InfoCard: import("svelte").Component<Props
|
|
19
|
+
declare const InfoCard: import("svelte").Component<Props<"section">, {}, "">;
|
|
21
20
|
type InfoCard = ReturnType<typeof InfoCard>;
|
|
22
21
|
export default InfoCard;
|
|
@@ -59,7 +59,7 @@ function handle_reset(event) {
|
|
|
59
59
|
}
|
|
60
60
|
</script>
|
|
61
61
|
|
|
62
|
-
<h4>
|
|
62
|
+
<h4 id="settings-section-title">
|
|
63
63
|
{title}
|
|
64
64
|
|
|
65
65
|
{#if has_changes}
|
|
@@ -74,7 +74,7 @@ function handle_reset(event) {
|
|
|
74
74
|
</button>
|
|
75
75
|
{/if}
|
|
76
76
|
</h4>
|
|
77
|
-
<section {...rest}>
|
|
77
|
+
<section {...rest} aria-labelledby="settings-section-title">
|
|
78
78
|
{@render children()}
|
|
79
79
|
</section>
|
|
80
80
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLElementTagNameMap[`section`]> {
|
|
3
4
|
title: string;
|
|
4
5
|
current_values: Record<string, unknown>;
|
|
5
6
|
children: Snippet<[]>;
|
|
6
7
|
on_reset?: () => void;
|
|
7
|
-
[key: string]: unknown;
|
|
8
8
|
}
|
|
9
9
|
declare const SettingsSection: import("svelte").Component<Props, {}, "">;
|
|
10
10
|
type SettingsSection = ReturnType<typeof SettingsSection>;
|
package/dist/Spinner.svelte
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
1
|
+
<script lang="ts">let { text = `Loading...`, ...rest } = $props();
|
|
2
|
+
export {};
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
|
-
<div class="spinner-overlay" role="status" aria-live="polite" {...rest}>
|
|
5
|
+
<div class="spinner-overlay" role="status" aria-live="polite" aria-busy="true" {...rest}>
|
|
6
6
|
<div class="spinner" aria-hidden="true"></div>
|
|
7
7
|
<p>{text}</p>
|
|
8
8
|
</div>
|
package/dist/Spinner.svelte.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
2
3
|
text?: string;
|
|
3
|
-
[key: string]: unknown;
|
|
4
4
|
}
|
|
5
5
|
declare const Spinner: import("svelte").Component<Props, {}, "">;
|
|
6
6
|
type Spinner = ReturnType<typeof Spinner>;
|
package/dist/api/optimade.d.ts
CHANGED
|
@@ -10,13 +10,13 @@ export interface OptimadeStructure {
|
|
|
10
10
|
lattice_vectors?: number[][];
|
|
11
11
|
cartesian_site_positions?: number[][];
|
|
12
12
|
species_at_sites?: string[];
|
|
13
|
-
species?:
|
|
13
|
+
species?: {
|
|
14
14
|
name: string;
|
|
15
15
|
chemical_symbols?: string[];
|
|
16
16
|
concentration?: number[];
|
|
17
17
|
mass?: number[];
|
|
18
18
|
original_name?: string;
|
|
19
|
-
}
|
|
19
|
+
}[];
|
|
20
20
|
n_sites?: number;
|
|
21
21
|
last_modified?: string;
|
|
22
22
|
immutable_id?: string;
|
package/dist/app.css
CHANGED
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
--page-bg: #090019;
|
|
5
5
|
--max-text-width: 50em;
|
|
6
6
|
|
|
7
|
-
--github-corner-color: var(--page-bg);
|
|
8
|
-
--github-corner-bg: var(--text-color);
|
|
9
|
-
|
|
10
7
|
--sms-max-width: 20em;
|
|
11
8
|
--sms-text-color: var(--text-color);
|
|
12
9
|
}
|
|
@@ -45,8 +42,7 @@ a {
|
|
|
45
42
|
text-decoration: none;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
button,
|
|
49
|
-
a.btn {
|
|
45
|
+
button, a.btn {
|
|
50
46
|
color: var(--text-color);
|
|
51
47
|
cursor: pointer;
|
|
52
48
|
border: none;
|
|
@@ -56,8 +52,7 @@ a.btn {
|
|
|
56
52
|
a:hover {
|
|
57
53
|
color: var(--accent-hover-color, orange);
|
|
58
54
|
}
|
|
59
|
-
code,
|
|
60
|
-
kbd {
|
|
55
|
+
code, kbd {
|
|
61
56
|
overflow-wrap: break-word;
|
|
62
57
|
padding: 1pt 3pt;
|
|
63
58
|
border-radius: 3pt;
|
|
@@ -155,7 +150,7 @@ table.roomy :is(td, th) {
|
|
|
155
150
|
padding: 5pt 9pt;
|
|
156
151
|
}
|
|
157
152
|
tbody tr:nth-child(odd) {
|
|
158
|
-
background: var(--
|
|
153
|
+
background: color-mix(in hsl, var(--page-bg, black), var(--text-color) 2%);
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
:where(ul.selected > li button, button.remove-all) {
|
|
@@ -174,3 +169,11 @@ tbody tr:nth-child(odd) {
|
|
|
174
169
|
margin-left: calc(-50vw + 50% + max(var(--margin), (100vw - 1400px) / 2));
|
|
175
170
|
max-width: none !important;
|
|
176
171
|
}
|
|
172
|
+
|
|
173
|
+
.copy-btn {
|
|
174
|
+
position: absolute;
|
|
175
|
+
top: 9pt;
|
|
176
|
+
right: 9pt;
|
|
177
|
+
background: var(--btn-bg);
|
|
178
|
+
color: var(--btn-color);
|
|
179
|
+
}
|
package/dist/colors/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { elem_symbols } from '../labels';
|
|
|
3
3
|
export type D3InterpolateName = keyof typeof d3_sc & `interpolate${string}`;
|
|
4
4
|
export type D3ColorSchemeName = D3InterpolateName extends `interpolate${infer Name}` ? Name : never;
|
|
5
5
|
export declare const default_category_colors: Record<string, string>;
|
|
6
|
+
export declare const axis_colors: readonly [readonly ["x", "#d75555", "#e66666"], readonly ["y", "#55b855", "#66c966"], readonly ["z", "#5555d7", "#6666e6"]];
|
|
7
|
+
export declare const neg_axis_colors: readonly [readonly ["nx", "#b84444", "#cc5555"], readonly ["ny", "#44a044", "#55b155"], readonly ["nz", "#4444b8", "#5555c9"]];
|
|
6
8
|
export type RGBColor = [number, number, number];
|
|
7
9
|
export type ElementColorScheme = Record<(typeof elem_symbols)[number], RGBColor>;
|
|
8
10
|
export declare const vesta_hex: Record<string, string>;
|
|
@@ -27,4 +29,10 @@ export declare const is_color: (val: unknown) => val is string;
|
|
|
27
29
|
export declare const plot_colors: readonly ["#63b3ed", "#68d391", "#fbd38d", "#fc8181", "#d6bcfa", "#4fd1c7", "#f687b3", "#fed7d7", "#bee3f8", "#c6f6d5"];
|
|
28
30
|
export declare function luminance(clr: string): number;
|
|
29
31
|
export declare function get_bg_color(elem: HTMLElement | null, bg_color?: string | null): string;
|
|
30
|
-
export
|
|
32
|
+
export interface ContrastOptions {
|
|
33
|
+
bg_color?: string;
|
|
34
|
+
text_color_threshold?: number;
|
|
35
|
+
choices?: [string, string];
|
|
36
|
+
}
|
|
37
|
+
export declare function pick_contrast_color(options?: ContrastOptions): string;
|
|
38
|
+
export declare const contrast_color: (options?: ContrastOptions) => (node: HTMLElement) => void;
|