matterviz 0.3.2 → 0.3.4
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/EmptyState.svelte +10 -2
- package/dist/FilePicker.svelte +123 -82
- package/dist/Icon.svelte +18 -12
- package/dist/MillerIndexInput.svelte +27 -21
- package/dist/api/optimade.js +6 -6
- package/dist/app.css +216 -207
- package/dist/brillouin/BrillouinZone.svelte +292 -149
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
- package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
- package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
- package/dist/brillouin/compute.js +11 -6
- package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
- package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
- package/dist/chempot-diagram/async-compute.svelte.js +77 -0
- package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
- package/dist/chempot-diagram/chempot-worker.js +11 -0
- package/dist/chempot-diagram/color.js +1 -2
- package/dist/chempot-diagram/compute.d.ts +10 -0
- package/dist/chempot-diagram/compute.js +250 -88
- package/dist/chempot-diagram/index.d.ts +2 -1
- package/dist/chempot-diagram/index.js +2 -1
- package/dist/chempot-diagram/temperature.js +8 -9
- package/dist/chempot-diagram/types.d.ts +3 -0
- package/dist/chempot-diagram/types.js +1 -0
- package/dist/colors/index.d.ts +1 -1
- package/dist/colors/index.js +5 -3
- package/dist/composition/BarChart.svelte +128 -55
- package/dist/composition/BubbleChart.svelte +102 -49
- package/dist/composition/Composition.svelte +100 -79
- package/dist/composition/Formula.svelte +108 -62
- package/dist/composition/FormulaFilter.svelte +665 -537
- package/dist/composition/PieChart.svelte +183 -108
- package/dist/composition/format.d.ts +5 -0
- package/dist/composition/format.js +20 -3
- package/dist/composition/parse.js +14 -9
- package/dist/convex-hull/ConvexHull.svelte +93 -40
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +549 -360
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte +115 -28
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
- package/dist/convex-hull/ConvexHullStats.svelte +425 -328
- package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
- package/dist/convex-hull/GasPressureControls.svelte +104 -61
- package/dist/convex-hull/StructurePopup.svelte +25 -4
- package/dist/convex-hull/TemperatureSlider.svelte +45 -25
- package/dist/convex-hull/barycentric-coords.js +13 -7
- package/dist/convex-hull/demo-temperature.js +8 -4
- package/dist/convex-hull/gas-thermodynamics.js +17 -12
- package/dist/convex-hull/helpers.d.ts +9 -0
- package/dist/convex-hull/helpers.js +77 -34
- package/dist/convex-hull/thermodynamics.js +61 -56
- package/dist/convex-hull/types.d.ts +9 -14
- package/dist/convex-hull/types.js +0 -17
- package/dist/coordination/CoordinationBarPlot.svelte +227 -154
- package/dist/element/BohrAtom.svelte +55 -12
- package/dist/element/ElementHeading.svelte +7 -2
- package/dist/element/ElementPhoto.svelte +15 -9
- package/dist/element/ElementStats.svelte +10 -4
- package/dist/element/ElementTile.svelte +137 -73
- package/dist/element/Nucleus.svelte +39 -11
- package/dist/element/data.js +1 -1
- package/dist/feedback/ClickFeedback.svelte +16 -5
- package/dist/feedback/DragOverlay.svelte +10 -2
- package/dist/feedback/Spinner.svelte +4 -2
- package/dist/feedback/StatusMessage.svelte +8 -2
- package/dist/fermi-surface/FermiSlice.svelte +118 -88
- package/dist/fermi-surface/FermiSurface.svelte +328 -187
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
- package/dist/fermi-surface/compute.js +16 -20
- package/dist/fermi-surface/parse.js +24 -14
- package/dist/fermi-surface/symmetry.js +2 -7
- package/dist/fermi-surface/types.d.ts +3 -5
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
- package/dist/icons.js +47 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/io/decompress.js +1 -1
- package/dist/io/export.d.ts +3 -0
- package/dist/io/export.js +129 -143
- package/dist/io/is-binary.js +2 -3
- package/dist/io/url-drop.js +1 -2
- package/dist/isosurface/Isosurface.svelte +202 -148
- package/dist/isosurface/IsosurfaceControls.svelte +46 -28
- package/dist/isosurface/parse.js +34 -29
- package/dist/isosurface/slice.js +5 -10
- package/dist/isosurface/types.d.ts +2 -1
- package/dist/isosurface/types.js +61 -12
- package/dist/labels.js +11 -8
- package/dist/layout/FullscreenToggle.svelte +11 -2
- package/dist/layout/InfoCard.svelte +38 -6
- package/dist/layout/InfoTag.svelte +63 -32
- package/dist/layout/PropertyFilter.svelte +82 -37
- package/dist/layout/SettingsSection.svelte +85 -55
- package/dist/layout/SubpageGrid.svelte +10 -2
- package/dist/layout/json-tree/JsonNode.svelte +183 -138
- package/dist/layout/json-tree/JsonTree.svelte +499 -413
- package/dist/layout/json-tree/JsonValue.svelte +127 -99
- package/dist/layout/json-tree/utils.js +4 -2
- package/dist/marching-cubes.js +25 -2
- package/dist/math.d.ts +13 -17
- package/dist/math.js +133 -67
- package/dist/overlays/ContextMenu.svelte +65 -40
- package/dist/overlays/DraggablePane.svelte +211 -139
- package/dist/periodic-table/PeriodicTable.svelte +278 -145
- package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
- package/dist/periodic-table/PropertySelect.svelte +25 -7
- package/dist/periodic-table/TableInset.svelte +8 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
- package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
- package/dist/phase-diagram/build-diagram.js +9 -9
- package/dist/phase-diagram/colors.js +1 -3
- package/dist/phase-diagram/parse.js +10 -9
- package/dist/phase-diagram/svg-to-diagram.js +53 -49
- package/dist/phase-diagram/utils.d.ts +1 -0
- package/dist/phase-diagram/utils.js +80 -25
- package/dist/plot/AxisLabel.svelte +28 -3
- package/dist/plot/BarPlot.svelte +1182 -734
- package/dist/plot/BarPlot.svelte.d.ts +2 -2
- package/dist/plot/BarPlotControls.svelte +31 -5
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +479 -329
- package/dist/plot/ColorScaleSelect.svelte +27 -6
- package/dist/plot/ElementScatter.svelte +36 -15
- package/dist/plot/FillArea.svelte +152 -95
- package/dist/plot/Histogram.svelte +934 -571
- package/dist/plot/Histogram.svelte.d.ts +1 -1
- package/dist/plot/HistogramControls.svelte +53 -9
- package/dist/plot/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/InteractiveAxisLabel.svelte +34 -11
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/Line.svelte +63 -28
- package/dist/plot/PlotControls.svelte +157 -114
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +174 -91
- package/dist/plot/PlotTooltip.svelte +45 -6
- package/dist/plot/PortalSelect.svelte +175 -147
- package/dist/plot/ReferenceLine.svelte +76 -22
- package/dist/plot/ReferenceLine3D.svelte +132 -107
- package/dist/plot/ReferencePlane.svelte +146 -121
- package/dist/plot/ScatterPlot.svelte +1681 -1091
- package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3D.svelte +256 -131
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +113 -63
- package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
- package/dist/plot/ScatterPlot3DScene.svelte +608 -403
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +65 -25
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte +98 -26
- package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
- package/dist/plot/SpacegroupBarPlot.svelte +142 -85
- package/dist/plot/Surface3D.svelte +159 -108
- package/dist/plot/ZeroLines.svelte +55 -3
- package/dist/plot/ZoomRect.svelte +4 -2
- package/dist/plot/axis-utils.js +1 -3
- package/dist/plot/data-cleaning.js +12 -28
- package/dist/plot/data-transform.js +2 -1
- package/dist/plot/fill-utils.js +2 -0
- package/dist/plot/layout.d.ts +4 -1
- package/dist/plot/layout.js +33 -14
- package/dist/plot/reference-line.d.ts +2 -2
- package/dist/plot/reference-line.js +7 -5
- package/dist/plot/scales.js +24 -36
- package/dist/plot/types.d.ts +11 -23
- package/dist/plot/types.js +6 -11
- package/dist/plot/utils/label-placement.d.ts +32 -15
- package/dist/plot/utils/label-placement.js +227 -66
- package/dist/plot/utils/series-visibility.js +2 -3
- package/dist/rdf/RdfPlot.svelte +143 -91
- package/dist/rdf/calc-rdf.js +4 -5
- package/dist/sanitize.d.ts +4 -0
- package/dist/sanitize.js +107 -0
- package/dist/settings.d.ts +18 -6
- package/dist/settings.js +46 -16
- package/dist/spectral/Bands.svelte +632 -453
- package/dist/spectral/BandsAndDos.svelte +90 -49
- package/dist/spectral/BrillouinBandsDos.svelte +151 -93
- package/dist/spectral/Dos.svelte +389 -258
- package/dist/spectral/helpers.js +55 -43
- package/dist/state.svelte.d.ts +1 -1
- package/dist/state.svelte.js +3 -2
- package/dist/structure/Arrow.svelte +59 -20
- package/dist/structure/AtomLegend.svelte +215 -134
- package/dist/structure/Bond.svelte +73 -47
- package/dist/structure/CanvasTooltip.svelte +10 -2
- package/dist/structure/CellSelect.svelte +72 -45
- package/dist/structure/Cylinder.svelte +33 -17
- package/dist/structure/Lattice.svelte +88 -33
- package/dist/structure/Structure.svelte +1063 -797
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureControls.svelte +349 -118
- package/dist/structure/StructureExportPane.svelte +124 -89
- package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +304 -237
- package/dist/structure/StructureScene.svelte +879 -443
- package/dist/structure/StructureScene.svelte.d.ts +15 -7
- package/dist/structure/atom-properties.js +8 -8
- package/dist/structure/bonding.js +6 -7
- package/dist/structure/export.js +14 -29
- package/dist/structure/ferrox-wasm.js +1 -1
- package/dist/structure/index.d.ts +13 -3
- package/dist/structure/index.js +83 -23
- package/dist/structure/measure.d.ts +2 -2
- package/dist/structure/measure.js +4 -44
- package/dist/structure/parse.js +113 -141
- package/dist/structure/partial-occupancy.js +7 -10
- package/dist/structure/pbc.d.ts +1 -0
- package/dist/structure/pbc.js +16 -6
- package/dist/structure/supercell.d.ts +2 -2
- package/dist/structure/supercell.js +12 -22
- package/dist/structure/validation.js +1 -2
- package/dist/symmetry/SymmetryStats.svelte +84 -41
- package/dist/symmetry/WyckoffTable.svelte +26 -6
- package/dist/symmetry/cell-transform.js +5 -3
- package/dist/symmetry/index.js +8 -7
- package/dist/symmetry/spacegroups.js +148 -148
- package/dist/table/HeatmapTable.svelte +790 -554
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/ToggleMenu.svelte +125 -92
- package/dist/table/index.js +2 -4
- package/dist/theme/ThemeControl.svelte +21 -12
- package/dist/time.js +4 -1
- package/dist/tooltip/TooltipContent.svelte +33 -8
- package/dist/trajectory/Trajectory.svelte +758 -558
- package/dist/trajectory/TrajectoryError.svelte +14 -3
- package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
- package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
- package/dist/trajectory/extract.js +10 -26
- package/dist/trajectory/format-detect.js +5 -5
- package/dist/trajectory/frame-reader.d.ts +1 -1
- package/dist/trajectory/frame-reader.js +5 -12
- package/dist/trajectory/helpers.d.ts +0 -1
- package/dist/trajectory/helpers.js +2 -17
- package/dist/trajectory/index.js +14 -12
- package/dist/trajectory/parse/ase.js +5 -4
- package/dist/trajectory/parse/hdf5.js +26 -18
- package/dist/trajectory/parse/index.js +13 -18
- package/dist/trajectory/parse/lammps.js +17 -7
- package/dist/trajectory/parse/vasp.js +5 -2
- package/dist/trajectory/parse/xyz.js +8 -7
- package/dist/trajectory/plotting.js +13 -8
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +13 -0
- package/dist/xrd/XrdPlot.svelte +337 -247
- package/dist/xrd/broadening.js +14 -9
- package/dist/xrd/calc-xrd.js +12 -18
- package/dist/xrd/parse.d.ts +1 -1
- package/dist/xrd/parse.js +17 -17
- package/package.json +99 -103
- package/readme.md +1 -1
- /package/dist/theme/{themes.js → themes.mjs} +0 -0
|
@@ -44,7 +44,7 @@ export function handle_legend_double_click(series, idx, prev_visibility) {
|
|
|
44
44
|
const check_series = prev_visibility ? series.slice(0, prev_visibility.length) : series;
|
|
45
45
|
const is_isolated = check_series.every((srs, srs_idx) => {
|
|
46
46
|
const in_group = label ? srs.label === label : srs_idx === idx;
|
|
47
|
-
return in_group ? srs.visible ?? true : !(srs.visible ?? true);
|
|
47
|
+
return in_group ? (srs.visible ?? true) : !(srs.visible ?? true);
|
|
48
48
|
});
|
|
49
49
|
// Restore from isolation
|
|
50
50
|
if (is_isolated && prev_visibility) {
|
|
@@ -56,8 +56,7 @@ export function handle_legend_double_click(series, idx, prev_visibility) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
// Isolate series
|
|
59
|
-
const new_prev = prev_visibility ??
|
|
60
|
-
(current.filter(Boolean).length > 1 ? [...current] : null);
|
|
59
|
+
const new_prev = prev_visibility ?? (current.filter(Boolean).length > 1 ? [...current] : null);
|
|
61
60
|
return {
|
|
62
61
|
series: series.map((srs, srs_idx) => {
|
|
63
62
|
const in_group = label ? srs.label === label : srs_idx === idx;
|
package/dist/rdf/RdfPlot.svelte
CHANGED
|
@@ -1,113 +1,165 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { PLOT_COLORS } from '../colors'
|
|
3
|
+
import { get_electro_neg_formula } from '../composition'
|
|
4
|
+
import { StatusMessage } from '../feedback'
|
|
5
|
+
import { create_file_drop_handler } from '../io'
|
|
6
|
+
import type { DataSeries } from '../plot'
|
|
7
|
+
import { ScatterPlot } from '../plot'
|
|
8
|
+
import type { Crystal, Pbc } from '../structure'
|
|
9
|
+
import { parse_any_structure } from '../structure/parse'
|
|
10
|
+
import { is_crystal } from '../structure/validation'
|
|
11
|
+
import type { ComponentProps, Snippet } from 'svelte'
|
|
12
|
+
import { calculate_all_pair_rdfs, calculate_rdf, type RdfEntry } from './index'
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
patterns,
|
|
16
|
+
structures,
|
|
17
|
+
mode = `element_pairs`,
|
|
18
|
+
show_reference_line = true,
|
|
19
|
+
x_axis = {},
|
|
20
|
+
y_axis = {},
|
|
21
|
+
cutoff = 15,
|
|
22
|
+
n_bins = 75,
|
|
23
|
+
pbc = [true, true, true],
|
|
24
|
+
enable_drop = false,
|
|
25
|
+
on_file_drop,
|
|
26
|
+
loading = $bindable(false),
|
|
27
|
+
error_msg = $bindable(),
|
|
28
|
+
children,
|
|
29
|
+
drag_dropped = $bindable([]),
|
|
30
|
+
dragging = $bindable(false),
|
|
31
|
+
...rest
|
|
32
|
+
}: {
|
|
33
|
+
patterns?: RdfEntry | RdfEntry[]
|
|
34
|
+
structures?: Crystal | Crystal[] | Record<string, Crystal>
|
|
35
|
+
mode?: `element_pairs` | `full`
|
|
36
|
+
show_reference_line?: boolean
|
|
37
|
+
x_axis?: ComponentProps<typeof ScatterPlot>[`x_axis`]
|
|
38
|
+
y_axis?: ComponentProps<typeof ScatterPlot>[`y_axis`]
|
|
39
|
+
cutoff?: number
|
|
40
|
+
n_bins?: number
|
|
41
|
+
pbc?: Pbc
|
|
42
|
+
enable_drop?: boolean
|
|
43
|
+
on_file_drop?: (content: string | ArrayBuffer, filename: string) => void
|
|
44
|
+
loading?: boolean
|
|
45
|
+
error_msg?: string
|
|
46
|
+
children?: Snippet<[{ drag_dropped: Crystal[] }]>
|
|
47
|
+
drag_dropped?: Crystal[]
|
|
48
|
+
dragging?: boolean
|
|
49
|
+
} & ComponentProps<typeof ScatterPlot> = $props()
|
|
50
|
+
|
|
51
|
+
function format_structure_label(struct: Crystal, label_base: string): string {
|
|
52
|
+
const formula = get_electro_neg_formula(struct)
|
|
53
|
+
return formula && label_base ? `${formula}: ${label_base}` : formula || label_base
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const compute_and_add = (content: string | ArrayBuffer, filename: string) => {
|
|
15
57
|
try {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
58
|
+
const text = content instanceof ArrayBuffer
|
|
59
|
+
? new TextDecoder().decode(content)
|
|
60
|
+
: content
|
|
61
|
+
const parsed_struct = parse_any_structure(text, filename)
|
|
62
|
+
if (is_crystal(parsed_struct)) {
|
|
63
|
+
drag_dropped = [...drag_dropped, parsed_struct]
|
|
64
|
+
} else {
|
|
65
|
+
error_msg = `Crystal has no lattice or sites; cannot compute RDF`
|
|
66
|
+
}
|
|
67
|
+
} catch (exc) {
|
|
68
|
+
error_msg = `Failed to process structure: ${
|
|
69
|
+
exc instanceof Error ? exc.message : String(exc)
|
|
70
|
+
}`
|
|
26
71
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
};
|
|
31
|
-
const handle_drop = create_file_drop_handler({
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const handle_drop = create_file_drop_handler({
|
|
32
75
|
allow: () => enable_drop,
|
|
33
|
-
on_drop: (content, filename) =>
|
|
76
|
+
on_drop: (content, filename) =>
|
|
77
|
+
(on_file_drop || compute_and_add)(content, filename),
|
|
34
78
|
on_error: (msg) => {
|
|
35
|
-
|
|
79
|
+
error_msg = msg
|
|
36
80
|
},
|
|
37
81
|
set_loading: (val) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
[error_msg, dragging] = [undefined, false];
|
|
82
|
+
loading = val
|
|
83
|
+
if (val) [error_msg, dragging] = [undefined, false]
|
|
41
84
|
},
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
dragging = true
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
function handle_dragover(ev: DragEvent) {
|
|
88
|
+
ev.preventDefault()
|
|
89
|
+
if (ev.dataTransfer) ev.dataTransfer.dropEffect = `copy`
|
|
90
|
+
dragging = true
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const entries = $derived.by(() => {
|
|
94
|
+
const result: RdfEntry[] = []
|
|
95
|
+
|
|
51
96
|
// Add patterns
|
|
52
97
|
if (patterns) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
else
|
|
56
|
-
result.push(patterns);
|
|
98
|
+
if (Array.isArray(patterns)) result.push(...patterns)
|
|
99
|
+
else result.push(patterns)
|
|
57
100
|
}
|
|
101
|
+
|
|
58
102
|
// Add structures
|
|
59
|
-
const struct_list = []
|
|
103
|
+
const struct_list: { struct: Crystal; label: string }[] = []
|
|
60
104
|
if (structures) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
105
|
+
if (Array.isArray(structures)) {
|
|
106
|
+
structures.forEach((struct, idx) =>
|
|
107
|
+
struct_list.push({
|
|
108
|
+
struct,
|
|
109
|
+
label: format_structure_label(struct, `Crystal ${idx + 1}`),
|
|
110
|
+
})
|
|
111
|
+
)
|
|
112
|
+
} else if (is_crystal(structures)) {
|
|
113
|
+
struct_list.push({
|
|
114
|
+
struct: structures,
|
|
115
|
+
label: format_structure_label(structures, ``),
|
|
116
|
+
})
|
|
117
|
+
} else {
|
|
118
|
+
Object.entries(structures).forEach(([label, struct]) =>
|
|
119
|
+
struct_list.push({ struct, label: format_structure_label(struct, label) })
|
|
120
|
+
)
|
|
121
|
+
}
|
|
76
122
|
}
|
|
77
|
-
drag_dropped.forEach((struct, idx) =>
|
|
123
|
+
drag_dropped.forEach((struct, idx) =>
|
|
124
|
+
struct_list.push({
|
|
78
125
|
struct,
|
|
79
126
|
label: format_structure_label(struct, `Dropped ${idx + 1}`),
|
|
80
|
-
|
|
127
|
+
})
|
|
128
|
+
)
|
|
129
|
+
|
|
81
130
|
for (const { struct, label } of struct_list) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
131
|
+
if (mode === `element_pairs`) {
|
|
132
|
+
const pairs = calculate_all_pair_rdfs(struct, { cutoff, n_bins, pbc })
|
|
133
|
+
result.push(...pairs.map((p) => ({
|
|
134
|
+
label: p.element_pair ? `${p.element_pair[0]}-${p.element_pair[1]}` : label,
|
|
135
|
+
legend_group: label, // Group by structure name for multi-structure plots
|
|
136
|
+
pattern: p,
|
|
137
|
+
})))
|
|
138
|
+
} else {
|
|
139
|
+
const pattern = calculate_rdf(struct, { cutoff, n_bins, pbc })
|
|
140
|
+
result.push({ label, pattern })
|
|
141
|
+
}
|
|
94
142
|
}
|
|
95
|
-
return result
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
143
|
+
return result
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
const max_r = $derived(Math.max(...entries.flatMap((e) => e.pattern.r), 0))
|
|
147
|
+
const max_g = $derived(Math.max(1.2, ...entries.flatMap((e) => e.pattern.g_r)))
|
|
148
|
+
|
|
149
|
+
const series = $derived<DataSeries[]>(
|
|
150
|
+
entries.map((ent, idx) => ({
|
|
151
|
+
x: ent.pattern.r,
|
|
152
|
+
y: ent.pattern.g_r,
|
|
153
|
+
label: ent.label,
|
|
154
|
+
legend_group: ent.legend_group,
|
|
155
|
+
visible: mode === `element_pairs` ? idx < 3 : true,
|
|
156
|
+
markers: `line` as const,
|
|
157
|
+
line_style: {
|
|
107
158
|
stroke: ent.color ?? PLOT_COLORS[idx % PLOT_COLORS.length],
|
|
108
159
|
stroke_width: 2,
|
|
109
|
-
|
|
110
|
-
}))
|
|
160
|
+
},
|
|
161
|
+
})),
|
|
162
|
+
)
|
|
111
163
|
</script>
|
|
112
164
|
|
|
113
165
|
<StatusMessage bind:message={error_msg} type="error" dismissible />
|
package/dist/rdf/calc-rdf.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { calc_lattice_params,
|
|
1
|
+
import { calc_lattice_params, create_lattice_converters, euclidean_dist, pbc_dist, } from '../math';
|
|
2
2
|
import { make_supercell } from '../structure/supercell';
|
|
3
3
|
// Calculate radial distribution function
|
|
4
4
|
export function calculate_rdf(structure, options = {}) {
|
|
@@ -45,18 +45,17 @@ export function calculate_rdf(structure, options = {}) {
|
|
|
45
45
|
}
|
|
46
46
|
// Calculate distances and bin them with occupancy weighting
|
|
47
47
|
const use_pbc = pbc.some((flag) => flag);
|
|
48
|
-
const
|
|
48
|
+
const converters = use_pbc ? create_lattice_converters(lattice) : undefined;
|
|
49
49
|
for (const center of centers) {
|
|
50
50
|
for (const neighbor of neighbors) {
|
|
51
51
|
if (center === neighbor)
|
|
52
52
|
continue;
|
|
53
53
|
const dist = use_pbc
|
|
54
|
-
? pbc_dist(center.xyz, neighbor.xyz, lattice,
|
|
54
|
+
? pbc_dist(center.xyz, neighbor.xyz, lattice, converters, pbc)
|
|
55
55
|
: euclidean_dist(center.xyz, neighbor.xyz);
|
|
56
56
|
if (dist > 0 && dist < cutoff) {
|
|
57
57
|
// Weight by product of occupancies for the species pair
|
|
58
|
-
const weight = get_occu(center, center_species) *
|
|
59
|
-
get_occu(neighbor, neighbor_species);
|
|
58
|
+
const weight = get_occu(center, center_species) * get_occu(neighbor, neighbor_species);
|
|
60
59
|
g_r[Math.min(Math.floor(dist / bin_size), n_bins - 1)] += weight;
|
|
61
60
|
}
|
|
62
61
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function sanitize_html(html: unknown): string;
|
|
2
|
+
export declare const sanitize_formula: (formula: string, use_subscripts?: boolean) => string;
|
|
3
|
+
export declare const sanitize_svg: (html: string) => string;
|
|
4
|
+
export declare const sanitize_icon_svg: (html: string) => string;
|
package/dist/sanitize.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import DOMPurify from 'dompurify';
|
|
2
|
+
import { format_formula_html } from './phase-diagram/utils';
|
|
3
|
+
// SSR: provide a DOM for DOMPurify when no browser window exists (e.g. during vite build)
|
|
4
|
+
let ssr_window;
|
|
5
|
+
if (typeof globalThis.window === `undefined`) {
|
|
6
|
+
try {
|
|
7
|
+
const { Window } = await import(`happy-dom`);
|
|
8
|
+
ssr_window = new Window();
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
// happy-dom not available at runtime — get_purify() will fall back to pass-through
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const SAFE_TAGS = [`a`, `b`, `i`, `em`, `strong`, `sub`, `sup`, `br`, `span`, `code`, `small`];
|
|
15
|
+
const SAFE_ATTRS = [`style`, `class`, `title`, `href`, `target`, `rel`];
|
|
16
|
+
// only allow safe CSS properties for text formatting
|
|
17
|
+
const SAFE_STYLE_RE = /^\s*(color|font-weight|font-style|font-size|text-decoration|vertical-align)\s*:/;
|
|
18
|
+
// Add a token to a space-separated string if not already present
|
|
19
|
+
const ensure_token = (value, token) => {
|
|
20
|
+
const tokens = new Set(value.split(/\s+/).filter(Boolean));
|
|
21
|
+
tokens.add(token);
|
|
22
|
+
return [...tokens].join(` `);
|
|
23
|
+
};
|
|
24
|
+
// undefined = not yet checked, null = no DOM available, instance = ready
|
|
25
|
+
let purify;
|
|
26
|
+
function get_purify() {
|
|
27
|
+
if (purify !== undefined)
|
|
28
|
+
return purify;
|
|
29
|
+
const instance = ssr_window
|
|
30
|
+
? DOMPurify(ssr_window)
|
|
31
|
+
: DOMPurify();
|
|
32
|
+
if (typeof instance.sanitize !== `function`) {
|
|
33
|
+
purify = null;
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
purify = instance;
|
|
37
|
+
instance.addHook(`uponSanitizeAttribute`, (node, data) => {
|
|
38
|
+
if (data.attrName === `style`) {
|
|
39
|
+
const rules = data.attrValue.split(`;`).filter((rule) => SAFE_STYLE_RE.test(rule));
|
|
40
|
+
if (rules.length === 0)
|
|
41
|
+
data.keepAttr = false;
|
|
42
|
+
else
|
|
43
|
+
data.attrValue = rules.join(`;`);
|
|
44
|
+
}
|
|
45
|
+
// force rel="noopener" on links to prevent window.opener attacks
|
|
46
|
+
if (data.attrName === `href`) {
|
|
47
|
+
node.setAttribute(`rel`, ensure_token(node.getAttribute(`rel`) ?? ``, `noopener`));
|
|
48
|
+
}
|
|
49
|
+
if (data.attrName === `rel`) {
|
|
50
|
+
data.attrValue = ensure_token(data.attrValue, `noopener`);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return instance;
|
|
54
|
+
}
|
|
55
|
+
// Wrap in <svg>, sanitize with allowlist, then unwrap. Required because DOMPurify
|
|
56
|
+
// needs the <svg> parent to parse children in the SVG namespace.
|
|
57
|
+
function sanitize_svg_content(html, allowed_tags, allowed_attrs) {
|
|
58
|
+
const dp = get_purify();
|
|
59
|
+
if (!dp)
|
|
60
|
+
return html;
|
|
61
|
+
const wrapped = dp.sanitize(`<svg>${html}</svg>`, {
|
|
62
|
+
ALLOWED_TAGS: [...allowed_tags, `svg`],
|
|
63
|
+
ALLOWED_ATTR: allowed_attrs,
|
|
64
|
+
});
|
|
65
|
+
const open_end = wrapped.indexOf(`>`);
|
|
66
|
+
const close_start = wrapped.lastIndexOf(`</svg>`);
|
|
67
|
+
if (open_end < 0 || close_start < 0)
|
|
68
|
+
return wrapped;
|
|
69
|
+
return wrapped.slice(open_end + 1, close_start);
|
|
70
|
+
}
|
|
71
|
+
// Sanitize HTML string, allowing only safe formatting tags and links.
|
|
72
|
+
// Two-pass: happy-dom promotes dangerous children when a non-allowed parent is
|
|
73
|
+
// stripped (e.g. <div><script>…</script></div> → <script>…</script>). The first
|
|
74
|
+
// pass explicitly removes dangerous tags so they can't survive promotion.
|
|
75
|
+
export function sanitize_html(html) {
|
|
76
|
+
const str = html == null ? `` : String(html);
|
|
77
|
+
const dp = get_purify();
|
|
78
|
+
if (!dp)
|
|
79
|
+
return str;
|
|
80
|
+
// oxfmt-ignore
|
|
81
|
+
const safe = dp.sanitize(str, { ADD_ATTR: [`target`], FORBID_TAGS: [
|
|
82
|
+
`script`, `style`, `iframe`, `object`, `embed`, `form`, `input`, `textarea`,
|
|
83
|
+
`select`, `button`, `meta`, `link`, `base`, `template`, `noscript`,
|
|
84
|
+
] });
|
|
85
|
+
return dp.sanitize(safe, { ALLOWED_TAGS: SAFE_TAGS, ALLOWED_ATTR: SAFE_ATTRS });
|
|
86
|
+
}
|
|
87
|
+
// Sanitize a chemical formula with optional subscript formatting
|
|
88
|
+
export const sanitize_formula = (formula, use_subscripts = true) => sanitize_html(format_formula_html(formula, use_subscripts));
|
|
89
|
+
const SVG_TEXT_TAGS = [`tspan`, `title`];
|
|
90
|
+
// oxfmt-ignore
|
|
91
|
+
const SVG_TEXT_ATTRS = [`dx`, `dy`, `x`, `y`, `fill`, `font-size`, `font-weight`, `baseline-shift`];
|
|
92
|
+
// Sanitize HTML intended for SVG text contexts (tspan, title)
|
|
93
|
+
export const sanitize_svg = (html) => sanitize_svg_content(html, SVG_TEXT_TAGS, SVG_TEXT_ATTRS);
|
|
94
|
+
// oxfmt-ignore
|
|
95
|
+
const SVG_ICON_TAGS = [
|
|
96
|
+
`path`, `circle`, `rect`, `line`, `polyline`, `polygon`, `g`, `ellipse`,
|
|
97
|
+
`clipPath`, `defs`, `mask`, `use`, `title`,
|
|
98
|
+
];
|
|
99
|
+
// oxfmt-ignore
|
|
100
|
+
const SVG_ICON_ATTRS = [
|
|
101
|
+
`d`, `fill`, `stroke`, `stroke-width`, `stroke-linecap`, `stroke-linejoin`,
|
|
102
|
+
`cx`, `cy`, `r`, `rx`, `ry`, `x`, `y`, `x1`, `y1`, `x2`, `y2`,
|
|
103
|
+
`width`, `height`, `viewBox`, `points`, `transform`, `opacity`,
|
|
104
|
+
`clip-path`, `clip-rule`, `fill-rule`, `id`, `class`,
|
|
105
|
+
];
|
|
106
|
+
// Sanitize inline SVG markup (path, circle, rect, etc.) for icon rendering
|
|
107
|
+
export const sanitize_icon_svg = (html) => sanitize_svg_content(html, SVG_ICON_TAGS, SVG_ICON_ATTRS);
|
package/dist/settings.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ export interface SettingType<T = unknown> {
|
|
|
17
17
|
export declare const SHOW_BONDS_OPTIONS: readonly ["never", "always", "crystals", "molecules"];
|
|
18
18
|
export type ShowBonds = (typeof SHOW_BONDS_OPTIONS)[number];
|
|
19
19
|
export type CameraProjection = `perspective` | `orthographic`;
|
|
20
|
+
export declare const VECTOR_COLOR_MODES: readonly ["auto", "element", "spin_direction", "magnitude", "uniform"];
|
|
21
|
+
export type VectorColorMode = (typeof VECTOR_COLOR_MODES)[number];
|
|
22
|
+
export type VectorLayerConfig = {
|
|
23
|
+
visible: boolean;
|
|
24
|
+
color: string | null;
|
|
25
|
+
scale: number | null;
|
|
26
|
+
};
|
|
20
27
|
export declare const ATOM_COLOR_MODE_OPTIONS: readonly ["element", "coordination", "wyckoff", "custom"];
|
|
21
28
|
export type AtomColorMode = (typeof ATOM_COLOR_MODE_OPTIONS)[number];
|
|
22
29
|
type DisplayConfigType = {
|
|
@@ -122,12 +129,17 @@ export interface SettingsConfig {
|
|
|
122
129
|
site_label_offset: SettingType<Vec3>;
|
|
123
130
|
ambient_light: SettingType<number>;
|
|
124
131
|
directional_light: SettingType<number>;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
vector_configs: SettingType<Record<string, VectorLayerConfig>>;
|
|
133
|
+
vector_scale: SettingType<number>;
|
|
134
|
+
vector_color: SettingType<string>;
|
|
135
|
+
vector_color_mode: SettingType<VectorColorMode>;
|
|
136
|
+
vector_color_scale: SettingType<D3InterpolateName>;
|
|
137
|
+
vector_normalize: SettingType<boolean>;
|
|
138
|
+
vector_uniform_thickness: SettingType<boolean>;
|
|
139
|
+
vector_origin_gap: SettingType<number>;
|
|
140
|
+
vector_shaft_radius: SettingType<number>;
|
|
141
|
+
vector_arrow_head_radius: SettingType<number>;
|
|
142
|
+
vector_arrow_head_length: SettingType<number>;
|
|
131
143
|
show_cell: SettingType<boolean>;
|
|
132
144
|
show_cell_vectors: SettingType<boolean>;
|
|
133
145
|
cell_edge_opacity: SettingType<number>;
|
package/dist/settings.js
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
import { symbol_names } from './labels';
|
|
4
4
|
import { merge_nested } from './utils';
|
|
5
5
|
export const SHOW_BONDS_OPTIONS = [`never`, `always`, `crystals`, `molecules`];
|
|
6
|
+
export const VECTOR_COLOR_MODES = [
|
|
7
|
+
`auto`,
|
|
8
|
+
`element`,
|
|
9
|
+
`spin_direction`,
|
|
10
|
+
`magnitude`,
|
|
11
|
+
`uniform`,
|
|
12
|
+
];
|
|
6
13
|
export const ATOM_COLOR_MODE_OPTIONS = [
|
|
7
14
|
`element`,
|
|
8
15
|
`coordination`,
|
|
@@ -74,8 +81,8 @@ export const SETTINGS_CONFIG = {
|
|
|
74
81
|
structure: {
|
|
75
82
|
// Atoms & Bonds
|
|
76
83
|
atom_radius: {
|
|
77
|
-
value:
|
|
78
|
-
description: `Radius multiplier for atoms (
|
|
84
|
+
value: 0.7,
|
|
85
|
+
description: `Radius multiplier for atoms (0.7 = standard atomic radii)`,
|
|
79
86
|
minimum: 0.1,
|
|
80
87
|
maximum: 3.0,
|
|
81
88
|
},
|
|
@@ -267,36 +274,58 @@ export const SETTINGS_CONFIG = {
|
|
|
267
274
|
minimum: 0,
|
|
268
275
|
maximum: 4,
|
|
269
276
|
},
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
value:
|
|
273
|
-
description: `
|
|
277
|
+
// Site Vectors (force, magmom, spin) & Lattice
|
|
278
|
+
vector_configs: {
|
|
279
|
+
value: {},
|
|
280
|
+
description: `Per-key configuration for site vector layers. Keys map to site property names (e.g. force, magmom, force_DFT). Auto-populated when a structure with vector data loads.`,
|
|
274
281
|
},
|
|
275
|
-
|
|
282
|
+
vector_scale: {
|
|
276
283
|
value: 1.0,
|
|
277
|
-
description: `Scale factor for
|
|
284
|
+
description: `Scale factor for site vector arrows`,
|
|
278
285
|
minimum: 0.1,
|
|
279
286
|
maximum: 10.0,
|
|
280
287
|
},
|
|
281
|
-
|
|
288
|
+
vector_color: {
|
|
282
289
|
value: `#ff0000`,
|
|
283
|
-
description: `Color for
|
|
290
|
+
description: `Color for site vector arrows (used in uniform mode and as fallback)`,
|
|
291
|
+
},
|
|
292
|
+
vector_color_mode: {
|
|
293
|
+
value: `auto`,
|
|
294
|
+
description: `How to color arrows. auto = element for force, spin-direction for magmom/spin. element = majority species color. spin_direction = red/blue by z-component. magnitude = continuous color scale by vector length. uniform = single color (vector_color).`,
|
|
295
|
+
},
|
|
296
|
+
vector_color_scale: {
|
|
297
|
+
value: `interpolateViridis`,
|
|
298
|
+
description: `D3 color scale for magnitude coloring mode`,
|
|
299
|
+
},
|
|
300
|
+
vector_normalize: {
|
|
301
|
+
value: false,
|
|
302
|
+
description: `Show all arrows at the same length (direction only). Useful for spin/magmom visualization where orientation matters but magnitude does not.`,
|
|
303
|
+
},
|
|
304
|
+
vector_uniform_thickness: {
|
|
305
|
+
value: false,
|
|
306
|
+
description: `Use the same shaft and head size for all arrows regardless of length. When off (default), thickness scales with arrow length.`,
|
|
307
|
+
},
|
|
308
|
+
vector_origin_gap: {
|
|
309
|
+
value: 0,
|
|
310
|
+
description: `Fraction of visual atom radius to offset each arrow origin when multiple vectors are shown per site. 0 = all from atom center, 0.5 = halfway to surface.`,
|
|
311
|
+
minimum: 0,
|
|
312
|
+
maximum: 0.5,
|
|
284
313
|
},
|
|
285
|
-
|
|
314
|
+
vector_shaft_radius: {
|
|
286
315
|
value: -0.03,
|
|
287
|
-
description: `Radius of
|
|
316
|
+
description: `Radius of vector shaft (negative = relative to length, positive = absolute)`,
|
|
288
317
|
minimum: -0.1,
|
|
289
318
|
maximum: 0.1,
|
|
290
319
|
},
|
|
291
|
-
|
|
320
|
+
vector_arrow_head_radius: {
|
|
292
321
|
value: -0.06,
|
|
293
|
-
description: `Radius of
|
|
322
|
+
description: `Radius of vector arrow head (negative = relative to length, positive = absolute)`,
|
|
294
323
|
minimum: -0.2,
|
|
295
324
|
maximum: 0.2,
|
|
296
325
|
},
|
|
297
|
-
|
|
326
|
+
vector_arrow_head_length: {
|
|
298
327
|
value: -0.15,
|
|
299
|
-
description: `Length of
|
|
328
|
+
description: `Length of vector arrow head (negative = relative to length, positive = absolute)`,
|
|
300
329
|
minimum: -0.5,
|
|
301
330
|
maximum: 0.5,
|
|
302
331
|
},
|
|
@@ -785,6 +814,7 @@ export const SETTINGS_CONFIG = {
|
|
|
785
814
|
},
|
|
786
815
|
},
|
|
787
816
|
convex_hull: {
|
|
817
|
+
// Convex hull defaults (binary/ternary/quaternary)
|
|
788
818
|
binary: {
|
|
789
819
|
camera_zoom: {
|
|
790
820
|
value: 1.0,
|