matterviz 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +12 -14
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/app.css +53 -0
- package/dist/brillouin/BrillouinZone.svelte +132 -219
- package/dist/brillouin/BrillouinZone.svelte.d.ts +9 -20
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +47 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +15 -42
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +63 -230
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
- package/dist/brillouin/ReciprocalVectors.svelte +39 -0
- package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
- package/dist/brillouin/compute.d.ts +2 -0
- package/dist/brillouin/compute.js +80 -77
- package/dist/brillouin/geometry.d.ts +8 -0
- package/dist/brillouin/geometry.js +57 -0
- package/dist/brillouin/index.d.ts +2 -0
- package/dist/brillouin/index.js +2 -0
- package/dist/brillouin/types.d.ts +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +33 -38
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +143 -246
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +652 -976
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/async-compute.svelte.js +1 -1
- package/dist/chempot-diagram/color.d.ts +3 -6
- package/dist/chempot-diagram/color.js +5 -5
- package/dist/chempot-diagram/compute.d.ts +3 -3
- package/dist/chempot-diagram/compute.js +3 -1
- package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
- package/dist/chempot-diagram/controls-state.svelte.js +42 -0
- package/dist/chempot-diagram/export.d.ts +47 -0
- package/dist/chempot-diagram/export.js +133 -0
- package/dist/chempot-diagram/index.d.ts +1 -0
- package/dist/chempot-diagram/index.js +1 -0
- package/dist/chempot-diagram/pointer.d.ts +0 -10
- package/dist/chempot-diagram/pointer.js +4 -4
- package/dist/chempot-diagram/types.d.ts +3 -3
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +21 -22
- package/dist/composition/BarChart.svelte +37 -31
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +7 -11
- package/dist/composition/Formula.svelte +18 -25
- package/dist/composition/FormulaFilter.svelte +96 -98
- package/dist/composition/PieChart.svelte +60 -46
- package/dist/composition/chem-sys.js +3 -2
- package/dist/composition/format.js +4 -3
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -3
- package/dist/composition/parse.js +27 -28
- package/dist/constants.js +11 -9
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +20 -25
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +176 -256
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +269 -804
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +236 -755
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +264 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +128 -49
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
- package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
- package/dist/convex-hull/ConvexHullStats.svelte +210 -351
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +16 -14
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- package/dist/convex-hull/GasPressureControls.svelte +5 -12
- package/dist/convex-hull/StructurePopup.svelte +17 -21
- package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
- package/dist/convex-hull/TemperatureSlider.svelte +4 -10
- package/dist/convex-hull/barycentric-coords.d.ts +2 -4
- package/dist/convex-hull/barycentric-coords.js +6 -33
- package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
- package/dist/convex-hull/canvas-interactions.svelte.js +279 -0
- package/dist/convex-hull/helpers.d.ts +47 -17
- package/dist/convex-hull/helpers.js +186 -101
- package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
- package/dist/convex-hull/hull-state.svelte.js +124 -0
- package/dist/convex-hull/index.d.ts +9 -7
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +109 -937
- package/dist/convex-hull/types.d.ts +12 -4
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +41 -43
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +1 -1
- package/dist/coordination/calc-coordination.js +28 -25
- package/dist/element/BohrAtom.svelte +6 -8
- package/dist/element/ElementHeading.svelte +4 -1
- package/dist/element/ElementPhoto.svelte +11 -9
- package/dist/element/ElementStats.svelte +12 -10
- package/dist/element/ElementTile.svelte +24 -29
- package/dist/element/ElementTile.svelte.d.ts +1 -1
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +1 -2
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +1 -0
- package/dist/element/index.js +3 -0
- package/dist/feedback/DragOverlay.svelte +5 -3
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -1
- package/dist/feedback/StatusMessage.svelte +20 -7
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +78 -165
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +9 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceScene.svelte +93 -272
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +14 -13
- package/dist/fermi-surface/export.js +4 -15
- package/dist/fermi-surface/index.d.ts +0 -1
- package/dist/fermi-surface/index.js +0 -1
- package/dist/fermi-surface/parse.d.ts +1 -1
- package/dist/fermi-surface/parse.js +84 -97
- package/dist/fermi-surface/types.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +161 -185
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +6 -5
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +12 -9
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +8 -2
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +170 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +22 -36
- package/dist/io/export.d.ts +9 -1
- package/dist/io/export.js +37 -29
- package/dist/io/fetch.d.ts +2 -4
- package/dist/io/fetch.js +0 -11
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +13 -0
- package/dist/io/index.d.ts +1 -0
- package/dist/io/index.js +3 -0
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/types.d.ts +13 -0
- package/dist/io/url-drop.js +13 -25
- package/dist/isosurface/Isosurface.svelte +17 -23
- package/dist/isosurface/IsosurfaceControls.svelte +37 -42
- package/dist/isosurface/parse-vaspwave.d.ts +3 -0
- package/dist/isosurface/parse-vaspwave.js +138 -0
- package/dist/isosurface/parse.js +50 -48
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +44 -14
- package/dist/layout/FullscreenButton.svelte +34 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +12 -12
- package/dist/layout/InfoCard.svelte +7 -18
- package/dist/layout/InfoTag.svelte +1 -3
- package/dist/layout/NumberRangeInput.svelte +46 -0
- package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
- package/dist/layout/PropertyFilter.svelte +2 -6
- package/dist/layout/SettingsSection.svelte +21 -17
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +115 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +18 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +36 -0
- package/dist/layout/index.d.ts +4 -0
- package/dist/layout/index.js +4 -0
- package/dist/layout/json-tree/JsonNode.svelte +8 -11
- package/dist/layout/json-tree/JsonTree.svelte +53 -77
- package/dist/layout/json-tree/JsonValue.svelte +7 -15
- package/dist/layout/json-tree/utils.js +14 -23
- package/dist/math.d.ts +9 -3
- package/dist/math.js +37 -21
- package/dist/overlays/ContextMenu.svelte +4 -2
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +81 -26
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -0
- package/dist/overlays/GlassChip.svelte +30 -0
- package/dist/overlays/GlassChip.svelte.d.ts +8 -0
- package/dist/overlays/InfoPaneCards.svelte +11 -23
- package/dist/overlays/index.d.ts +11 -0
- package/dist/overlays/index.js +26 -0
- package/dist/overlays/portal.d.ts +2 -0
- package/dist/overlays/portal.js +14 -0
- package/dist/periodic-table/PeriodicTable.svelte +115 -146
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
- package/dist/periodic-table/PeriodicTableControls.svelte +11 -63
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +50 -71
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
- package/dist/phase-diagram/PhaseDiagramControls.svelte +73 -96
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +4 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +49 -134
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
- package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
- package/dist/phase-diagram/build-diagram.js +3 -3
- package/dist/phase-diagram/colors.js +1 -1
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.d.ts +2 -1
- package/dist/phase-diagram/parse.js +15 -15
- package/dist/phase-diagram/svg-to-diagram.js +21 -15
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +494 -692
- package/dist/plot/bar/BarPlot.svelte.d.ts +9 -15
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +5 -7
- package/dist/plot/bar/SpacegroupBarPlot.svelte +31 -37
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +361 -439
- package/dist/plot/box/BoxPlot.svelte.d.ts +6 -3
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
- package/dist/plot/box/Violin.svelte.d.ts +2 -1
- package/dist/plot/box/box-plot.d.ts +3 -2
- package/dist/plot/box/box-plot.js +6 -3
- package/dist/plot/box/kde.d.ts +2 -1
- package/dist/plot/box/kde.js +4 -4
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +5 -2
- package/dist/plot/core/axis-utils.d.ts +12 -7
- package/dist/plot/core/axis-utils.js +48 -48
- package/dist/plot/core/components/AxisLabel.svelte +82 -20
- package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
- package/dist/plot/core/components/ColorBar.svelte +106 -111
- package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
- package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
- package/dist/plot/core/components/FillArea.svelte +10 -17
- package/dist/plot/core/components/HierarchyControls.svelte +249 -0
- package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
- package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
- package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/core/components/Line.svelte +21 -11
- package/dist/plot/core/components/Line.svelte.d.ts +5 -2
- package/dist/plot/core/components/PlotAxis.svelte +42 -18
- package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/core/components/PlotLegend.svelte +31 -35
- package/dist/plot/core/components/PlotMarginals.svelte +616 -0
- package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
- package/dist/plot/core/components/PlotTooltip.svelte +1 -1
- package/dist/plot/core/components/PortalSelect.svelte +4 -8
- package/dist/plot/core/components/ReferenceLine.svelte +27 -24
- package/dist/plot/core/components/ReferenceLine3D.svelte +56 -59
- package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
- package/dist/plot/core/components/ReferencePlane.svelte +9 -10
- package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
- package/dist/plot/core/components/ZeroLines.svelte +4 -8
- package/dist/plot/core/components/ZoomRect.svelte +1 -2
- package/dist/plot/core/components/index.d.ts +1 -0
- package/dist/plot/core/components/index.js +1 -0
- package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
- package/dist/plot/core/data-cleaning-signal.js +467 -0
- package/dist/plot/core/data-cleaning.d.ts +2 -42
- package/dist/plot/core/data-cleaning.js +29 -476
- package/dist/plot/core/data-transform.js +9 -5
- package/dist/plot/core/fill-utils.d.ts +7 -4
- package/dist/plot/core/fill-utils.js +34 -9
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.d.ts +5 -1
- package/dist/plot/core/interactions.js +14 -2
- package/dist/plot/core/layout.d.ts +3 -1
- package/dist/plot/core/layout.js +22 -13
- package/dist/plot/core/marginals.d.ts +170 -0
- package/dist/plot/core/marginals.js +436 -0
- package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
- package/dist/plot/core/pan-zoom.svelte.js +221 -0
- package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -0
- package/dist/plot/core/reference-line.d.ts +10 -10
- package/dist/plot/core/reference-line.js +7 -7
- package/dist/plot/core/scales.d.ts +40 -25
- package/dist/plot/core/scales.js +49 -21
- package/dist/plot/core/svg.d.ts +2 -1
- package/dist/plot/core/types/fills.d.ts +101 -0
- package/dist/plot/core/types/fills.js +15 -0
- package/dist/plot/core/types/plot-3d.d.ts +87 -0
- package/dist/plot/core/types/plot-3d.js +4 -0
- package/dist/plot/core/types/reference-lines.d.ts +140 -0
- package/dist/plot/core/types/reference-lines.js +9 -0
- package/dist/plot/core/types.d.ts +47 -331
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +51 -0
- package/dist/plot/core/utils/hierarchy-chart.js +179 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +99 -0
- package/dist/plot/core/utils/label-placement.d.ts +1 -1
- package/dist/plot/core/utils/label-placement.js +5 -5
- package/dist/plot/core/utils.d.ts +2 -1
- package/dist/plot/histogram/Histogram.svelte +373 -631
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/histogram/histogram.d.ts +31 -0
- package/dist/plot/histogram/histogram.js +70 -0
- package/dist/plot/histogram/index.d.ts +1 -0
- package/dist/plot/histogram/index.js +1 -0
- package/dist/plot/index.d.ts +1 -0
- package/dist/plot/index.js +1 -0
- package/dist/plot/sankey/Sankey.svelte +79 -73
- package/dist/plot/sankey/Sankey.svelte.d.ts +3 -3
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/sankey/sankey.js +3 -1
- package/dist/plot/scatter/BinnedScatterPlot.svelte +264 -112
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +11 -4
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +623 -821
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +9 -15
- package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/ScatterPoint.svelte +16 -9
- package/dist/plot/scatter/binned-scatter-types.d.ts +6 -12
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/index.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.js +8 -7
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +40 -60
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +17 -15
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +232 -234
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
- package/dist/plot/scatter-3d/Surface3D.svelte +9 -17
- package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
- package/dist/plot/sunburst/Sunburst.svelte +256 -338
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
- package/dist/plot/sunburst/index.d.ts +1 -1
- package/dist/plot/sunburst/index.js +2 -1
- package/dist/plot/sunburst/render.d.ts +2 -2
- package/dist/plot/sunburst/render.js +47 -22
- package/dist/plot/sunburst/sunburst.d.ts +5 -1
- package/dist/plot/sunburst/sunburst.js +14 -4
- package/dist/plot/treemap/Treemap.svelte +907 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +84 -0
- package/dist/plot/treemap/index.d.ts +3 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/treemap.d.ts +26 -0
- package/dist/plot/treemap/treemap.js +99 -0
- package/dist/rdf/RdfPlot.svelte +22 -26
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +4 -8
- package/dist/sanitize.js +14 -3
- package/dist/scene/SceneCamera.svelte +62 -0
- package/dist/scene/SceneCamera.svelte.d.ts +19 -0
- package/dist/scene/bind-renderer.svelte.d.ts +2 -0
- package/dist/scene/bind-renderer.svelte.js +22 -0
- package/dist/scene/index.d.ts +4 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/props.js +52 -0
- package/dist/scene/types.d.ts +26 -0
- package/dist/scene/types.js +1 -0
- package/dist/settings.d.ts +33 -11
- package/dist/settings.js +136 -51
- package/dist/spectral/Bands.svelte +231 -237
- package/dist/spectral/Bands.svelte.d.ts +3 -2
- package/dist/spectral/BandsAndDos.svelte +29 -29
- package/dist/spectral/BrillouinBandsDos.svelte +21 -29
- package/dist/spectral/Dos.svelte +75 -77
- package/dist/spectral/Dos.svelte.d.ts +2 -1
- package/dist/spectral/helpers.d.ts +9 -9
- package/dist/spectral/helpers.js +66 -70
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +5 -24
- package/dist/structure/Arrow.svelte +6 -21
- package/dist/structure/ArrowInstances.svelte +160 -0
- package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
- package/dist/structure/AtomLegend.svelte +115 -75
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +16 -3
- package/dist/structure/CellSelect.svelte +22 -29
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- package/dist/structure/Cylinder.svelte +24 -40
- package/dist/structure/InstancedAtoms.svelte +114 -0
- package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
- package/dist/structure/Lattice.svelte +85 -149
- package/dist/structure/SiteLabels.svelte +122 -0
- package/dist/structure/SiteLabels.svelte.d.ts +18 -0
- package/dist/structure/Structure.svelte +725 -735
- package/dist/structure/Structure.svelte.d.ts +8 -16
- package/dist/structure/StructureCarousel.svelte +630 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +298 -325
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +62 -168
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +77 -69
- package/dist/structure/StructureInfoPane.svelte.d.ts +6 -6
- package/dist/structure/StructureScene.svelte +758 -600
- package/dist/structure/StructureScene.svelte.d.ts +24 -20
- package/dist/structure/StructureViewport.svelte +386 -0
- package/dist/structure/StructureViewport.svelte.d.ts +63 -0
- package/dist/structure/atom-label-placement.d.ts +18 -0
- package/dist/structure/atom-label-placement.js +115 -0
- package/dist/structure/atom-properties.d.ts +3 -1
- package/dist/structure/atom-properties.js +115 -54
- package/dist/structure/bond-order-perception.js +2 -4
- package/dist/structure/bonding.d.ts +12 -2
- package/dist/structure/bonding.js +172 -73
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +25 -4
- package/dist/structure/export.js +103 -153
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +22 -0
- package/dist/structure/geometry.d.ts +9 -0
- package/dist/structure/geometry.js +27 -0
- package/dist/structure/index.d.ts +18 -1
- package/dist/structure/index.js +15 -2
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +5 -3
- package/dist/structure/parse.js +551 -567
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +5 -3
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +204 -51
- package/dist/structure/polyhedra.d.ts +40 -0
- package/dist/structure/polyhedra.js +587 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +10 -15
- package/dist/structure/validation.js +5 -6
- package/dist/symmetry/SymmetryElementControls.svelte +69 -0
- package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
- package/dist/symmetry/SymmetryElements.svelte +350 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +142 -49
- package/dist/symmetry/WyckoffTable.svelte +58 -16
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +8 -14
- package/dist/symmetry/index.d.ts +15 -4
- package/dist/symmetry/index.js +308 -81
- package/dist/symmetry/spacegroups.d.ts +5 -1
- package/dist/symmetry/spacegroups.js +18 -3
- package/dist/symmetry/symmetry-elements.d.ts +33 -0
- package/dist/symmetry/symmetry-elements.js +521 -0
- package/dist/symmetry/wyckoff-db.d.ts +9 -0
- package/dist/symmetry/wyckoff-db.js +87 -0
- package/dist/table/HeatmapTable.svelte +1104 -378
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +5 -12
- package/dist/table/index.d.ts +21 -6
- package/dist/table/index.js +34 -21
- package/dist/theme/ThemeControl.svelte +16 -8
- package/dist/theme/index.d.ts +1 -5
- package/dist/theme/index.js +4 -10
- package/dist/theme/themes.mjs +14 -7
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +2 -5
- package/dist/trajectory/Trajectory.svelte +556 -352
- package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
- package/dist/trajectory/TrajectoryError.svelte +11 -8
- package/dist/trajectory/TrajectoryExportPane.svelte +28 -54
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +88 -99
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +73 -71
- package/dist/trajectory/format-detect.d.ts +0 -1
- package/dist/trajectory/format-detect.js +13 -17
- package/dist/trajectory/frame-reader.d.ts +2 -1
- package/dist/trajectory/frame-reader.js +74 -136
- package/dist/trajectory/helpers.d.ts +12 -2
- package/dist/trajectory/helpers.js +68 -37
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +3 -0
- package/dist/trajectory/parse/ase.d.ts +9 -1
- package/dist/trajectory/parse/ase.js +47 -32
- package/dist/trajectory/parse/diagnostics.d.ts +3 -0
- package/dist/trajectory/parse/diagnostics.js +14 -0
- package/dist/trajectory/parse/h5-utils.d.ts +13 -0
- package/dist/trajectory/parse/h5-utils.js +109 -0
- package/dist/trajectory/parse/hdf5.d.ts +1 -1
- package/dist/trajectory/parse/hdf5.js +116 -106
- package/dist/trajectory/parse/index.d.ts +3 -4
- package/dist/trajectory/parse/index.js +68 -119
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +14 -16
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +13 -9
- package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
- package/dist/trajectory/parse/vaspout-electronic.js +207 -0
- package/dist/trajectory/parse/vaspout-h5.d.ts +5 -0
- package/dist/trajectory/parse/vaspout-h5.js +284 -0
- package/dist/trajectory/parse/xyz.d.ts +9 -21
- package/dist/trajectory/parse/xyz.js +38 -39
- package/dist/trajectory/plotting.d.ts +8 -10
- package/dist/trajectory/plotting.js +102 -127
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +8 -1
- package/dist/xrd/XrdPlot.svelte +56 -85
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +8 -15
- package/dist/xrd/index.d.ts +2 -2
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +56 -73
- package/package.json +77 -36
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/element/data.json +0 -11864
- package/dist/fermi-surface/marching-cubes.d.ts +0 -2
- package/dist/fermi-surface/marching-cubes.js +0 -2
- package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/core/hover-lock.svelte.js +0 -45
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
- package/dist/structure/label-placement.d.ts +0 -14
- package/dist/structure/label-placement.js +0 -72
|
@@ -9,14 +9,8 @@
|
|
|
9
9
|
} from '../colors'
|
|
10
10
|
import { normalize_show_controls } from '../controls'
|
|
11
11
|
import { sanitize_html } from '../sanitize'
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
set_fullscreen_bg,
|
|
16
|
-
setup_fullscreen_effect,
|
|
17
|
-
toggle_fullscreen,
|
|
18
|
-
} from '../layout'
|
|
19
|
-
import { ColorBar, PlotTooltip } from '../plot'
|
|
12
|
+
import { Spinner } from '../feedback'
|
|
13
|
+
import { ColorBar } from '../plot'
|
|
20
14
|
import { create_pulse_animation } from '../effects.svelte'
|
|
21
15
|
import { DEFAULTS } from '../settings'
|
|
22
16
|
import type { AnyStructure } from '../structure'
|
|
@@ -25,38 +19,36 @@
|
|
|
25
19
|
compute_4d_coords,
|
|
26
20
|
TETRAHEDRON_VERTICES,
|
|
27
21
|
} from './barycentric-coords'
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import ConvexHullTooltip from './ConvexHullTooltip.svelte'
|
|
22
|
+
import { create_canvas_interactions } from './canvas-interactions.svelte'
|
|
23
|
+
import ConvexHullChrome from './ConvexHullChrome.svelte'
|
|
31
24
|
import GasPressureControls from './GasPressureControls.svelte'
|
|
32
25
|
import * as helpers from './helpers'
|
|
26
|
+
import { create_hull_data_pipeline } from './hull-state.svelte'
|
|
33
27
|
import type { BaseConvexHullProps, Hull3DProps } from './index'
|
|
34
28
|
import { CONVEX_HULL_STYLE, default_controls, default_hull_config } from './index'
|
|
35
|
-
import StructurePopup from './StructurePopup.svelte'
|
|
36
29
|
import TemperatureSlider from './TemperatureSlider.svelte'
|
|
37
30
|
import type { Point4D } from './thermodynamics'
|
|
38
31
|
import * as thermo from './thermodynamics'
|
|
39
|
-
import type {
|
|
40
|
-
|
|
41
|
-
HighlightStyle,
|
|
42
|
-
HoverData3D,
|
|
43
|
-
HullFaceColorMode,
|
|
44
|
-
} from './types'
|
|
32
|
+
import type { ConvexHullEntry, HighlightStyle, HullFaceColorMode, PhaseData } from './types'
|
|
33
|
+
import { MAGNETIC_ORDERING_CATEGORY } from './types'
|
|
45
34
|
import { compute_hull_stability } from './helpers'
|
|
46
35
|
|
|
47
36
|
let {
|
|
48
37
|
entries = [],
|
|
49
38
|
controls = {},
|
|
50
39
|
config = {},
|
|
40
|
+
show_controls,
|
|
51
41
|
on_point_click,
|
|
52
42
|
on_point_hover,
|
|
53
43
|
fullscreen = $bindable(DEFAULTS.convex_hull.quaternary.fullscreen),
|
|
54
|
-
|
|
44
|
+
fullscreen_toggle = true,
|
|
55
45
|
enable_info_pane = true,
|
|
56
46
|
wrapper = $bindable(),
|
|
57
47
|
label_threshold = 50,
|
|
58
48
|
show_stable = $bindable(DEFAULTS.convex_hull.quaternary.show_stable),
|
|
59
49
|
show_unstable = $bindable(DEFAULTS.convex_hull.quaternary.show_unstable),
|
|
50
|
+
entry_category = MAGNETIC_ORDERING_CATEGORY,
|
|
51
|
+
hidden_categories = $bindable([]),
|
|
60
52
|
show_hull_faces = $bindable(DEFAULTS.convex_hull.quaternary.show_hull_faces),
|
|
61
53
|
hull_face_opacity = $bindable(DEFAULTS.convex_hull.quaternary.hull_face_opacity),
|
|
62
54
|
hull_face_color_mode = $bindable(
|
|
@@ -64,23 +56,17 @@
|
|
|
64
56
|
),
|
|
65
57
|
element_colors = vesta_hex,
|
|
66
58
|
color_mode = $bindable(DEFAULTS.convex_hull.quaternary.color_mode),
|
|
67
|
-
color_scale = $bindable(
|
|
68
|
-
DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName,
|
|
69
|
-
),
|
|
59
|
+
color_scale = $bindable(DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName),
|
|
70
60
|
info_pane_open = $bindable(DEFAULTS.convex_hull.quaternary.info_pane_open),
|
|
71
|
-
|
|
61
|
+
controls_open = $bindable(DEFAULTS.convex_hull.quaternary.legend_pane_open),
|
|
72
62
|
max_hull_dist_show_phases = $bindable(
|
|
73
63
|
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
|
|
74
64
|
),
|
|
75
65
|
max_hull_dist_show_labels = $bindable(
|
|
76
66
|
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_labels,
|
|
77
67
|
),
|
|
78
|
-
show_stable_labels = $bindable(
|
|
79
|
-
|
|
80
|
-
),
|
|
81
|
-
show_unstable_labels = $bindable(
|
|
82
|
-
DEFAULTS.convex_hull.quaternary.show_unstable_labels,
|
|
83
|
-
),
|
|
68
|
+
show_stable_labels = $bindable(DEFAULTS.convex_hull.quaternary.show_stable_labels),
|
|
69
|
+
show_unstable_labels = $bindable(DEFAULTS.convex_hull.quaternary.show_unstable_labels),
|
|
84
70
|
on_file_drop,
|
|
85
71
|
enable_click_selection = true,
|
|
86
72
|
enable_structure_preview = true,
|
|
@@ -99,12 +85,13 @@
|
|
|
99
85
|
children,
|
|
100
86
|
tooltip,
|
|
101
87
|
...rest
|
|
102
|
-
}: BaseConvexHullProps<ConvexHullEntry> &
|
|
103
|
-
|
|
104
|
-
|
|
88
|
+
}: BaseConvexHullProps<ConvexHullEntry> &
|
|
89
|
+
Hull3DProps & {
|
|
90
|
+
highlight_style?: HighlightStyle
|
|
91
|
+
} = $props()
|
|
105
92
|
|
|
106
93
|
const merged_controls = $derived({ ...default_controls, ...controls })
|
|
107
|
-
const controls_config = $derived(normalize_show_controls(
|
|
94
|
+
const controls_config = $derived(normalize_show_controls(show_controls))
|
|
108
95
|
const merged_config = $derived({
|
|
109
96
|
...default_hull_config,
|
|
110
97
|
...config,
|
|
@@ -114,90 +101,36 @@
|
|
|
114
101
|
|
|
115
102
|
// Reactive dark mode detection for canvas text color
|
|
116
103
|
let dark_mode = $state(is_dark_mode())
|
|
117
|
-
$effect(() => watch_dark_mode((dark) => dark_mode = dark))
|
|
104
|
+
$effect(() => watch_dark_mode((dark) => (dark_mode = dark)))
|
|
118
105
|
const text_color = $derived(helpers.get_canvas_text_color(dark_mode))
|
|
119
106
|
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
// Gas-dependent chemical potential support (corrections based on T, P)
|
|
145
|
-
const {
|
|
146
|
-
entries: gas_corrected_entries,
|
|
147
|
-
analysis: gas_analysis,
|
|
148
|
-
merged_config: merged_gas_config,
|
|
149
|
-
} = $derived(
|
|
150
|
-
helpers.get_gas_corrected_entries(
|
|
151
|
-
temp_filtered_entries,
|
|
152
|
-
gas_config,
|
|
153
|
-
gas_pressures,
|
|
154
|
-
temperature ?? helpers.DEFAULT_GAS_TEMP,
|
|
155
|
-
),
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
let { // Compute energy mode information
|
|
159
|
-
has_precomputed_e_form,
|
|
160
|
-
has_precomputed_hull,
|
|
161
|
-
can_compute_e_form,
|
|
162
|
-
can_compute_hull,
|
|
163
|
-
energy_mode,
|
|
164
|
-
unary_refs,
|
|
165
|
-
} = $derived(
|
|
166
|
-
helpers.compute_energy_mode_info(
|
|
167
|
-
gas_corrected_entries,
|
|
168
|
-
thermo.find_lowest_energy_unary_refs,
|
|
169
|
-
energy_source_mode,
|
|
170
|
-
),
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
const effective_entries = $derived(
|
|
174
|
-
helpers.get_effective_entries(
|
|
175
|
-
gas_corrected_entries,
|
|
176
|
-
energy_mode,
|
|
177
|
-
unary_refs,
|
|
178
|
-
thermo.compute_e_form_per_atom,
|
|
179
|
-
),
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
// Process convex hull data with unified PhaseData interface using effective entries
|
|
183
|
-
const pd_data = $derived(thermo.process_hull_entries(effective_entries))
|
|
184
|
-
|
|
185
|
-
// Pre-compute polymorph stats once for O(1) tooltip lookups
|
|
186
|
-
const polymorph_stats_map = $derived(
|
|
187
|
-
helpers.compute_all_polymorph_stats(effective_entries),
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
const elements = $derived.by(() => {
|
|
191
|
-
if (pd_data.elements.length > 4) {
|
|
192
|
-
console.error(
|
|
193
|
-
`ConvexHull4D: Dataset contains ${pd_data.elements.length} elements, but quaternary diagrams require exactly 4. Found: [${
|
|
194
|
-
pd_data.elements.join(`, `)
|
|
195
|
-
}]`,
|
|
196
|
-
)
|
|
197
|
-
return []
|
|
198
|
-
}
|
|
199
|
-
return pd_data.elements
|
|
107
|
+
// Shared reactive data pipeline (temperature → gas → energy mode → hull data → threshold)
|
|
108
|
+
// Explicit generic breaks the circular type inference through the all_enriched_entries thunk
|
|
109
|
+
const hull_data = create_hull_data_pipeline<ConvexHullEntry>({
|
|
110
|
+
dim: 4,
|
|
111
|
+
entries: () => entries,
|
|
112
|
+
temperature: () => temperature,
|
|
113
|
+
interpolate_temperature: () => interpolate_temperature,
|
|
114
|
+
max_interpolation_gap: () => max_interpolation_gap,
|
|
115
|
+
gas_config: () => gas_config,
|
|
116
|
+
gas_pressures: () => gas_pressures,
|
|
117
|
+
energy_source_mode: () => energy_source_mode,
|
|
118
|
+
all_enriched_entries: () => all_enriched_entries,
|
|
119
|
+
max_hull_dist_show_phases: () => max_hull_dist_show_phases,
|
|
120
|
+
show_stable: () => show_stable,
|
|
121
|
+
show_unstable: () => show_unstable,
|
|
122
|
+
entry_category: () => entry_category,
|
|
123
|
+
hidden_categories: () => hidden_categories,
|
|
124
|
+
keep_plot_entry: helpers.entry_within_hull_dist,
|
|
125
|
+
set_temperature: (next_temp) => (temperature = next_temp),
|
|
126
|
+
set_max_hull_dist_show_phases: (value) => (max_hull_dist_show_phases = value),
|
|
127
|
+
set_stable_entries: (value) => (stable_entries = value),
|
|
128
|
+
set_unstable_entries: (value) => (unstable_entries = value),
|
|
200
129
|
})
|
|
130
|
+
const merged_gas_config = $derived(hull_data.merged_gas_config)
|
|
131
|
+
const pd_data = $derived(hull_data.pd_data)
|
|
132
|
+
const elements = $derived(hull_data.elements)
|
|
133
|
+
const plot_entries = $derived(hull_data.plot_entries)
|
|
201
134
|
|
|
202
135
|
// Compute 4D hull for visualization (always compute when we have formation energies)
|
|
203
136
|
const hull_4d = $derived.by(() => {
|
|
@@ -205,8 +138,9 @@
|
|
|
205
138
|
|
|
206
139
|
try {
|
|
207
140
|
// Get coords with formation energies, excluding entries that don't participate in hull
|
|
208
|
-
const coords = compute_4d_coords(pd_data.entries, elements)
|
|
209
|
-
|
|
141
|
+
const coords = compute_4d_coords(pd_data.entries, elements).filter(
|
|
142
|
+
(ent) => !ent.exclude_from_hull,
|
|
143
|
+
)
|
|
210
144
|
|
|
211
145
|
// Convert to 4D points for hull computation using barycentric coordinates (composition fractions)
|
|
212
146
|
const points_4d: Point4D[] = coords
|
|
@@ -234,84 +168,46 @@
|
|
|
234
168
|
})
|
|
235
169
|
|
|
236
170
|
// Enrich coords with e_above_hull (before filtering)
|
|
237
|
-
|
|
171
|
+
// Explicit return type breaks circular type inference with the hull_data pipeline
|
|
172
|
+
const all_enriched_entries = $derived.by((): ConvexHullEntry[] => {
|
|
238
173
|
if (elements.length !== 4) return []
|
|
239
174
|
try {
|
|
240
175
|
const coords = compute_4d_coords(pd_data.entries, elements)
|
|
241
|
-
if (energy_mode !== `on-the-fly` || hull_4d.length === 0) return coords
|
|
176
|
+
if (hull_data.energy_mode !== `on-the-fly` || hull_4d.length === 0) return coords
|
|
242
177
|
|
|
243
178
|
// Build 4D points, tracking original indices for mapping hull distances back
|
|
244
179
|
const valid = coords.flatMap((entry, idx) => {
|
|
245
180
|
if (
|
|
246
181
|
!Number.isFinite(entry.e_form_per_atom) ||
|
|
247
182
|
![entry.x, entry.y, entry.z].every(Number.isFinite)
|
|
248
|
-
)
|
|
183
|
+
)
|
|
184
|
+
return []
|
|
249
185
|
const amounts = elements.map((el) => entry.composition[el] || 0)
|
|
250
|
-
|
|
186
|
+
const total = amounts.reduce((sum, amt) => sum + amt, 0)
|
|
251
187
|
if (!(total > 0)) return []
|
|
252
|
-
|
|
188
|
+
const [x, y, z] = amounts.map((amt) => amt / total)
|
|
253
189
|
return [x, y, z].every(Number.isFinite)
|
|
254
190
|
? [{ idx, pt: { x, y, z, w: entry.e_form_per_atom ?? NaN } }]
|
|
255
191
|
: []
|
|
256
192
|
})
|
|
257
|
-
const raw_dists = thermo.compute_e_above_hull_4d(
|
|
193
|
+
const raw_dists = thermo.compute_e_above_hull_4d(
|
|
194
|
+
valid.map((item) => item.pt),
|
|
195
|
+
hull_4d,
|
|
196
|
+
)
|
|
258
197
|
const hull_map = new Map(valid.map((item, hull_idx) => [item.idx, raw_dists[hull_idx]]))
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
})
|
|
198
|
+
// missing/non-finite distance (no energy or point outside hull projection) -> unknown
|
|
199
|
+
return coords.map((entry, idx) => ({
|
|
200
|
+
...entry,
|
|
201
|
+
...compute_hull_stability(hull_map.get(idx), entry.exclude_from_hull),
|
|
202
|
+
}))
|
|
264
203
|
} catch (err) {
|
|
265
204
|
console.error(`Error computing quaternary coordinates:`, err)
|
|
266
205
|
return []
|
|
267
206
|
}
|
|
268
207
|
})
|
|
269
208
|
|
|
270
|
-
// Auto threshold: show all for few entries, use default for many, interpolate between
|
|
271
|
-
const max_hull_dist_in_data = $derived(
|
|
272
|
-
helpers.calc_max_hull_dist_in_data(all_enriched_entries),
|
|
273
|
-
)
|
|
274
|
-
const auto_default_threshold = $derived(helpers.compute_auto_hull_dist_threshold(
|
|
275
|
-
all_enriched_entries.length,
|
|
276
|
-
max_hull_dist_in_data,
|
|
277
|
-
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
|
|
278
|
-
))
|
|
279
|
-
|
|
280
|
-
const next_auto_threshold = helpers.auto_threshold_reset(
|
|
281
|
-
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_phases,
|
|
282
|
-
)
|
|
283
|
-
$effect(() => {
|
|
284
|
-
max_hull_dist_show_phases = next_auto_threshold(
|
|
285
|
-
entries,
|
|
286
|
-
max_hull_dist_show_phases,
|
|
287
|
-
auto_default_threshold,
|
|
288
|
-
) ?? max_hull_dist_show_phases
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
// Filter by threshold; visibility is a view predicate, not entry state.
|
|
292
|
-
const plot_entries = $derived(
|
|
293
|
-
all_enriched_entries.filter((entry) => {
|
|
294
|
-
// Always include stable entries and elemental reference points
|
|
295
|
-
if (helpers.entry_is_stable(entry)) return true
|
|
296
|
-
return typeof entry.e_above_hull === `number` &&
|
|
297
|
-
entry.e_above_hull <= max_hull_dist_show_phases
|
|
298
|
-
}),
|
|
299
|
-
)
|
|
300
|
-
const visible_entries = $derived(helpers.visible_entries(
|
|
301
|
-
plot_entries,
|
|
302
|
-
show_stable,
|
|
303
|
-
show_unstable,
|
|
304
|
-
))
|
|
305
|
-
|
|
306
|
-
// Stable and unstable entries exposed as bindable props
|
|
307
|
-
$effect(() => {
|
|
308
|
-
stable_entries = plot_entries.filter(helpers.entry_is_stable)
|
|
309
|
-
unstable_entries = plot_entries.filter(helpers.entry_is_unstable)
|
|
310
|
-
})
|
|
311
|
-
|
|
312
209
|
let canvas: HTMLCanvasElement | undefined = undefined
|
|
313
210
|
let ctx: CanvasRenderingContext2D | null = null
|
|
314
|
-
let frame_id = 0 // Performance optimization
|
|
315
211
|
|
|
316
212
|
// Camera state - following Materials Project's 3D camera setup
|
|
317
213
|
let camera = $state({
|
|
@@ -322,43 +218,60 @@
|
|
|
322
218
|
center_y: 20, // Slight offset to avoid legend overlap
|
|
323
219
|
})
|
|
324
220
|
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
221
|
+
// Shared canvas-interaction scaffold (mouse/keyboard handlers, hover/drag/popup
|
|
222
|
+
// state, canvas sizing, render scheduler). Rotation math + keydown actions stay local.
|
|
223
|
+
const interactions = create_canvas_interactions({
|
|
224
|
+
wheel_clamp: [1.0, 15],
|
|
225
|
+
fullscreen_bg_var: `--hull-4d-bg-fullscreen`,
|
|
226
|
+
canvas: () => canvas,
|
|
227
|
+
wrapper: () => wrapper,
|
|
228
|
+
ctx: () => ctx,
|
|
229
|
+
set_ctx: (context) => (ctx = context),
|
|
230
|
+
set_canvas_dims: (dims) => (canvas_dims = dims),
|
|
231
|
+
visible_entries: () => hull_data.visible_entries,
|
|
232
|
+
plot_entries: () => plot_entries,
|
|
233
|
+
selected_entry: () => selected_entry,
|
|
234
|
+
set_selected_entry: (entry) => (selected_entry = entry),
|
|
235
|
+
fullscreen: () => fullscreen,
|
|
236
|
+
enable_click_selection: () => enable_click_selection,
|
|
237
|
+
enable_structure_preview: () => enable_structure_preview,
|
|
238
|
+
on_point_click: () => on_point_click,
|
|
239
|
+
on_point_hover: () => on_point_hover,
|
|
240
|
+
on_file_drop: () => on_file_drop,
|
|
241
|
+
entry_category: () => entry_category,
|
|
242
|
+
zoom: () => camera.zoom,
|
|
243
|
+
set_zoom: (zoom) => (camera.zoom = zoom),
|
|
244
|
+
project_point: project_3d_point,
|
|
245
|
+
extract_structure: extract_structure_from_entry,
|
|
246
|
+
render_frame,
|
|
247
|
+
on_drag: (dx, dy, panning) => {
|
|
248
|
+
if (panning) {
|
|
249
|
+
camera.center_x += dx
|
|
250
|
+
camera.center_y += dy
|
|
251
|
+
} else {
|
|
252
|
+
camera.rotation_y += dx * 0.005
|
|
253
|
+
camera.rotation_x = Math.max(
|
|
254
|
+
-Math.PI / 3,
|
|
255
|
+
Math.min(Math.PI / 3, camera.rotation_x - dy * 0.005),
|
|
256
|
+
)
|
|
359
257
|
}
|
|
360
|
-
}
|
|
258
|
+
},
|
|
259
|
+
// Reset pan center when entering/exiting fullscreen
|
|
260
|
+
on_fullscreen_change: () => {
|
|
261
|
+
camera.center_x = 0
|
|
262
|
+
camera.center_y = 20
|
|
263
|
+
},
|
|
264
|
+
actions: () => ({
|
|
265
|
+
r: reset_camera,
|
|
266
|
+
b: () => (color_mode = color_mode === `stability` ? `energy` : `stability`),
|
|
267
|
+
s: () => (show_stable = !show_stable),
|
|
268
|
+
u: () => (show_unstable = !show_unstable),
|
|
269
|
+
h: () => (show_hull_faces = !show_hull_faces),
|
|
270
|
+
l: () => (show_stable_labels = !show_stable_labels),
|
|
271
|
+
}),
|
|
361
272
|
})
|
|
273
|
+
const { render_once } = interactions
|
|
274
|
+
const sorted_points_cache = $derived(interactions.sorted_points_cache)
|
|
362
275
|
|
|
363
276
|
// Hull face color (customizable via controls)
|
|
364
277
|
let hull_face_color = $state(`#4caf50`)
|
|
@@ -371,9 +284,7 @@
|
|
|
371
284
|
let pulse_opacity = $derived(0.3 + 0.4 * pulse.unit)
|
|
372
285
|
|
|
373
286
|
// Merge highlight style with defaults
|
|
374
|
-
const merged_highlight_style = $derived(
|
|
375
|
-
helpers.merge_highlight_style(highlight_style),
|
|
376
|
-
)
|
|
287
|
+
const merged_highlight_style = $derived(helpers.merge_highlight_style(highlight_style))
|
|
377
288
|
|
|
378
289
|
// Helper to check if entry is highlighted
|
|
379
290
|
const is_highlighted = (entry: ConvexHullEntry): boolean =>
|
|
@@ -382,31 +293,27 @@
|
|
|
382
293
|
// Re-render when important state changes
|
|
383
294
|
$effect(() => {
|
|
384
295
|
// oxfmt-ignore
|
|
385
|
-
void [show_hull_faces, color_mode, color_scale, camera.rotation_x, camera.rotation_y, camera.zoom, camera.center_x, camera.center_y, plot_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, text_color, elements] // track reactively
|
|
296
|
+
void [show_hull_faces, color_mode, color_scale, camera.rotation_x, camera.rotation_y, camera.zoom, camera.center_x, camera.center_y, plot_entries, hull_data.visible_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, text_color, elements] // track reactively
|
|
386
297
|
|
|
387
298
|
render_once()
|
|
388
299
|
})
|
|
389
300
|
|
|
390
301
|
// Visibility toggles are now bindable props
|
|
391
302
|
|
|
392
|
-
// Smart label defaults
|
|
303
|
+
// Smart label defaults: hide labels for large datasets. Applied once per dataset
|
|
304
|
+
// (keyed on the entries prop) so later entry-count changes from temperature/gas
|
|
305
|
+
// filtering don't clobber the user's label toggles.
|
|
306
|
+
let label_defaults_applied_for: PhaseData[] | null = null
|
|
393
307
|
$effect(() => {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
} else {
|
|
398
|
-
// For smaller datasets, show stable labels by default
|
|
399
|
-
show_stable_labels = true
|
|
400
|
-
}
|
|
308
|
+
if (label_defaults_applied_for === entries) return
|
|
309
|
+
label_defaults_applied_for = entries
|
|
310
|
+
show_stable_labels = hull_data.effective_entries.length <= label_threshold
|
|
401
311
|
show_unstable_labels = false
|
|
402
312
|
})
|
|
403
313
|
|
|
404
|
-
//
|
|
405
|
-
function extract_structure_from_entry(
|
|
406
|
-
|
|
407
|
-
): AnyStructure | null {
|
|
408
|
-
const orig_entry = entries.find((ent) => ent.entry_id === entry.entry_id)
|
|
409
|
-
return orig_entry?.structure as AnyStructure || null
|
|
314
|
+
// function (not const) so the create_canvas_interactions options above can reference it
|
|
315
|
+
function extract_structure_from_entry(entry: ConvexHullEntry): AnyStructure | null {
|
|
316
|
+
return helpers.extract_structure_from_entry(entries, entry)
|
|
410
317
|
}
|
|
411
318
|
|
|
412
319
|
const reset_camera = () => {
|
|
@@ -420,17 +327,17 @@
|
|
|
420
327
|
reset_camera()
|
|
421
328
|
fullscreen = DEFAULTS.convex_hull.quaternary.fullscreen
|
|
422
329
|
info_pane_open = DEFAULTS.convex_hull.quaternary.info_pane_open
|
|
423
|
-
|
|
330
|
+
controls_open = DEFAULTS.convex_hull.quaternary.legend_pane_open
|
|
424
331
|
color_mode = DEFAULTS.convex_hull.quaternary.color_mode
|
|
425
332
|
color_scale = DEFAULTS.convex_hull.quaternary.color_scale as D3InterpolateName
|
|
426
333
|
show_stable = DEFAULTS.convex_hull.quaternary.show_stable
|
|
427
334
|
show_unstable = DEFAULTS.convex_hull.quaternary.show_unstable
|
|
335
|
+
hidden_categories = []
|
|
428
336
|
show_stable_labels = DEFAULTS.convex_hull.quaternary.show_stable_labels
|
|
429
337
|
show_unstable_labels = DEFAULTS.convex_hull.quaternary.show_unstable_labels
|
|
430
338
|
// Use auto-computed threshold based on entry count instead of static default
|
|
431
|
-
max_hull_dist_show_phases = auto_default_threshold
|
|
432
|
-
max_hull_dist_show_labels =
|
|
433
|
-
DEFAULTS.convex_hull.quaternary.max_hull_dist_show_labels
|
|
339
|
+
max_hull_dist_show_phases = hull_data.auto_default_threshold
|
|
340
|
+
max_hull_dist_show_labels = DEFAULTS.convex_hull.quaternary.max_hull_dist_show_labels
|
|
434
341
|
show_hull_faces = DEFAULTS.convex_hull.quaternary.show_hull_faces
|
|
435
342
|
hull_face_color = DEFAULTS.convex_hull.quaternary.hull_face_color
|
|
436
343
|
hull_face_opacity = DEFAULTS.convex_hull.quaternary.hull_face_opacity
|
|
@@ -438,69 +345,6 @@
|
|
|
438
345
|
.hull_face_color_mode as HullFaceColorMode
|
|
439
346
|
}
|
|
440
347
|
|
|
441
|
-
const handle_keydown = (event: KeyboardEvent) => {
|
|
442
|
-
const target = event.target
|
|
443
|
-
// Skip if focus is on an interactive element that handles Enter natively
|
|
444
|
-
const interactive_selector =
|
|
445
|
-
`input,textarea,select,button,a,[contenteditable="true"],[role="button"],[tabindex]:not([tabindex="-1"])`
|
|
446
|
-
if (
|
|
447
|
-
target instanceof HTMLElement &&
|
|
448
|
-
target.matches(interactive_selector) &&
|
|
449
|
-
target !== canvas
|
|
450
|
-
) return
|
|
451
|
-
|
|
452
|
-
// Prevent double handling from canvas + wrapper bubbling
|
|
453
|
-
if (event.target !== event.currentTarget && event.currentTarget !== canvas) return
|
|
454
|
-
|
|
455
|
-
// Handle Enter for keyboard accessibility - select hovered entry
|
|
456
|
-
if (event.key === `Enter`) {
|
|
457
|
-
const entry = hover_data?.entry
|
|
458
|
-
if (entry) {
|
|
459
|
-
on_point_click?.(entry)
|
|
460
|
-
if (enable_click_selection) {
|
|
461
|
-
selected_entry = entry
|
|
462
|
-
if (enable_structure_preview) {
|
|
463
|
-
const structure = extract_structure_from_entry(entry)
|
|
464
|
-
if (structure) {
|
|
465
|
-
selected_structure = structure
|
|
466
|
-
modal_place_right = helpers.calculate_modal_side(wrapper)
|
|
467
|
-
modal_open = true
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
} else if (modal_open) {
|
|
472
|
-
close_structure_popup()
|
|
473
|
-
}
|
|
474
|
-
return
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
const actions: Record<string, () => void> = {
|
|
478
|
-
r: reset_camera,
|
|
479
|
-
b: () => color_mode = color_mode === `stability` ? `energy` : `stability`,
|
|
480
|
-
s: () => show_stable = !show_stable,
|
|
481
|
-
u: () => show_unstable = !show_unstable,
|
|
482
|
-
h: () => show_hull_faces = !show_hull_faces,
|
|
483
|
-
l: () => show_stable_labels = !show_stable_labels,
|
|
484
|
-
}
|
|
485
|
-
actions[event.key.toLowerCase()]?.()
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
async function handle_file_drop(event: DragEvent): Promise<void> {
|
|
489
|
-
drag_over = false
|
|
490
|
-
const data = await helpers.parse_hull_entries_from_drop(event)
|
|
491
|
-
if (data) on_file_drop?.(data)
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
async function copy_entry_data(
|
|
495
|
-
entry: ConvexHullEntry,
|
|
496
|
-
position: { x: number; y: number },
|
|
497
|
-
) {
|
|
498
|
-
await helpers.copy_entry_to_clipboard(entry, position, (visible, pos) => {
|
|
499
|
-
copy_feedback.visible = visible
|
|
500
|
-
copy_feedback.position = pos
|
|
501
|
-
})
|
|
502
|
-
}
|
|
503
|
-
|
|
504
348
|
const get_point_color = (entry: ConvexHullEntry): string =>
|
|
505
349
|
helpers.get_point_color_for_entry(
|
|
506
350
|
entry,
|
|
@@ -511,7 +355,7 @@
|
|
|
511
355
|
|
|
512
356
|
// Cache energy color scale per frame/setting
|
|
513
357
|
const energy_color_scale = $derived.by(() =>
|
|
514
|
-
helpers.get_energy_color_scale(color_mode, color_scale, plot_entries)
|
|
358
|
+
helpers.get_energy_color_scale(color_mode, color_scale, plot_entries),
|
|
515
359
|
)
|
|
516
360
|
|
|
517
361
|
// Convex hull statistics - compute internally and expose via bindable prop
|
|
@@ -672,30 +516,10 @@
|
|
|
672
516
|
const [p0, p1, p2, p3] = tet.vertices
|
|
673
517
|
|
|
674
518
|
// Convert barycentric coordinates to tetrahedral 3D coordinates
|
|
675
|
-
const tet0 = barycentric_to_tetrahedral([
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
1 - p0.x - p0.y - p0.z,
|
|
680
|
-
])
|
|
681
|
-
const tet1 = barycentric_to_tetrahedral([
|
|
682
|
-
p1.x,
|
|
683
|
-
p1.y,
|
|
684
|
-
p1.z,
|
|
685
|
-
1 - p1.x - p1.y - p1.z,
|
|
686
|
-
])
|
|
687
|
-
const tet2 = barycentric_to_tetrahedral([
|
|
688
|
-
p2.x,
|
|
689
|
-
p2.y,
|
|
690
|
-
p2.z,
|
|
691
|
-
1 - p2.x - p2.y - p2.z,
|
|
692
|
-
])
|
|
693
|
-
const tet3 = barycentric_to_tetrahedral([
|
|
694
|
-
p3.x,
|
|
695
|
-
p3.y,
|
|
696
|
-
p3.z,
|
|
697
|
-
1 - p3.x - p3.y - p3.z,
|
|
698
|
-
])
|
|
519
|
+
const tet0 = barycentric_to_tetrahedral([p0.x, p0.y, p0.z, 1 - p0.x - p0.y - p0.z])
|
|
520
|
+
const tet1 = barycentric_to_tetrahedral([p1.x, p1.y, p1.z, 1 - p1.x - p1.y - p1.z])
|
|
521
|
+
const tet2 = barycentric_to_tetrahedral([p2.x, p2.y, p2.z, 1 - p2.x - p2.y - p2.z])
|
|
522
|
+
const tet3 = barycentric_to_tetrahedral([p3.x, p3.y, p3.z, 1 - p3.x - p3.y - p3.z])
|
|
699
523
|
|
|
700
524
|
// Project to 2D screen space
|
|
701
525
|
const proj0 = project_3d_point(tet0.x, tet0.y, tet0.z)
|
|
@@ -709,8 +533,14 @@
|
|
|
709
533
|
(p0.x + p1.x + p2.x + p3.x) / 4,
|
|
710
534
|
(p0.y + p1.y + p2.y + p3.y) / 4,
|
|
711
535
|
(p0.z + p1.z + p2.z + p3.z) / 4,
|
|
712
|
-
(
|
|
713
|
-
|
|
536
|
+
(1 -
|
|
537
|
+
p0.x -
|
|
538
|
+
p0.y -
|
|
539
|
+
p0.z +
|
|
540
|
+
(1 - p1.x - p1.y - p1.z) +
|
|
541
|
+
(1 - p2.x - p2.y - p2.z) +
|
|
542
|
+
(1 - p3.x - p3.y - p3.z)) /
|
|
543
|
+
4,
|
|
714
544
|
]
|
|
715
545
|
|
|
716
546
|
// Each tetrahedron has 4 triangular faces
|
|
@@ -736,14 +566,14 @@
|
|
|
736
566
|
triangles.sort((a, b) => a.avg_depth - b.avg_depth)
|
|
737
567
|
|
|
738
568
|
// Lazy computation for uniform mode: normalize alpha by formation energy
|
|
739
|
-
let norm_alpha: ((
|
|
569
|
+
let norm_alpha: ((energy: number) => number) | null = null
|
|
740
570
|
if (hull_face_color_mode === `uniform`) {
|
|
741
571
|
norm_alpha = (energy: number) => {
|
|
742
|
-
const
|
|
572
|
+
const frac = Math.max(
|
|
743
573
|
0,
|
|
744
574
|
Math.min(1, (0 - energy) / Math.max(1e-6, 0 - formation_energy_min)),
|
|
745
575
|
)
|
|
746
|
-
return
|
|
576
|
+
return frac * hull_face_opacity
|
|
747
577
|
}
|
|
748
578
|
}
|
|
749
579
|
|
|
@@ -752,7 +582,7 @@
|
|
|
752
582
|
let min_w = 0
|
|
753
583
|
if (hull_face_color_mode === `formation_energy`) {
|
|
754
584
|
const all_avg_w = triangles.map((tri) => tri.avg_w)
|
|
755
|
-
min_w =
|
|
585
|
+
min_w = helpers.array_min(all_avg_w)
|
|
756
586
|
energy_face_scale = helpers.get_energy_color_scale(
|
|
757
587
|
`energy`,
|
|
758
588
|
color_scale,
|
|
@@ -770,7 +600,7 @@
|
|
|
770
600
|
}
|
|
771
601
|
if (hull_face_color_mode === `dominant_element`) {
|
|
772
602
|
// Find element with highest fraction
|
|
773
|
-
const max_idx = tri.centroid_bary.indexOf(
|
|
603
|
+
const max_idx = tri.centroid_bary.indexOf(helpers.array_max(tri.centroid_bary))
|
|
774
604
|
const el = elements[max_idx]
|
|
775
605
|
return element_colors[el] ?? `#888888`
|
|
776
606
|
}
|
|
@@ -784,9 +614,10 @@
|
|
|
784
614
|
for (const tri of triangles) {
|
|
785
615
|
const [v0, v1, v2] = tri.vertices
|
|
786
616
|
// Uniform mode uses variable opacity; other modes use fixed opacity
|
|
787
|
-
const alpha =
|
|
788
|
-
|
|
789
|
-
|
|
617
|
+
const alpha =
|
|
618
|
+
hull_face_color_mode === `uniform`
|
|
619
|
+
? (norm_alpha?.(tri.avg_w) ?? hull_face_opacity)
|
|
620
|
+
: hull_face_opacity
|
|
790
621
|
const face_color = get_face_color(tri)
|
|
791
622
|
|
|
792
623
|
ctx.save()
|
|
@@ -809,59 +640,16 @@
|
|
|
809
640
|
|
|
810
641
|
function draw_data_points(): void {
|
|
811
642
|
if (!ctx || sorted_points_cache.length === 0) return
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
ctx.fillStyle = `rgba(0, 0, 0, 0.2)`
|
|
823
|
-
const shadow_path = helpers.create_marker_path(size * 0.8, marker)
|
|
824
|
-
ctx.save()
|
|
825
|
-
ctx.translate(projected.x + shadow_offset, projected.y + shadow_offset)
|
|
826
|
-
ctx.fill(shadow_path)
|
|
827
|
-
ctx.restore()
|
|
828
|
-
|
|
829
|
-
// Highlights
|
|
830
|
-
if (selected_entry && entry.entry_id === selected_entry.entry_id) {
|
|
831
|
-
helpers.draw_selection_highlight(
|
|
832
|
-
ctx,
|
|
833
|
-
projected,
|
|
834
|
-
size,
|
|
835
|
-
canvas_dims.scale,
|
|
836
|
-
pulse.time,
|
|
837
|
-
pulse_opacity,
|
|
838
|
-
)
|
|
839
|
-
}
|
|
840
|
-
if (is_entry_highlighted) {
|
|
841
|
-
helpers.draw_highlight_effect(
|
|
842
|
-
ctx,
|
|
843
|
-
projected,
|
|
844
|
-
size,
|
|
845
|
-
canvas_dims.scale,
|
|
846
|
-
pulse.time,
|
|
847
|
-
merged_highlight_style,
|
|
848
|
-
)
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
// Main point with marker symbol
|
|
852
|
-
ctx.fillStyle =
|
|
853
|
-
is_entry_highlighted && merged_highlight_style.effect === `color`
|
|
854
|
-
? merged_highlight_style.color
|
|
855
|
-
: color
|
|
856
|
-
ctx.strokeStyle = is_stable ? `#ffffff` : `#000000`
|
|
857
|
-
ctx.lineWidth = 0.5 * canvas_dims.scale
|
|
858
|
-
const marker_path = helpers.create_marker_path(size, marker)
|
|
859
|
-
ctx.save()
|
|
860
|
-
ctx.translate(projected.x, projected.y)
|
|
861
|
-
ctx.fill(marker_path)
|
|
862
|
-
ctx.stroke(marker_path)
|
|
863
|
-
ctx.restore()
|
|
864
|
-
}
|
|
643
|
+
helpers.draw_hull_points(ctx, sorted_points_cache, {
|
|
644
|
+
scale: canvas_dims.scale,
|
|
645
|
+
shadow_factor: 2,
|
|
646
|
+
selected_entry,
|
|
647
|
+
is_highlighted,
|
|
648
|
+
get_point_color,
|
|
649
|
+
highlight_style: merged_highlight_style,
|
|
650
|
+
pulse_time: pulse.time,
|
|
651
|
+
pulse_opacity,
|
|
652
|
+
})
|
|
865
653
|
|
|
866
654
|
if (!merged_config.show_labels) return
|
|
867
655
|
|
|
@@ -871,9 +659,12 @@
|
|
|
871
659
|
.filter((entry) => {
|
|
872
660
|
if (entry.is_element) return false
|
|
873
661
|
const is_stable = helpers.entry_is_stable(entry)
|
|
874
|
-
return (
|
|
875
|
-
(
|
|
662
|
+
return (
|
|
663
|
+
(is_stable && show_stable_labels) ||
|
|
664
|
+
(!is_stable &&
|
|
665
|
+
show_unstable_labels &&
|
|
876
666
|
(entry.e_above_hull ?? 0) <= max_hull_dist_show_labels)
|
|
667
|
+
)
|
|
877
668
|
}),
|
|
878
669
|
)
|
|
879
670
|
|
|
@@ -925,169 +716,7 @@
|
|
|
925
716
|
draw_data_points() // Draw data points (on top)
|
|
926
717
|
}
|
|
927
718
|
|
|
928
|
-
|
|
929
|
-
is_dragging = true
|
|
930
|
-
drag_started = false
|
|
931
|
-
hover_data = null
|
|
932
|
-
on_point_hover?.(null)
|
|
933
|
-
last_mouse = { x: event.clientX, y: event.clientY }
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
const handle_mouse_move = (event: MouseEvent) => {
|
|
937
|
-
if (!is_dragging) return
|
|
938
|
-
const [dx, dy] = [event.clientX - last_mouse.x, event.clientY - last_mouse.y]
|
|
939
|
-
|
|
940
|
-
// Mark as drag if any movement occurred
|
|
941
|
-
if (dx !== 0 || dy !== 0) drag_started = true
|
|
942
|
-
|
|
943
|
-
// With Cmd/Ctrl held: pan the view instead of rotating
|
|
944
|
-
if (event.metaKey || event.ctrlKey) {
|
|
945
|
-
camera.center_x += dx
|
|
946
|
-
camera.center_y += dy
|
|
947
|
-
} else {
|
|
948
|
-
camera.rotation_y += dx * 0.005
|
|
949
|
-
camera.rotation_x = Math.max(
|
|
950
|
-
-Math.PI / 3,
|
|
951
|
-
Math.min(Math.PI / 3, camera.rotation_x - dy * 0.005),
|
|
952
|
-
)
|
|
953
|
-
}
|
|
954
|
-
last_mouse = { x: event.clientX, y: event.clientY }
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
const handle_wheel = (event: WheelEvent) => {
|
|
958
|
-
event.preventDefault()
|
|
959
|
-
camera.zoom = Math.max(
|
|
960
|
-
1.0,
|
|
961
|
-
Math.min(15, camera.zoom * (event.deltaY > 0 ? 0.98 : 1.02)),
|
|
962
|
-
)
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
const handle_hover = (event: MouseEvent) => {
|
|
966
|
-
if (is_dragging) return
|
|
967
|
-
const entry = find_entry_at_mouse(event)
|
|
968
|
-
hover_data = entry
|
|
969
|
-
? { entry, position: { x: event.clientX, y: event.clientY } }
|
|
970
|
-
: null
|
|
971
|
-
on_point_hover?.(hover_data)
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
const find_entry_at_mouse = (event: MouseEvent): ConvexHullEntry | null =>
|
|
975
|
-
helpers.find_hull_entry_at_mouse(
|
|
976
|
-
canvas,
|
|
977
|
-
event,
|
|
978
|
-
visible_entries,
|
|
979
|
-
(x: number, y: number, z: number) => {
|
|
980
|
-
const projected = project_3d_point(x, y, z)
|
|
981
|
-
return { x: projected.x, y: projected.y }
|
|
982
|
-
},
|
|
983
|
-
)
|
|
984
|
-
|
|
985
|
-
const handle_click = (event: MouseEvent) => {
|
|
986
|
-
event.stopPropagation()
|
|
987
|
-
|
|
988
|
-
// Check if this was a drag operation (any mouse movement during drag)
|
|
989
|
-
const was_drag = drag_started
|
|
990
|
-
drag_started = false // Reset for next interaction
|
|
991
|
-
if (was_drag) return // Don't trigger click if this was a drag
|
|
992
|
-
|
|
993
|
-
const entry = find_entry_at_mouse(event)
|
|
994
|
-
if (entry) {
|
|
995
|
-
on_point_click?.(entry)
|
|
996
|
-
if (enable_click_selection) {
|
|
997
|
-
selected_entry = entry
|
|
998
|
-
if (enable_structure_preview) {
|
|
999
|
-
const structure = extract_structure_from_entry(entry)
|
|
1000
|
-
if (structure) {
|
|
1001
|
-
selected_structure = structure
|
|
1002
|
-
modal_place_right = helpers.calculate_modal_side(wrapper)
|
|
1003
|
-
modal_open = true
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
} else if (modal_open) close_structure_popup()
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
function close_structure_popup() {
|
|
1011
|
-
modal_open = false
|
|
1012
|
-
selected_structure = null
|
|
1013
|
-
selected_entry = null
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
const handle_double_click = (event: MouseEvent) => {
|
|
1017
|
-
const entry = find_entry_at_mouse(event)
|
|
1018
|
-
if (entry) {
|
|
1019
|
-
copy_entry_data(entry, {
|
|
1020
|
-
x: event.clientX,
|
|
1021
|
-
y: event.clientY,
|
|
1022
|
-
})
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
function render_once() {
|
|
1027
|
-
if (!frame_id) {
|
|
1028
|
-
frame_id = requestAnimationFrame(() => {
|
|
1029
|
-
render_frame()
|
|
1030
|
-
frame_id = 0
|
|
1031
|
-
})
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
function update_canvas_size() {
|
|
1036
|
-
if (!canvas) return
|
|
1037
|
-
const dpr = globalThis.devicePixelRatio || 1
|
|
1038
|
-
const container = canvas.parentElement
|
|
1039
|
-
const rect = container?.getBoundingClientRect()
|
|
1040
|
-
const [width, height] = rect ? [rect.width, rect.height] : [400, 400]
|
|
1041
|
-
|
|
1042
|
-
const new_width = Math.max(0, Math.round(width * dpr))
|
|
1043
|
-
const new_height = Math.max(0, Math.round(height * dpr))
|
|
1044
|
-
canvas_dims = { width, height, scale: Math.min(width, height) / 600 }
|
|
1045
|
-
|
|
1046
|
-
if (!ctx || canvas.width !== new_width || canvas.height !== new_height) {
|
|
1047
|
-
canvas.width = new_width
|
|
1048
|
-
canvas.height = new_height
|
|
1049
|
-
ctx = canvas.getContext(`2d`)
|
|
1050
|
-
if (ctx) {
|
|
1051
|
-
ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
|
|
1052
|
-
ctx.imageSmoothingEnabled = true
|
|
1053
|
-
ctx.imageSmoothingQuality = `high`
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
render_once()
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
$effect(() => {
|
|
1060
|
-
if (!canvas) return
|
|
1061
|
-
|
|
1062
|
-
// Initial setup
|
|
1063
|
-
update_canvas_size()
|
|
1064
|
-
|
|
1065
|
-
// Watch for resize events - only update canvas, don't reset camera
|
|
1066
|
-
const resize_observer = new ResizeObserver(update_canvas_size)
|
|
1067
|
-
|
|
1068
|
-
const container = canvas.parentElement
|
|
1069
|
-
if (container) resize_observer.observe(container)
|
|
1070
|
-
|
|
1071
|
-
return () => { // Cleanup on unmount
|
|
1072
|
-
if (frame_id) cancelAnimationFrame(frame_id)
|
|
1073
|
-
resize_observer.disconnect()
|
|
1074
|
-
}
|
|
1075
|
-
})
|
|
1076
|
-
|
|
1077
|
-
// Fullscreen handling with camera reset
|
|
1078
|
-
let was_fullscreen = $state(fullscreen)
|
|
1079
|
-
$effect(() => {
|
|
1080
|
-
setup_fullscreen_effect(fullscreen, wrapper, (entering_fullscreen) => {
|
|
1081
|
-
if (entering_fullscreen !== was_fullscreen) {
|
|
1082
|
-
camera.center_x = 0
|
|
1083
|
-
camera.center_y = 20
|
|
1084
|
-
was_fullscreen = entering_fullscreen
|
|
1085
|
-
}
|
|
1086
|
-
})
|
|
1087
|
-
set_fullscreen_bg(wrapper, fullscreen, `--hull-4d-bg-fullscreen`)
|
|
1088
|
-
})
|
|
1089
|
-
|
|
1090
|
-
// Performance: Cache canvas dimensions and pre-compute sorted point projections
|
|
719
|
+
// Performance: Cache canvas dimensions and formation energy minimum
|
|
1091
720
|
let canvas_dims = $state({ width: 600, height: 600, scale: 1 })
|
|
1092
721
|
const formation_energy_min = $derived.by(() => {
|
|
1093
722
|
let min_energy = 0
|
|
@@ -1096,65 +725,41 @@
|
|
|
1096
725
|
}
|
|
1097
726
|
return min_energy
|
|
1098
727
|
})
|
|
1099
|
-
const sorted_points_cache = $derived.by(() => {
|
|
1100
|
-
if (!canvas || visible_entries.length === 0) return []
|
|
1101
|
-
return visible_entries
|
|
1102
|
-
.map((entry) => ({
|
|
1103
|
-
entry,
|
|
1104
|
-
projected: project_3d_point(entry.x, entry.y, entry.z),
|
|
1105
|
-
}))
|
|
1106
|
-
.sort((a, b) => a.projected.depth - b.projected.depth)
|
|
1107
|
-
})
|
|
1108
728
|
|
|
1109
|
-
let style = $derived(
|
|
1110
|
-
`--hull-stable-color:${merged_config.colors?.stable || `#0072B2`};
|
|
1111
|
-
--hull-unstable-color:${merged_config.colors?.unstable || `#E69F00`};
|
|
1112
|
-
--hull-edge-color:${merged_config.colors?.edge || `var(--text-color, #212121)`};
|
|
1113
|
-
--hull-text-color:${
|
|
1114
|
-
merged_config.colors?.annotation || `var(--text-color, #212121)`
|
|
1115
|
-
}`,
|
|
1116
|
-
)
|
|
729
|
+
let style = $derived(helpers.hull_style_css(merged_config.colors))
|
|
1117
730
|
</script>
|
|
1118
731
|
|
|
1119
732
|
<svelte:document
|
|
1120
733
|
onfullscreenchange={() => {
|
|
1121
|
-
fullscreen
|
|
734
|
+
// tie fullscreen state to this component's own wrapper, not any fullscreen element
|
|
735
|
+
fullscreen = document.fullscreenElement === wrapper
|
|
1122
736
|
}}
|
|
1123
|
-
onmousemove={handle_mouse_move}
|
|
1124
|
-
onmouseup={
|
|
737
|
+
onmousemove={interactions.handle_mouse_move}
|
|
738
|
+
onmouseup={interactions.handle_mouse_up}
|
|
1125
739
|
/>
|
|
1126
740
|
|
|
1127
741
|
<div
|
|
1128
742
|
{...rest}
|
|
1129
|
-
class=
|
|
1130
|
-
class:dragover={drag_over}
|
|
743
|
+
class={[`convex-hull-4d`, rest.class]}
|
|
744
|
+
class:dragover={interactions.drag_over}
|
|
1131
745
|
style={`${style}; ${rest.style ?? ``}`}
|
|
1132
746
|
data-has-selection={selected_entry !== null}
|
|
1133
|
-
data-has-hover={hover_data !== null}
|
|
1134
|
-
data-is-dragging={is_dragging}
|
|
747
|
+
data-has-hover={interactions.hover_data !== null}
|
|
748
|
+
data-is-dragging={interactions.is_dragging}
|
|
1135
749
|
data-rotation-x={camera.rotation_x.toFixed(4)}
|
|
1136
750
|
data-rotation-y={camera.rotation_y.toFixed(4)}
|
|
1137
751
|
bind:this={wrapper}
|
|
1138
752
|
role="application"
|
|
1139
753
|
tabindex="-1"
|
|
1140
|
-
|
|
1141
|
-
ondrop={handle_file_drop}
|
|
1142
|
-
ondragover={(event) => {
|
|
1143
|
-
event.preventDefault()
|
|
1144
|
-
drag_over = true
|
|
1145
|
-
}}
|
|
1146
|
-
ondragleave={(event) => {
|
|
1147
|
-
event.preventDefault()
|
|
1148
|
-
drag_over = false
|
|
1149
|
-
}}
|
|
754
|
+
{...interactions.wrapper_handlers}
|
|
1150
755
|
aria-label="Convex hull visualization"
|
|
1151
756
|
>
|
|
1152
757
|
{@render children?.({
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
758
|
+
stable_entries,
|
|
759
|
+
unstable_entries,
|
|
760
|
+
highlighted_entries,
|
|
761
|
+
selected_entry,
|
|
762
|
+
})}
|
|
1158
763
|
<h3 style="position: absolute; left: 1em; top: 1ex; margin: 0">
|
|
1159
764
|
{@html sanitize_html(merged_controls.title || phase_stats?.chemical_system || ``)}
|
|
1160
765
|
</h3>
|
|
@@ -1163,12 +768,7 @@
|
|
|
1163
768
|
bind:this={canvas}
|
|
1164
769
|
tabindex="0"
|
|
1165
770
|
aria-label={merged_controls.title || phase_stats?.chemical_system || `4D Convex Hull`}
|
|
1166
|
-
|
|
1167
|
-
onmousemove={handle_hover}
|
|
1168
|
-
onclick={handle_click}
|
|
1169
|
-
onkeydown={handle_keydown}
|
|
1170
|
-
ondblclick={handle_double_click}
|
|
1171
|
-
onwheel={handle_wheel}
|
|
771
|
+
{...interactions.canvas_handlers}
|
|
1172
772
|
></canvas>
|
|
1173
773
|
|
|
1174
774
|
{#if entries.length === 0}
|
|
@@ -1180,14 +780,9 @@
|
|
|
1180
780
|
|
|
1181
781
|
<!-- Energy above hull Color Bar -->
|
|
1182
782
|
{#if color_mode === `energy` && plot_entries.length > 0}
|
|
1183
|
-
{@const hull_distances = plot_entries
|
|
1184
|
-
.map((entry) => entry.e_above_hull)
|
|
1185
|
-
.filter((val): val is number => typeof val === `number`)}
|
|
1186
|
-
{@const min_energy = hull_distances.length > 0 ? Math.min(...hull_distances) : 0}
|
|
1187
|
-
{@const max_energy = hull_distances.length > 0 ? Math.max(...hull_distances, 0.1) : 0.1}
|
|
1188
783
|
<ColorBar
|
|
1189
784
|
title="Energy above hull (eV/atom)"
|
|
1190
|
-
range={
|
|
785
|
+
range={helpers.hull_distance_range(plot_entries)}
|
|
1191
786
|
{color_scale}
|
|
1192
787
|
wrapper_style="position: absolute; bottom: 2em; left: 1em; width: 200px;"
|
|
1193
788
|
bar_style="height: 12px;"
|
|
@@ -1195,137 +790,61 @@
|
|
|
1195
790
|
/>
|
|
1196
791
|
{/if}
|
|
1197
792
|
|
|
1198
|
-
<!--
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
bind:show_stable
|
|
1245
|
-
bind:show_unstable
|
|
1246
|
-
bind:show_stable_labels
|
|
1247
|
-
bind:show_unstable_labels
|
|
1248
|
-
bind:max_hull_dist_show_phases
|
|
1249
|
-
bind:max_hull_dist_show_labels
|
|
1250
|
-
{max_hull_dist_in_data}
|
|
1251
|
-
{stable_entries}
|
|
1252
|
-
{unstable_entries}
|
|
1253
|
-
{camera}
|
|
1254
|
-
{merged_controls}
|
|
1255
|
-
toggle_props={{ class: `legend-controls-btn` }}
|
|
1256
|
-
{show_hull_faces}
|
|
1257
|
-
on_hull_faces_change={(value: boolean) => show_hull_faces = value}
|
|
1258
|
-
{hull_face_color}
|
|
1259
|
-
on_hull_face_color_change={(value: string) => hull_face_color = value}
|
|
1260
|
-
{hull_face_opacity}
|
|
1261
|
-
on_hull_face_opacity_change={(value: number) => hull_face_opacity = value}
|
|
1262
|
-
{hull_face_color_mode}
|
|
1263
|
-
on_hull_face_color_mode_change={(value: HullFaceColorMode) =>
|
|
1264
|
-
hull_face_color_mode = value}
|
|
1265
|
-
bind:energy_source_mode
|
|
1266
|
-
{has_precomputed_e_form}
|
|
1267
|
-
{can_compute_e_form}
|
|
1268
|
-
{has_precomputed_hull}
|
|
1269
|
-
{can_compute_hull}
|
|
1270
|
-
/>
|
|
1271
|
-
{/if}
|
|
1272
|
-
</section>
|
|
1273
|
-
{/if}
|
|
1274
|
-
|
|
1275
|
-
{#if has_temp_data && temperature !== undefined}
|
|
1276
|
-
<TemperatureSlider {available_temperatures} bind:temperature />
|
|
793
|
+
<!-- Toolbar + tooltip/copy-feedback/drag/structure-popup chrome -->
|
|
794
|
+
<ConvexHullChrome
|
|
795
|
+
{interactions}
|
|
796
|
+
{hull_data}
|
|
797
|
+
{controls_config}
|
|
798
|
+
{reset_all}
|
|
799
|
+
reset_title="Reset view and settings"
|
|
800
|
+
{enable_info_pane}
|
|
801
|
+
{phase_stats}
|
|
802
|
+
{label_threshold}
|
|
803
|
+
{fullscreen}
|
|
804
|
+
{fullscreen_toggle}
|
|
805
|
+
{wrapper}
|
|
806
|
+
{camera}
|
|
807
|
+
{merged_controls}
|
|
808
|
+
{stable_entries}
|
|
809
|
+
{unstable_entries}
|
|
810
|
+
{get_point_color}
|
|
811
|
+
{merged_highlight_style}
|
|
812
|
+
{is_highlighted}
|
|
813
|
+
{tooltip}
|
|
814
|
+
{selected_entry}
|
|
815
|
+
bind:show_hull_faces
|
|
816
|
+
bind:hull_face_color
|
|
817
|
+
bind:hull_face_opacity
|
|
818
|
+
bind:hull_face_color_mode
|
|
819
|
+
bind:info_pane_open
|
|
820
|
+
bind:controls_open
|
|
821
|
+
bind:color_mode
|
|
822
|
+
bind:color_scale
|
|
823
|
+
bind:show_stable
|
|
824
|
+
bind:show_unstable
|
|
825
|
+
{entry_category}
|
|
826
|
+
bind:hidden_categories
|
|
827
|
+
bind:show_stable_labels
|
|
828
|
+
bind:show_unstable_labels
|
|
829
|
+
bind:max_hull_dist_show_phases
|
|
830
|
+
bind:max_hull_dist_show_labels
|
|
831
|
+
bind:energy_source_mode
|
|
832
|
+
/>
|
|
833
|
+
|
|
834
|
+
{#if hull_data.has_temp_data && temperature !== undefined}
|
|
835
|
+
<TemperatureSlider
|
|
836
|
+
available_temperatures={hull_data.available_temperatures}
|
|
837
|
+
bind:temperature
|
|
838
|
+
/>
|
|
1277
839
|
{/if}
|
|
1278
840
|
|
|
1279
|
-
{#if gas_analysis.has_gas_dependent_elements && merged_gas_config}
|
|
841
|
+
{#if hull_data.gas_analysis.has_gas_dependent_elements && merged_gas_config}
|
|
1280
842
|
<GasPressureControls
|
|
1281
843
|
config={merged_gas_config}
|
|
1282
844
|
bind:pressures={gas_pressures}
|
|
1283
845
|
temperature={temperature ?? 300}
|
|
1284
846
|
/>
|
|
1285
847
|
{/if}
|
|
1286
|
-
|
|
1287
|
-
<!-- Hover tooltip -->
|
|
1288
|
-
{#if hover_data}
|
|
1289
|
-
{@const { entry, position } = hover_data}
|
|
1290
|
-
{@const entry_highlight = is_highlighted(entry) ? merged_highlight_style : undefined}
|
|
1291
|
-
{@const tooltip_style =
|
|
1292
|
-
`z-index: ${CONVEX_HULL_STYLE.z_index.tooltip}; backdrop-filter: blur(4px);
|
|
1293
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);`}
|
|
1294
|
-
<PlotTooltip
|
|
1295
|
-
x={position.x}
|
|
1296
|
-
y={position.y}
|
|
1297
|
-
offset={{ x: 10, y: -10 }}
|
|
1298
|
-
bg_color={get_point_color(entry)}
|
|
1299
|
-
fixed
|
|
1300
|
-
style={tooltip_style}
|
|
1301
|
-
>
|
|
1302
|
-
<ConvexHullTooltip
|
|
1303
|
-
{entry}
|
|
1304
|
-
{polymorph_stats_map}
|
|
1305
|
-
highlight_style={entry_highlight}
|
|
1306
|
-
{tooltip}
|
|
1307
|
-
/>
|
|
1308
|
-
</PlotTooltip>
|
|
1309
|
-
{/if}
|
|
1310
|
-
|
|
1311
|
-
<!-- Copy-to-clipboard feedback (double-click on point) -->
|
|
1312
|
-
<ClickFeedback bind:visible={copy_feedback.visible} position={copy_feedback.position} />
|
|
1313
|
-
|
|
1314
|
-
<!-- Drag over overlay -->
|
|
1315
|
-
<DragOverlay visible={drag_over} />
|
|
1316
|
-
|
|
1317
|
-
{#if modal_open && selected_structure}
|
|
1318
|
-
<StructurePopup
|
|
1319
|
-
structure={selected_structure}
|
|
1320
|
-
place_right={modal_place_right}
|
|
1321
|
-
stats={{
|
|
1322
|
-
id: selected_entry?.entry_id,
|
|
1323
|
-
e_above_hull: selected_entry?.e_above_hull,
|
|
1324
|
-
e_form: selected_entry?.e_form_per_atom,
|
|
1325
|
-
}}
|
|
1326
|
-
onclose={close_structure_popup}
|
|
1327
|
-
/>
|
|
1328
|
-
{/if}
|
|
1329
848
|
</div>
|
|
1330
849
|
|
|
1331
850
|
<style>
|
|
@@ -1353,42 +872,4 @@
|
|
|
1353
872
|
canvas:active {
|
|
1354
873
|
cursor: grabbing;
|
|
1355
874
|
}
|
|
1356
|
-
.control-buttons {
|
|
1357
|
-
position: absolute;
|
|
1358
|
-
top: 1ex;
|
|
1359
|
-
right: 1ex;
|
|
1360
|
-
display: flex;
|
|
1361
|
-
gap: 8px;
|
|
1362
|
-
transition: opacity 0.2s ease-in-out;
|
|
1363
|
-
}
|
|
1364
|
-
.control-buttons.hover-visible {
|
|
1365
|
-
opacity: 0;
|
|
1366
|
-
pointer-events: none;
|
|
1367
|
-
}
|
|
1368
|
-
.convex-hull-4d:hover .control-buttons.hover-visible,
|
|
1369
|
-
.convex-hull-4d:focus-within .control-buttons.hover-visible {
|
|
1370
|
-
opacity: 1;
|
|
1371
|
-
pointer-events: auto;
|
|
1372
|
-
}
|
|
1373
|
-
.control-buttons.always-visible {
|
|
1374
|
-
opacity: 1;
|
|
1375
|
-
pointer-events: auto;
|
|
1376
|
-
}
|
|
1377
|
-
.control-buttons :global(.draggable-pane) {
|
|
1378
|
-
z-index: 1001 !important;
|
|
1379
|
-
}
|
|
1380
|
-
.control-buttons :global(button) {
|
|
1381
|
-
background: transparent;
|
|
1382
|
-
border: none;
|
|
1383
|
-
padding: 4px;
|
|
1384
|
-
cursor: pointer;
|
|
1385
|
-
border-radius: 3px;
|
|
1386
|
-
color: var(--text-color, currentColor);
|
|
1387
|
-
transition: background-color 0.2s;
|
|
1388
|
-
display: flex;
|
|
1389
|
-
font-size: clamp(0.85em, 2cqmin, 1.3em);
|
|
1390
|
-
}
|
|
1391
|
-
.control-buttons :global(button):hover {
|
|
1392
|
-
background-color: color-mix(in srgb, currentColor 8%, transparent);
|
|
1393
|
-
}
|
|
1394
875
|
</style>
|