matterviz 0.3.7 → 0.4.1
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/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +1 -1
- package/dist/api/optimade.js +32 -26
- package/dist/app.css +0 -3
- package/dist/brillouin/BrillouinZone.svelte +76 -148
- package/dist/brillouin/BrillouinZone.svelte.d.ts +6 -14
- package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +97 -205
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +4 -23
- package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
- 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 +89 -90
- 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 +14 -13
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +109 -203
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +180 -470
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/async-compute.svelte.js +3 -1
- package/dist/chempot-diagram/chempot-worker.js +2 -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 +4 -4
- package/dist/chempot-diagram/compute.js +20 -20
- 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.js +8 -7
- package/dist/composition/FormulaFilter.svelte +18 -11
- package/dist/composition/PieChart.svelte +11 -10
- package/dist/composition/chem-sys.d.ts +8 -0
- package/dist/composition/chem-sys.js +86 -0
- package/dist/composition/format.js +7 -4
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/composition/parse.d.ts +0 -1
- package/dist/composition/parse.js +41 -31
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +8 -10
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +106 -185
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +179 -683
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +183 -687
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +88 -7
- 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 +36 -175
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- package/dist/convex-hull/GasPressureControls.svelte +4 -4
- package/dist/convex-hull/TemperatureSlider.svelte +2 -2
- 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 +278 -0
- package/dist/convex-hull/demo-temperature.d.ts +1 -1
- package/dist/convex-hull/demo-temperature.js +20 -22
- package/dist/convex-hull/gas-thermodynamics.d.ts +2 -2
- package/dist/convex-hull/gas-thermodynamics.js +22 -30
- package/dist/convex-hull/helpers.d.ts +42 -7
- package/dist/convex-hull/helpers.js +171 -78
- 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 +10 -8
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +136 -960
- package/dist/convex-hull/types.d.ts +13 -5
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +27 -34
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/element/BohrAtom.svelte +2 -1
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +18 -0
- package/dist/feedback/DragOverlay.svelte +3 -1
- package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
- package/dist/feedback/StatusMessage.svelte +13 -3
- package/dist/fermi-surface/FermiSlice.svelte +13 -5
- package/dist/fermi-surface/FermiSurface.svelte +78 -151
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
- package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -221
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
- package/dist/fermi-surface/compute.js +67 -66
- package/dist/fermi-surface/export.js +6 -16
- 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 +71 -79
- package/dist/fermi-surface/types.d.ts +3 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +69 -52
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +3 -2
- package/dist/heatmap-matrix/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +166 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.js +5 -4
- package/dist/io/export.d.ts +9 -5
- package/dist/io/export.js +77 -51
- package/dist/io/fetch.d.ts +2 -1
- package/dist/io/fetch.js +5 -1
- package/dist/io/file-drop.d.ts +8 -1
- package/dist/io/file-drop.js +48 -36
- package/dist/io/index.d.ts +2 -0
- package/dist/io/index.js +10 -0
- package/dist/io/types.d.ts +13 -0
- package/dist/io/url-drop.js +64 -33
- package/dist/isosurface/parse.js +52 -51
- package/dist/isosurface/slice.js +5 -4
- package/dist/isosurface/types.js +1 -1
- package/dist/keyboard.d.ts +3 -0
- package/dist/keyboard.js +23 -0
- package/dist/labels.d.ts +1 -1
- package/dist/labels.js +9 -8
- package/dist/layout/FullscreenButton.svelte +33 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +8 -14
- package/dist/layout/PropertyFilter.svelte +3 -2
- package/dist/layout/SettingsSection.svelte +1 -1
- package/dist/layout/ViewerChrome.svelte +116 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +37 -0
- package/dist/layout/index.d.ts +3 -0
- package/dist/layout/index.js +3 -0
- package/dist/layout/json-tree/JsonNode.svelte +1 -1
- package/dist/layout/json-tree/JsonTree.svelte +2 -2
- package/dist/layout/json-tree/utils.js +5 -4
- package/dist/marching-cubes.js +8 -13
- package/dist/math.d.ts +12 -4
- package/dist/math.js +42 -30
- package/dist/overlays/DraggablePane.svelte +4 -4
- package/dist/overlays/index.d.ts +4 -0
- package/dist/periodic-table/PeriodicTable.svelte +27 -15
- package/dist/periodic-table/PropertySelect.svelte +1 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +9 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
- 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 +47 -132
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
- package/dist/phase-diagram/build-diagram.js +2 -2
- package/dist/phase-diagram/colors.js +1 -1
- package/dist/phase-diagram/parse.d.ts +2 -1
- package/dist/phase-diagram/parse.js +6 -5
- package/dist/phase-diagram/types.d.ts +1 -1
- package/dist/phase-diagram/utils.d.ts +3 -3
- package/dist/phase-diagram/utils.js +8 -12
- package/dist/plot/{BarPlot.svelte → bar/BarPlot.svelte} +246 -841
- package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +8 -16
- package/dist/plot/{BarPlotControls.svelte → bar/BarPlotControls.svelte} +6 -5
- package/dist/plot/{BarPlotControls.svelte.d.ts → bar/BarPlotControls.svelte.d.ts} +3 -3
- package/dist/plot/{SpacegroupBarPlot.svelte → bar/SpacegroupBarPlot.svelte} +8 -7
- package/dist/plot/{SpacegroupBarPlot.svelte.d.ts → bar/SpacegroupBarPlot.svelte.d.ts} +1 -1
- package/dist/plot/bar/data.d.ts +40 -0
- package/dist/plot/bar/data.js +154 -0
- package/dist/plot/bar/geometry.d.ts +39 -0
- package/dist/plot/bar/geometry.js +60 -0
- package/dist/plot/bar/index.d.ts +3 -0
- package/dist/plot/bar/index.js +3 -0
- package/dist/plot/box/BoxPlot.svelte +1292 -0
- package/dist/plot/box/BoxPlot.svelte.d.ts +95 -0
- package/dist/plot/box/BoxPlotControls.svelte +109 -0
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +19 -0
- package/dist/plot/box/Violin.svelte +14 -0
- package/dist/plot/box/Violin.svelte.d.ts +70 -0
- package/dist/plot/box/box-plot.d.ts +56 -0
- package/dist/plot/box/box-plot.js +129 -0
- package/dist/plot/box/index.d.ts +5 -0
- package/dist/plot/box/index.js +5 -0
- package/dist/plot/box/kde.d.ts +17 -0
- package/dist/plot/box/kde.js +160 -0
- package/dist/plot/box/quantile.d.ts +3 -0
- package/dist/plot/box/quantile.js +53 -0
- package/dist/plot/{auto-place.d.ts → core/auto-place.d.ts} +1 -1
- package/dist/plot/{auto-place.js → core/auto-place.js} +6 -3
- package/dist/plot/core/axis-utils.d.ts +46 -0
- package/dist/plot/core/axis-utils.js +110 -0
- package/dist/plot/{AxisLabel.svelte → core/components/AxisLabel.svelte} +2 -2
- package/dist/plot/{AxisLabel.svelte.d.ts → core/components/AxisLabel.svelte.d.ts} +1 -1
- package/dist/plot/{ColorBar.svelte → core/components/ColorBar.svelte} +41 -38
- package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +7 -6
- package/dist/plot/{ColorScaleSelect.svelte → core/components/ColorScaleSelect.svelte} +4 -3
- package/dist/plot/{ColorScaleSelect.svelte.d.ts → core/components/ColorScaleSelect.svelte.d.ts} +2 -2
- package/dist/plot/core/components/ControlPane.svelte +46 -0
- package/dist/plot/core/components/ControlPane.svelte.d.ts +13 -0
- package/dist/plot/{FillArea.svelte → core/components/FillArea.svelte} +17 -6
- package/dist/plot/{FillArea.svelte.d.ts → core/components/FillArea.svelte.d.ts} +1 -1
- package/dist/plot/{InteractiveAxisLabel.svelte → core/components/InteractiveAxisLabel.svelte} +3 -3
- package/dist/plot/{InteractiveAxisLabel.svelte.d.ts → core/components/InteractiveAxisLabel.svelte.d.ts} +2 -2
- package/dist/plot/{Line.svelte → core/components/Line.svelte} +33 -15
- package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +3 -2
- package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +9 -6
- package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +5 -3
- package/dist/plot/{PlotControls.svelte → core/components/PlotControls.svelte} +17 -29
- package/dist/plot/core/components/PlotControls.svelte.d.ts +4 -0
- package/dist/plot/{PlotLegend.svelte → core/components/PlotLegend.svelte} +21 -10
- package/dist/plot/{PlotLegend.svelte.d.ts → core/components/PlotLegend.svelte.d.ts} +3 -2
- package/dist/plot/{PlotTooltip.svelte → core/components/PlotTooltip.svelte} +17 -1
- package/dist/plot/{PlotTooltip.svelte.d.ts → core/components/PlotTooltip.svelte.d.ts} +8 -0
- package/dist/plot/{PortalSelect.svelte → core/components/PortalSelect.svelte} +11 -7
- package/dist/plot/{ReferenceLine.svelte → core/components/ReferenceLine.svelte} +3 -3
- package/dist/plot/{ReferenceLine.svelte.d.ts → core/components/ReferenceLine.svelte.d.ts} +1 -1
- package/dist/plot/{ReferenceLine3D.svelte → core/components/ReferenceLine3D.svelte} +5 -5
- package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +5 -5
- package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +8 -8
- package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +5 -5
- package/dist/plot/{ZeroLines.svelte → core/components/ZeroLines.svelte} +3 -3
- package/dist/plot/{ZeroLines.svelte.d.ts → core/components/ZeroLines.svelte.d.ts} +3 -3
- package/dist/plot/{ZoomRect.svelte → core/components/ZoomRect.svelte} +1 -1
- package/dist/plot/{ZoomRect.svelte.d.ts → core/components/ZoomRect.svelte.d.ts} +1 -1
- package/dist/plot/core/components/index.d.ts +17 -0
- package/dist/plot/core/components/index.js +17 -0
- package/dist/plot/{data-cleaning.d.ts → core/data-cleaning.d.ts} +71 -1
- package/dist/plot/{data-cleaning.js → core/data-cleaning.js} +21 -23
- package/dist/plot/{data-transform.d.ts → core/data-transform.d.ts} +2 -2
- package/dist/plot/{data-transform.js → core/data-transform.js} +3 -3
- package/dist/plot/core/fill-utils.d.ts +34 -0
- package/dist/plot/core/fill-utils.js +391 -0
- package/dist/plot/core/index.d.ts +10 -0
- package/dist/plot/core/index.js +11 -0
- package/dist/plot/core/interactions.d.ts +39 -0
- package/dist/plot/core/interactions.js +209 -0
- package/dist/plot/{layout.d.ts → core/layout.d.ts} +1 -0
- package/dist/plot/{layout.js → core/layout.js} +16 -8
- 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/{reference-line.d.ts → core/reference-line.d.ts} +11 -11
- package/dist/plot/{reference-line.js → core/reference-line.js} +29 -42
- package/dist/plot/core/scales.d.ts +40 -0
- package/dist/plot/{scales.js → core/scales.js} +94 -93
- package/dist/plot/core/svg.d.ts +3 -0
- package/dist/plot/core/svg.js +41 -0
- package/dist/plot/{types.d.ts → core/types.d.ts} +36 -85
- package/dist/plot/{types.js → core/types.js} +1 -1
- package/dist/plot/{utils → core/utils}/label-placement.d.ts +3 -3
- package/dist/plot/{utils → core/utils}/label-placement.js +3 -3
- package/dist/plot/core/utils/series-visibility.d.ts +26 -0
- package/dist/plot/{utils → core/utils}/series-visibility.js +29 -2
- package/dist/plot/core/utils.d.ts +12 -0
- package/dist/plot/core/utils.js +27 -0
- package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +174 -551
- package/dist/plot/{Histogram.svelte.d.ts → histogram/Histogram.svelte.d.ts} +2 -2
- package/dist/plot/{HistogramControls.svelte → histogram/HistogramControls.svelte} +6 -6
- package/dist/plot/{HistogramControls.svelte.d.ts → histogram/HistogramControls.svelte.d.ts} +4 -4
- package/dist/plot/histogram/index.d.ts +2 -0
- package/dist/plot/histogram/index.js +2 -0
- package/dist/plot/index.d.ts +8 -41
- package/dist/plot/index.js +10 -39
- package/dist/plot/sankey/Sankey.svelte +697 -0
- package/dist/plot/sankey/Sankey.svelte.d.ts +74 -0
- package/dist/plot/sankey/SankeyControls.svelte +98 -0
- package/dist/plot/sankey/SankeyControls.svelte.d.ts +19 -0
- package/dist/plot/sankey/index.d.ts +4 -0
- package/dist/plot/sankey/index.js +3 -0
- package/dist/plot/sankey/sankey-types.d.ts +42 -0
- package/dist/plot/sankey/sankey-types.js +4 -0
- package/dist/plot/sankey/sankey.d.ts +52 -0
- package/dist/plot/sankey/sankey.js +189 -0
- package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +64 -64
- package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +6 -6
- package/dist/plot/{ElementScatter.svelte → scatter/ElementScatter.svelte} +6 -6
- package/dist/plot/{ElementScatter.svelte.d.ts → scatter/ElementScatter.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPlot.svelte → scatter/ScatterPlot.svelte} +297 -1008
- package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +10 -18
- package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
- package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPoint.svelte → scatter/ScatterPoint.svelte} +7 -7
- package/dist/plot/{ScatterPoint.svelte.d.ts → scatter/ScatterPoint.svelte.d.ts} +3 -3
- package/dist/plot/{adaptive-density.d.ts → scatter/adaptive-density.d.ts} +14 -4
- package/dist/plot/{adaptive-density.js → scatter/adaptive-density.js} +46 -20
- package/dist/plot/{binned-scatter-types.d.ts → scatter/binned-scatter-types.d.ts} +5 -12
- package/dist/plot/scatter/index.d.ts +7 -0
- package/dist/plot/scatter/index.js +5 -0
- package/dist/plot/scatter/scatter-data.d.ts +19 -0
- package/dist/plot/scatter/scatter-data.js +212 -0
- package/dist/plot/{ScatterPlot3D.svelte → scatter-3d/ScatterPlot3D.svelte} +25 -34
- package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +9 -17
- package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +14 -14
- package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +6 -6
- package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +129 -128
- package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +6 -15
- package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +7 -6
- package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +5 -4
- package/dist/plot/scatter-3d/index.d.ts +4 -0
- package/dist/plot/scatter-3d/index.js +4 -0
- package/dist/plot/sunburst/Sunburst.svelte +1041 -0
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +97 -0
- package/dist/plot/sunburst/SunburstControls.svelte +200 -0
- package/dist/plot/sunburst/SunburstControls.svelte.d.ts +26 -0
- package/dist/plot/sunburst/index.d.ts +4 -0
- package/dist/plot/sunburst/index.js +4 -0
- package/dist/plot/sunburst/render.d.ts +34 -0
- package/dist/plot/sunburst/render.js +122 -0
- package/dist/plot/sunburst/sunburst.d.ts +62 -0
- package/dist/plot/sunburst/sunburst.js +269 -0
- package/dist/rdf/RdfPlot.svelte +2 -1
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +11 -24
- 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 +14 -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 +79 -3
- package/dist/settings.js +321 -1
- package/dist/spectral/Bands.svelte +47 -36
- package/dist/spectral/Bands.svelte.d.ts +6 -6
- package/dist/spectral/BandsAndDos.svelte +23 -25
- package/dist/spectral/BrillouinBandsDos.svelte +42 -30
- package/dist/spectral/Dos.svelte +15 -23
- package/dist/spectral/Dos.svelte.d.ts +4 -3
- package/dist/spectral/helpers.d.ts +8 -6
- package/dist/spectral/helpers.js +137 -65
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +0 -6
- package/dist/structure/Arrow.svelte +2 -4
- package/dist/structure/AtomLegend.svelte +8 -9
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CanvasTooltip.svelte +1 -0
- package/dist/structure/CellSelect.svelte +12 -5
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- package/dist/structure/Cylinder.svelte +12 -8
- package/dist/structure/Cylinder.svelte.d.ts +4 -1
- package/dist/structure/Lattice.svelte +2 -2
- package/dist/structure/Structure.svelte +365 -423
- package/dist/structure/Structure.svelte.d.ts +5 -15
- package/dist/structure/StructureControls.svelte +217 -2
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +54 -156
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +10 -9
- package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
- package/dist/structure/StructureScene.svelte +376 -208
- package/dist/structure/StructureScene.svelte.d.ts +22 -20
- package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
- package/dist/structure/{label-placement.js → atom-label-placement.js} +15 -5
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +17 -22
- package/dist/structure/bond-order-perception.js +3 -5
- package/dist/structure/bonding.d.ts +4 -0
- package/dist/structure/bonding.js +134 -63
- package/dist/structure/export.d.ts +24 -4
- package/dist/structure/export.js +89 -143
- package/dist/structure/index.d.ts +4 -4
- package/dist/structure/index.js +3 -3
- package/dist/structure/measure.d.ts +3 -2
- package/dist/structure/measure.js +6 -5
- package/dist/structure/parse.d.ts +3 -2
- package/dist/structure/parse.js +419 -438
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +1 -1
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +190 -13
- package/dist/structure/polyhedra.d.ts +41 -0
- package/dist/structure/polyhedra.js +602 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.js +3 -2
- 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 +354 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +113 -8
- package/dist/symmetry/WyckoffTable.svelte +68 -7
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +7 -14
- package/dist/symmetry/index.d.ts +14 -4
- package/dist/symmetry/index.js +291 -72
- package/dist/symmetry/spacegroups.d.ts +12 -1
- package/dist/symmetry/spacegroups.js +63 -14
- 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 +66 -25
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/index.d.ts +1 -3
- package/dist/table/index.js +1 -1
- package/dist/theme/index.js +8 -8
- package/dist/tooltip/KCoords.svelte +45 -0
- package/dist/tooltip/KCoords.svelte.d.ts +8 -0
- package/dist/tooltip/index.d.ts +1 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/trajectory/Trajectory.svelte +123 -100
- package/dist/trajectory/Trajectory.svelte.d.ts +11 -22
- package/dist/trajectory/TrajectoryExportPane.svelte +17 -25
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +5 -3
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +17 -37
- package/dist/trajectory/format-detect.d.ts +1 -1
- package/dist/trajectory/format-detect.js +27 -19
- package/dist/trajectory/frame-reader.d.ts +0 -1
- package/dist/trajectory/frame-reader.js +63 -162
- package/dist/trajectory/helpers.d.ts +10 -2
- package/dist/trajectory/helpers.js +56 -36
- package/dist/trajectory/index.js +1 -1
- 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/hdf5.js +1 -1
- package/dist/trajectory/parse/index.d.ts +1 -1
- package/dist/trajectory/parse/index.js +65 -105
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +8 -6
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +38 -18
- package/dist/trajectory/parse/xyz.d.ts +13 -1
- package/dist/trajectory/parse/xyz.js +102 -94
- package/dist/trajectory/plotting.d.ts +1 -2
- package/dist/trajectory/plotting.js +16 -113
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +7 -5
- package/dist/xrd/XrdPlot.svelte +16 -30
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/calc-xrd.js +18 -20
- package/dist/xrd/index.d.ts +2 -2
- package/dist/xrd/parse.js +2 -2
- package/package.json +43 -26
- 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/PlotControls.svelte.d.ts +0 -4
- package/dist/plot/axis-utils.d.ts +0 -19
- package/dist/plot/axis-utils.js +0 -78
- package/dist/plot/defaults.d.ts +0 -19
- package/dist/plot/defaults.js +0 -9
- package/dist/plot/fill-utils.d.ts +0 -46
- package/dist/plot/fill-utils.js +0 -322
- package/dist/plot/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/hover-lock.svelte.js +0 -46
- package/dist/plot/interactions.d.ts +0 -12
- package/dist/plot/interactions.js +0 -101
- package/dist/plot/scales.d.ts +0 -48
- package/dist/plot/svg.d.ts +0 -1
- package/dist/plot/svg.js +0 -11
- package/dist/plot/utils/series-visibility.d.ts +0 -15
- package/dist/plot/utils.d.ts +0 -1
- package/dist/plot/utils.js +0 -14
- /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
- /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
|
@@ -13,18 +13,12 @@
|
|
|
13
13
|
import type { FormulaLabelSegment } from '../composition/format'
|
|
14
14
|
import { normalize_show_controls } from '../controls'
|
|
15
15
|
import { sanitize_html } from '../sanitize'
|
|
16
|
-
import {
|
|
17
|
-
import Icon from '../Icon.svelte'
|
|
16
|
+
import { Spinner } from '../feedback'
|
|
18
17
|
import { format_num } from '../labels'
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from '../layout'
|
|
24
|
-
import { to_radians, type Point3D, type Vec3 } from '../math'
|
|
25
|
-
import { ColorBar, PlotTooltip } from '../plot'
|
|
26
|
-
import { centered_rect, pad_rect, rects_overlap, rect_within_rect } from '../plot/layout'
|
|
27
|
-
import type { Rect } from '../plot/layout'
|
|
18
|
+
import { to_radians, type Point3D, type Vec2, type Vec3 } from '../math'
|
|
19
|
+
import { ColorBar } from '../plot'
|
|
20
|
+
import { centered_rect, pad_rect, rects_overlap, rect_within_rect } from '../plot/core/layout'
|
|
21
|
+
import type { Rect } from '../plot/core/layout'
|
|
28
22
|
import { create_pulse_animation } from '../effects.svelte'
|
|
29
23
|
import { DEFAULTS } from '../settings'
|
|
30
24
|
import type { AnyStructure } from '../structure'
|
|
@@ -40,39 +34,41 @@
|
|
|
40
34
|
get_triangle_vertical_edges,
|
|
41
35
|
TRIANGLE_VERTICES,
|
|
42
36
|
} from './barycentric-coords'
|
|
43
|
-
import
|
|
44
|
-
import
|
|
45
|
-
import ConvexHullTooltip from './ConvexHullTooltip.svelte'
|
|
37
|
+
import { create_canvas_interactions } from './canvas-interactions.svelte'
|
|
38
|
+
import ConvexHullChrome from './ConvexHullChrome.svelte'
|
|
46
39
|
import GasPressureControls from './GasPressureControls.svelte'
|
|
47
40
|
import * as helpers from './helpers'
|
|
41
|
+
import { create_hull_data_pipeline } from './hull-state.svelte'
|
|
48
42
|
import type { BaseConvexHullProps, Hull3DProps } from './index'
|
|
49
43
|
import { CONVEX_HULL_STYLE, default_controls, default_hull_config } from './index'
|
|
50
|
-
import StructurePopup from './StructurePopup.svelte'
|
|
51
44
|
import TemperatureSlider from './TemperatureSlider.svelte'
|
|
52
45
|
import * as thermo from './thermodynamics'
|
|
53
46
|
import type {
|
|
54
47
|
ConvexHullEntry,
|
|
55
48
|
ConvexHullTriangle,
|
|
56
49
|
HighlightStyle,
|
|
57
|
-
HoverData3D,
|
|
58
50
|
HullFaceColorMode,
|
|
59
51
|
LabelPlacement,
|
|
60
52
|
} from './types'
|
|
61
53
|
import { compute_hull_stability } from './helpers'
|
|
54
|
+
import { MAGNETIC_ORDERING_CATEGORY } from './types'
|
|
62
55
|
|
|
63
56
|
let {
|
|
64
57
|
entries = [],
|
|
65
58
|
controls = {},
|
|
66
59
|
config = {},
|
|
60
|
+
show_controls,
|
|
67
61
|
on_point_click,
|
|
68
62
|
on_point_hover,
|
|
69
63
|
fullscreen = $bindable(DEFAULTS.convex_hull.ternary.fullscreen),
|
|
70
|
-
|
|
64
|
+
fullscreen_toggle = true,
|
|
71
65
|
enable_info_pane = true,
|
|
72
66
|
wrapper = $bindable(),
|
|
73
67
|
label_threshold = 50,
|
|
74
68
|
show_stable = $bindable(DEFAULTS.convex_hull.ternary.show_stable),
|
|
75
69
|
show_unstable = $bindable(DEFAULTS.convex_hull.ternary.show_unstable),
|
|
70
|
+
entry_category = MAGNETIC_ORDERING_CATEGORY,
|
|
71
|
+
hidden_categories = $bindable([]),
|
|
76
72
|
show_hull_faces = $bindable(DEFAULTS.convex_hull.ternary.show_hull_faces),
|
|
77
73
|
hull_face_opacity = $bindable(DEFAULTS.convex_hull.ternary.hull_face_opacity),
|
|
78
74
|
hull_face_color_mode = $bindable(
|
|
@@ -84,7 +80,7 @@
|
|
|
84
80
|
DEFAULTS.convex_hull.ternary.color_scale as D3InterpolateName,
|
|
85
81
|
),
|
|
86
82
|
info_pane_open = $bindable(DEFAULTS.convex_hull.ternary.info_pane_open),
|
|
87
|
-
|
|
83
|
+
controls_open = $bindable(DEFAULTS.convex_hull.ternary.legend_pane_open),
|
|
88
84
|
max_hull_dist_show_phases = $bindable(
|
|
89
85
|
DEFAULTS.convex_hull.ternary.max_hull_dist_show_phases,
|
|
90
86
|
),
|
|
@@ -119,7 +115,7 @@
|
|
|
119
115
|
} = $props()
|
|
120
116
|
|
|
121
117
|
const merged_controls = $derived({ ...default_controls, ...controls })
|
|
122
|
-
const controls_config = $derived(normalize_show_controls(
|
|
118
|
+
const controls_config = $derived(normalize_show_controls(show_controls))
|
|
123
119
|
const merged_config = $derived({
|
|
124
120
|
...default_hull_config,
|
|
125
121
|
...config,
|
|
@@ -127,89 +123,36 @@
|
|
|
127
123
|
margin: { t: 40, r: 40, b: 60, l: 60, ...config.margin },
|
|
128
124
|
})
|
|
129
125
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
// Gas-dependent chemical potential support (corrections based on T, P)
|
|
155
|
-
// Default to DEFAULT_GAS_TEMP (room temperature) when no temperature specified
|
|
156
|
-
const {
|
|
157
|
-
entries: gas_corrected_entries,
|
|
158
|
-
analysis: gas_analysis,
|
|
159
|
-
merged_config: merged_gas_config,
|
|
160
|
-
} = $derived(
|
|
161
|
-
helpers.get_gas_corrected_entries(
|
|
162
|
-
temp_filtered_entries,
|
|
163
|
-
gas_config,
|
|
164
|
-
gas_pressures,
|
|
165
|
-
temperature ?? helpers.DEFAULT_GAS_TEMP,
|
|
166
|
-
),
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
let { // Compute energy mode information
|
|
170
|
-
has_precomputed_e_form,
|
|
171
|
-
has_precomputed_hull,
|
|
172
|
-
can_compute_e_form,
|
|
173
|
-
can_compute_hull,
|
|
174
|
-
energy_mode,
|
|
175
|
-
unary_refs,
|
|
176
|
-
} = $derived(
|
|
177
|
-
helpers.compute_energy_mode_info(
|
|
178
|
-
gas_corrected_entries,
|
|
179
|
-
thermo.find_lowest_energy_unary_refs,
|
|
180
|
-
energy_source_mode,
|
|
181
|
-
),
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
const effective_entries = $derived(
|
|
185
|
-
helpers.get_effective_entries(
|
|
186
|
-
gas_corrected_entries,
|
|
187
|
-
energy_mode,
|
|
188
|
-
unary_refs,
|
|
189
|
-
thermo.compute_e_form_per_atom,
|
|
190
|
-
),
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
// Process convex hull data with unified PhaseData interface using effective entries
|
|
194
|
-
const pd_data = $derived(thermo.process_hull_entries(effective_entries))
|
|
195
|
-
|
|
196
|
-
// Pre-compute polymorph stats once for O(1) tooltip lookups
|
|
197
|
-
const polymorph_stats_map = $derived(
|
|
198
|
-
helpers.compute_all_polymorph_stats(effective_entries),
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
const elements = $derived.by(() => {
|
|
202
|
-
if (pd_data.elements.length > 3) {
|
|
203
|
-
console.error(
|
|
204
|
-
`ConvexHull3D: Dataset contains ${pd_data.elements.length} elements, but ternary diagrams require exactly 3. Found: [${
|
|
205
|
-
pd_data.elements.join(`, `)
|
|
206
|
-
}]`,
|
|
207
|
-
)
|
|
208
|
-
return []
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return pd_data.elements
|
|
126
|
+
// Shared reactive data pipeline (temperature → gas → energy mode → hull data → threshold)
|
|
127
|
+
// Explicit generic breaks the circular type inference through the all_enriched_entries thunk
|
|
128
|
+
const hull_data = create_hull_data_pipeline<ConvexHullEntry>({
|
|
129
|
+
dim: 3,
|
|
130
|
+
entries: () => entries,
|
|
131
|
+
temperature: () => temperature,
|
|
132
|
+
interpolate_temperature: () => interpolate_temperature,
|
|
133
|
+
max_interpolation_gap: () => max_interpolation_gap,
|
|
134
|
+
gas_config: () => gas_config,
|
|
135
|
+
gas_pressures: () => gas_pressures,
|
|
136
|
+
energy_source_mode: () => energy_source_mode,
|
|
137
|
+
all_enriched_entries: () => all_enriched_entries,
|
|
138
|
+
max_hull_dist_show_phases: () => max_hull_dist_show_phases,
|
|
139
|
+
show_stable: () => show_stable,
|
|
140
|
+
show_unstable: () => show_unstable,
|
|
141
|
+
entry_category: () => entry_category,
|
|
142
|
+
hidden_categories: () => hidden_categories,
|
|
143
|
+
keep_plot_entry: (entry, max_dist) => (entry.e_above_hull ?? 0) <= max_dist,
|
|
144
|
+
set_temperature: (next_temp) => temperature = next_temp,
|
|
145
|
+
set_max_hull_dist_show_phases: (value) => max_hull_dist_show_phases = value,
|
|
146
|
+
set_stable_entries: (value) => stable_entries = value,
|
|
147
|
+
set_unstable_entries: (value) => unstable_entries = value,
|
|
212
148
|
})
|
|
149
|
+
const has_temp_data = $derived(hull_data.has_temp_data)
|
|
150
|
+
const gas_analysis = $derived(hull_data.gas_analysis)
|
|
151
|
+
const merged_gas_config = $derived(hull_data.merged_gas_config)
|
|
152
|
+
const pd_data = $derived(hull_data.pd_data)
|
|
153
|
+
const elements = $derived(hull_data.elements)
|
|
154
|
+
const plot_entries = $derived(hull_data.plot_entries)
|
|
155
|
+
const visible_entries = $derived(hull_data.visible_entries)
|
|
213
156
|
|
|
214
157
|
// 1) Raw 3D coordinates (formation-energy z), independent of hull state
|
|
215
158
|
const coords_entries = $derived.by(() => {
|
|
@@ -250,7 +193,7 @@
|
|
|
250
193
|
// Enrich coords with e_above_hull from cached hull model (before filtering)
|
|
251
194
|
const all_enriched_entries = $derived.by(() => {
|
|
252
195
|
if (coords_entries.length === 0) return []
|
|
253
|
-
if (energy_mode !== `on-the-fly`) return coords_entries
|
|
196
|
+
if (hull_data.energy_mode !== `on-the-fly`) return coords_entries
|
|
254
197
|
const pts = coords_entries.map(({ x, y, z }) => ({ x, y, z }))
|
|
255
198
|
const raw_dists = thermo.compute_e_above_hull_for_points(pts, hull_model)
|
|
256
199
|
return coords_entries.map((entry, idx) => ({
|
|
@@ -258,51 +201,10 @@
|
|
|
258
201
|
}))
|
|
259
202
|
})
|
|
260
203
|
|
|
261
|
-
// Auto threshold: show all for few entries, use default for many, interpolate between
|
|
262
|
-
const max_hull_dist_in_data = $derived(
|
|
263
|
-
helpers.calc_max_hull_dist_in_data(all_enriched_entries),
|
|
264
|
-
)
|
|
265
|
-
const auto_default_threshold = $derived(helpers.compute_auto_hull_dist_threshold(
|
|
266
|
-
all_enriched_entries.length,
|
|
267
|
-
max_hull_dist_in_data,
|
|
268
|
-
DEFAULTS.convex_hull.ternary.max_hull_dist_show_phases,
|
|
269
|
-
))
|
|
270
|
-
|
|
271
|
-
const next_auto_threshold = helpers.auto_threshold_reset(
|
|
272
|
-
DEFAULTS.convex_hull.ternary.max_hull_dist_show_phases,
|
|
273
|
-
)
|
|
274
|
-
$effect(() => {
|
|
275
|
-
max_hull_dist_show_phases = next_auto_threshold(
|
|
276
|
-
entries,
|
|
277
|
-
max_hull_dist_show_phases,
|
|
278
|
-
auto_default_threshold,
|
|
279
|
-
) ?? max_hull_dist_show_phases
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
// Filter by threshold; visibility is a view predicate, not entry state.
|
|
283
|
-
const plot_entries = $derived(
|
|
284
|
-
all_enriched_entries.filter((entry) =>
|
|
285
|
-
(entry.e_above_hull ?? 0) <= max_hull_dist_show_phases
|
|
286
|
-
),
|
|
287
|
-
)
|
|
288
|
-
const visible_entries = $derived(helpers.visible_entries(
|
|
289
|
-
plot_entries,
|
|
290
|
-
show_stable,
|
|
291
|
-
show_unstable,
|
|
292
|
-
))
|
|
293
|
-
|
|
294
|
-
$effect(() => {
|
|
295
|
-
stable_entries = plot_entries.filter(helpers.entry_is_stable)
|
|
296
|
-
unstable_entries = plot_entries.filter(helpers.entry_is_unstable)
|
|
297
|
-
})
|
|
298
|
-
|
|
299
204
|
// Canvas rendering
|
|
300
205
|
let canvas: HTMLCanvasElement | undefined = undefined
|
|
301
206
|
let ctx: CanvasRenderingContext2D | null = null
|
|
302
207
|
|
|
303
|
-
// Performance optimization
|
|
304
|
-
let frame_id = 0
|
|
305
|
-
|
|
306
208
|
const camera_default = {
|
|
307
209
|
elevation: DEFAULTS.convex_hull.ternary.camera_elevation,
|
|
308
210
|
azimuth: DEFAULTS.convex_hull.ternary.camera_azimuth,
|
|
@@ -418,43 +320,64 @@
|
|
|
418
320
|
}
|
|
419
321
|
})
|
|
420
322
|
|
|
421
|
-
//
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
323
|
+
// Shared canvas-interaction scaffold (mouse/keyboard handlers, hover/drag/popup
|
|
324
|
+
// state, canvas sizing, render scheduler). Rotation math + keydown actions stay local.
|
|
325
|
+
const interactions = create_canvas_interactions({
|
|
326
|
+
wheel_clamp: [0.5, 10],
|
|
327
|
+
fullscreen_bg_var: `--hull-3d-bg-fullscreen`,
|
|
328
|
+
canvas: () => canvas,
|
|
329
|
+
wrapper: () => wrapper,
|
|
330
|
+
ctx: () => ctx,
|
|
331
|
+
set_ctx: (context) => ctx = context,
|
|
332
|
+
set_canvas_dims: (dims) => canvas_dims = dims,
|
|
333
|
+
visible_entries: () => visible_entries,
|
|
334
|
+
plot_entries: () => plot_entries,
|
|
335
|
+
selected_entry: () => selected_entry,
|
|
336
|
+
set_selected_entry: (entry) => selected_entry = entry,
|
|
337
|
+
fullscreen: () => fullscreen,
|
|
338
|
+
enable_click_selection: () => enable_click_selection,
|
|
339
|
+
enable_structure_preview: () => enable_structure_preview,
|
|
340
|
+
on_point_click: () => on_point_click,
|
|
341
|
+
on_point_hover: () => on_point_hover,
|
|
342
|
+
on_file_drop: () => on_file_drop,
|
|
343
|
+
entry_category: () => entry_category,
|
|
344
|
+
zoom: () => camera.zoom,
|
|
345
|
+
set_zoom: (zoom) => camera.zoom = zoom,
|
|
346
|
+
project_point: project_3d_point,
|
|
347
|
+
extract_structure: extract_structure_from_entry,
|
|
348
|
+
render_frame,
|
|
349
|
+
on_drag: (dx, dy, panning) => {
|
|
350
|
+
if (panning) {
|
|
351
|
+
camera.center_x += dx
|
|
352
|
+
camera.center_y += dy
|
|
353
|
+
} else {
|
|
354
|
+
// Horizontal drag -> azimuth rotation around z-axis
|
|
355
|
+
camera.azimuth += dx * 0.3 // Positive dx (drag right) rotates clockwise
|
|
356
|
+
// Vertical drag -> elevation angle (full range)
|
|
357
|
+
camera.elevation -= dy * 0.3 // Positive dy (drag down) tilts view down
|
|
455
358
|
}
|
|
456
|
-
}
|
|
359
|
+
},
|
|
360
|
+
// Reset pan center when entering/exiting fullscreen
|
|
361
|
+
on_fullscreen_change: () => {
|
|
362
|
+
camera.center_x = 0
|
|
363
|
+
camera.center_y = -50
|
|
364
|
+
},
|
|
365
|
+
actions: () => ({
|
|
366
|
+
r: reset_camera,
|
|
367
|
+
t: () => {
|
|
368
|
+
camera.elevation = 0
|
|
369
|
+
camera.azimuth = 0
|
|
370
|
+
center_camera(0)
|
|
371
|
+
},
|
|
372
|
+
b: () => color_mode = color_mode === `stability` ? `energy` : `stability`,
|
|
373
|
+
s: () => show_stable = !show_stable,
|
|
374
|
+
u: () => show_unstable = !show_unstable,
|
|
375
|
+
h: () => show_hull_faces = !show_hull_faces,
|
|
376
|
+
l: () => show_stable_labels = !show_stable_labels,
|
|
377
|
+
}),
|
|
457
378
|
})
|
|
379
|
+
const { render_once } = interactions
|
|
380
|
+
const sorted_points_cache = $derived(interactions.sorted_points_cache)
|
|
458
381
|
|
|
459
382
|
// Hull face color (customizable via controls)
|
|
460
383
|
let hull_face_color = $state(`#4caf50`)
|
|
@@ -478,17 +401,14 @@
|
|
|
478
401
|
// Re-render when important state changes
|
|
479
402
|
$effect(() => {
|
|
480
403
|
// oxfmt-ignore
|
|
481
|
-
void [show_hull_faces, color_mode, color_scale, show_stable_labels, show_unstable_labels, max_hull_dist_show_labels, camera.elevation, camera.azimuth, camera.zoom, camera.center_x, camera.center_y, plot_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, highlighted_entries, text_color] // track reactively
|
|
404
|
+
void [show_hull_faces, color_mode, color_scale, show_stable_labels, show_unstable_labels, max_hull_dist_show_labels, camera.elevation, camera.azimuth, camera.zoom, camera.center_x, camera.center_y, plot_entries, visible_entries, hull_face_color, hull_face_opacity, hull_face_color_mode, element_colors, highlighted_entries, text_color] // track reactively
|
|
482
405
|
|
|
483
406
|
render_once()
|
|
484
407
|
})
|
|
485
408
|
|
|
486
|
-
//
|
|
487
|
-
function extract_structure_from_entry(
|
|
488
|
-
|
|
489
|
-
): AnyStructure | null {
|
|
490
|
-
const orig_entry = entries.find((ent) => ent.entry_id === entry.entry_id)
|
|
491
|
-
return orig_entry?.structure as AnyStructure || null
|
|
409
|
+
// function (not const) so the create_canvas_interactions options above can reference it
|
|
410
|
+
function extract_structure_from_entry(entry: ConvexHullEntry): AnyStructure | null {
|
|
411
|
+
return helpers.extract_structure_from_entry(entries, entry)
|
|
492
412
|
}
|
|
493
413
|
|
|
494
414
|
const reset_camera = () => Object.assign(camera, camera_default)
|
|
@@ -496,16 +416,17 @@
|
|
|
496
416
|
reset_camera()
|
|
497
417
|
fullscreen = DEFAULTS.convex_hull.ternary.fullscreen
|
|
498
418
|
info_pane_open = DEFAULTS.convex_hull.ternary.info_pane_open
|
|
499
|
-
|
|
419
|
+
controls_open = DEFAULTS.convex_hull.ternary.legend_pane_open
|
|
500
420
|
color_mode = DEFAULTS.convex_hull.ternary.color_mode
|
|
501
421
|
color_scale = DEFAULTS.convex_hull.ternary.color_scale as D3InterpolateName
|
|
502
422
|
show_stable = DEFAULTS.convex_hull.ternary.show_stable
|
|
503
423
|
show_unstable = DEFAULTS.convex_hull.ternary.show_unstable
|
|
424
|
+
hidden_categories = []
|
|
504
425
|
show_stable_labels = DEFAULTS.convex_hull.ternary.show_stable_labels
|
|
505
426
|
show_unstable_labels = DEFAULTS.convex_hull.ternary.show_unstable_labels
|
|
506
427
|
max_hull_dist_show_labels = DEFAULTS.convex_hull.ternary.max_hull_dist_show_labels
|
|
507
428
|
// Use auto-computed threshold based on entry count instead of static default
|
|
508
|
-
max_hull_dist_show_phases = auto_default_threshold
|
|
429
|
+
max_hull_dist_show_phases = hull_data.auto_default_threshold
|
|
509
430
|
show_hull_faces = DEFAULTS.convex_hull.ternary.show_hull_faces
|
|
510
431
|
hull_face_color = DEFAULTS.convex_hull.ternary.hull_face_color
|
|
511
432
|
hull_face_opacity = DEFAULTS.convex_hull.ternary.hull_face_opacity
|
|
@@ -513,75 +434,6 @@
|
|
|
513
434
|
.hull_face_color_mode as HullFaceColorMode
|
|
514
435
|
}
|
|
515
436
|
|
|
516
|
-
const handle_keydown = (event: KeyboardEvent) => {
|
|
517
|
-
const target = event.target
|
|
518
|
-
if (target instanceof HTMLElement && target.tagName.match(/INPUT|TEXTAREA/)) return
|
|
519
|
-
|
|
520
|
-
// Stop propagation if event came from canvas to prevent wrapper's handler
|
|
521
|
-
// from running again (both have onkeydown, causing duplicate handling)
|
|
522
|
-
if (target === canvas) {
|
|
523
|
-
event.stopPropagation()
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
if (event.key === `Escape` && modal_open) {
|
|
527
|
-
close_structure_popup()
|
|
528
|
-
return
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Handle Enter for keyboard accessibility - select hovered entry
|
|
532
|
-
if (event.key === `Enter`) {
|
|
533
|
-
const entry = hover_data?.entry
|
|
534
|
-
if (entry) {
|
|
535
|
-
on_point_click?.(entry)
|
|
536
|
-
if (enable_click_selection) {
|
|
537
|
-
selected_entry = entry
|
|
538
|
-
if (enable_structure_preview) {
|
|
539
|
-
const structure = extract_structure_from_entry(entry)
|
|
540
|
-
if (structure) {
|
|
541
|
-
selected_structure = structure
|
|
542
|
-
modal_place_right = helpers.calculate_modal_side(wrapper)
|
|
543
|
-
modal_open = true
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
} else if (modal_open) {
|
|
548
|
-
close_structure_popup()
|
|
549
|
-
}
|
|
550
|
-
return
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
const actions: Record<string, () => void> = {
|
|
554
|
-
r: reset_camera,
|
|
555
|
-
t: () => {
|
|
556
|
-
camera.elevation = 0
|
|
557
|
-
camera.azimuth = 0
|
|
558
|
-
center_camera(0)
|
|
559
|
-
},
|
|
560
|
-
b: () => color_mode = color_mode === `stability` ? `energy` : `stability`,
|
|
561
|
-
s: () => show_stable = !show_stable,
|
|
562
|
-
u: () => show_unstable = !show_unstable,
|
|
563
|
-
h: () => show_hull_faces = !show_hull_faces,
|
|
564
|
-
l: () => show_stable_labels = !show_stable_labels,
|
|
565
|
-
}
|
|
566
|
-
actions[event.key.toLowerCase()]?.()
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
async function handle_file_drop(event: DragEvent): Promise<void> {
|
|
570
|
-
drag_over = false
|
|
571
|
-
const data = await helpers.parse_hull_entries_from_drop(event)
|
|
572
|
-
if (data) on_file_drop?.(data)
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
async function copy_entry_data(
|
|
576
|
-
entry: ConvexHullEntry,
|
|
577
|
-
position: { x: number; y: number },
|
|
578
|
-
) {
|
|
579
|
-
await helpers.copy_entry_to_clipboard(entry, position, (visible, pos) => {
|
|
580
|
-
copy_feedback.visible = visible
|
|
581
|
-
copy_feedback.position = pos
|
|
582
|
-
})
|
|
583
|
-
}
|
|
584
|
-
|
|
585
437
|
const get_point_color = (entry: ConvexHullEntry): string =>
|
|
586
438
|
helpers.get_point_color_for_entry(
|
|
587
439
|
entry,
|
|
@@ -841,12 +693,14 @@
|
|
|
841
693
|
return energy_face_scale?.(avg_e_form - min_face_e_form) ?? hull_face_color
|
|
842
694
|
}
|
|
843
695
|
if (hull_face_color_mode === `dominant_element`) {
|
|
844
|
-
// Find element vertex closest to face centroid in 2D ternary space
|
|
696
|
+
// Find element vertex closest to face centroid in 2D ternary space (single-pass argmin)
|
|
845
697
|
const { x: cx, y: cy } = tri.centroid
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
698
|
+
let [closest_idx, min_dist] = [0, Infinity]
|
|
699
|
+
for (const [idx, [tx, ty]] of TRIANGLE_VERTICES.entries()) {
|
|
700
|
+
const dist = Math.hypot(cx - tx, cy - ty)
|
|
701
|
+
if (dist < min_dist) [closest_idx, min_dist] = [idx, dist]
|
|
702
|
+
}
|
|
703
|
+
const el = elements[closest_idx]
|
|
850
704
|
return element_colors[el] ?? `#888888`
|
|
851
705
|
}
|
|
852
706
|
if (hull_face_color_mode === `facet_index`) {
|
|
@@ -962,8 +816,8 @@
|
|
|
962
816
|
}
|
|
963
817
|
|
|
964
818
|
// Formation energy color bar helpers
|
|
965
|
-
const e_form_range = $derived.by(():
|
|
966
|
-
const min_fe = plot_entries.length ? energy_range.min : -1
|
|
819
|
+
const e_form_range = $derived.by((): Vec2 => {
|
|
820
|
+
const min_fe = plot_entries.length > 0 ? energy_range.min : -1
|
|
967
821
|
return [min_fe, 0]
|
|
968
822
|
})
|
|
969
823
|
|
|
@@ -980,59 +834,16 @@
|
|
|
980
834
|
|
|
981
835
|
function draw_data_points(): void {
|
|
982
836
|
if (!ctx || sorted_points_cache.length === 0) return
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
ctx.fillStyle = `rgba(0, 0, 0, 0.2)`
|
|
994
|
-
const shadow_path = helpers.create_marker_path(size * 0.8, marker)
|
|
995
|
-
ctx.save()
|
|
996
|
-
ctx.translate(projected.x + shadow_offset, projected.y + shadow_offset)
|
|
997
|
-
ctx.fill(shadow_path)
|
|
998
|
-
ctx.restore()
|
|
999
|
-
|
|
1000
|
-
// Highlights
|
|
1001
|
-
if (selected_entry && entry.entry_id === selected_entry.entry_id) {
|
|
1002
|
-
helpers.draw_selection_highlight(
|
|
1003
|
-
ctx,
|
|
1004
|
-
projected,
|
|
1005
|
-
size,
|
|
1006
|
-
canvas_dims.scale,
|
|
1007
|
-
pulse.time,
|
|
1008
|
-
pulse_opacity,
|
|
1009
|
-
)
|
|
1010
|
-
}
|
|
1011
|
-
if (is_entry_highlighted) {
|
|
1012
|
-
helpers.draw_highlight_effect(
|
|
1013
|
-
ctx,
|
|
1014
|
-
projected,
|
|
1015
|
-
size,
|
|
1016
|
-
canvas_dims.scale,
|
|
1017
|
-
pulse.time,
|
|
1018
|
-
merged_highlight_style,
|
|
1019
|
-
)
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
// Main point with marker symbol
|
|
1023
|
-
ctx.fillStyle =
|
|
1024
|
-
is_entry_highlighted && merged_highlight_style.effect === `color`
|
|
1025
|
-
? merged_highlight_style.color
|
|
1026
|
-
: color
|
|
1027
|
-
ctx.strokeStyle = is_stable ? `#ffffff` : `#000000`
|
|
1028
|
-
ctx.lineWidth = 0.5 * canvas_dims.scale
|
|
1029
|
-
const marker_path = helpers.create_marker_path(size, marker)
|
|
1030
|
-
ctx.save()
|
|
1031
|
-
ctx.translate(projected.x, projected.y)
|
|
1032
|
-
ctx.fill(marker_path)
|
|
1033
|
-
ctx.stroke(marker_path)
|
|
1034
|
-
ctx.restore()
|
|
1035
|
-
}
|
|
837
|
+
helpers.draw_hull_points(ctx, sorted_points_cache, {
|
|
838
|
+
scale: canvas_dims.scale,
|
|
839
|
+
shadow_factor: 0.1,
|
|
840
|
+
selected_entry,
|
|
841
|
+
is_highlighted,
|
|
842
|
+
get_point_color,
|
|
843
|
+
highlight_style: merged_highlight_style,
|
|
844
|
+
pulse_time: pulse.time,
|
|
845
|
+
pulse_opacity,
|
|
846
|
+
})
|
|
1036
847
|
}
|
|
1037
848
|
|
|
1038
849
|
const hull_label_font_size = 12
|
|
@@ -1216,180 +1027,11 @@
|
|
|
1216
1027
|
draw_element_labels()
|
|
1217
1028
|
}
|
|
1218
1029
|
|
|
1219
|
-
function handle_mouse_down(event: MouseEvent) {
|
|
1220
|
-
is_dragging = true
|
|
1221
|
-
drag_started = false
|
|
1222
|
-
hover_data = null
|
|
1223
|
-
on_point_hover?.(null)
|
|
1224
|
-
last_mouse = { x: event.clientX, y: event.clientY }
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
const handle_mouse_move = (event: MouseEvent) => {
|
|
1228
|
-
if (!is_dragging) return
|
|
1229
|
-
const [dx, dy] = [event.clientX - last_mouse.x, event.clientY - last_mouse.y]
|
|
1230
|
-
|
|
1231
|
-
// Mark as drag if any movement occurred
|
|
1232
|
-
if (dx !== 0 || dy !== 0) drag_started = true
|
|
1233
|
-
|
|
1234
|
-
// With Cmd/Ctrl held: pan the view instead of rotating
|
|
1235
|
-
if (event.metaKey || event.ctrlKey) {
|
|
1236
|
-
camera.center_x += dx
|
|
1237
|
-
camera.center_y += dy
|
|
1238
|
-
} else {
|
|
1239
|
-
// Horizontal drag -> azimuth rotation around z-axis
|
|
1240
|
-
camera.azimuth += dx * 0.3 // Positive dx (drag right) rotates clockwise
|
|
1241
|
-
|
|
1242
|
-
// Vertical drag -> elevation angle (full range)
|
|
1243
|
-
camera.elevation -= dy * 0.3 // Positive dy (drag down) tilts view down
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
last_mouse = { x: event.clientX, y: event.clientY }
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
const handle_wheel = (event: WheelEvent) => {
|
|
1250
|
-
event.preventDefault()
|
|
1251
|
-
camera.zoom = Math.max(
|
|
1252
|
-
0.5,
|
|
1253
|
-
Math.min(10, camera.zoom * (event.deltaY > 0 ? 0.98 : 1.02)),
|
|
1254
|
-
)
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
const handle_hover = (event: MouseEvent) => {
|
|
1258
|
-
if (is_dragging) return
|
|
1259
|
-
const entry = find_entry_at_mouse(event)
|
|
1260
|
-
hover_data = entry
|
|
1261
|
-
? { entry, position: { x: event.clientX, y: event.clientY } }
|
|
1262
|
-
: null
|
|
1263
|
-
on_point_hover?.(hover_data)
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
const find_entry_at_mouse = (event: MouseEvent): ConvexHullEntry | null =>
|
|
1267
|
-
helpers.find_hull_entry_at_mouse(
|
|
1268
|
-
canvas,
|
|
1269
|
-
event,
|
|
1270
|
-
visible_entries,
|
|
1271
|
-
(x: number, y: number, z: number) => {
|
|
1272
|
-
const pt = project_3d_point(x, y, z)
|
|
1273
|
-
return { x: pt.x, y: pt.y }
|
|
1274
|
-
},
|
|
1275
|
-
)
|
|
1276
|
-
|
|
1277
|
-
const handle_click = (event: MouseEvent) => {
|
|
1278
|
-
event.stopPropagation()
|
|
1279
|
-
// Check if this was a drag operation (any mouse movement during drag)
|
|
1280
|
-
const was_drag = drag_started
|
|
1281
|
-
drag_started = false // Reset for next interaction
|
|
1282
|
-
if (was_drag) return // Don't trigger click if this was a drag
|
|
1283
|
-
|
|
1284
|
-
const entry = find_entry_at_mouse(event)
|
|
1285
|
-
if (!entry) {
|
|
1286
|
-
if (modal_open) close_structure_popup()
|
|
1287
|
-
return
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
on_point_click?.(entry)
|
|
1291
|
-
|
|
1292
|
-
if (enable_click_selection) {
|
|
1293
|
-
selected_entry = entry
|
|
1294
|
-
if (enable_structure_preview) {
|
|
1295
|
-
const structure = extract_structure_from_entry(entry)
|
|
1296
|
-
if (structure) {
|
|
1297
|
-
selected_structure = structure
|
|
1298
|
-
modal_place_right = helpers.calculate_modal_side(wrapper)
|
|
1299
|
-
modal_open = true
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
function close_structure_popup() {
|
|
1306
|
-
modal_open = false
|
|
1307
|
-
selected_structure = null
|
|
1308
|
-
selected_entry = null
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
const handle_double_click = (event: MouseEvent) => {
|
|
1312
|
-
const entry = find_entry_at_mouse(event)
|
|
1313
|
-
if (entry) {
|
|
1314
|
-
copy_entry_data(entry, {
|
|
1315
|
-
x: event.clientX,
|
|
1316
|
-
y: event.clientY,
|
|
1317
|
-
})
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
function render_once() {
|
|
1322
|
-
if (!frame_id) {
|
|
1323
|
-
frame_id = requestAnimationFrame(() => {
|
|
1324
|
-
render_frame()
|
|
1325
|
-
frame_id = 0
|
|
1326
|
-
})
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
function update_canvas_size() {
|
|
1331
|
-
if (!canvas) return
|
|
1332
|
-
const dpr = globalThis.devicePixelRatio || 1
|
|
1333
|
-
const container = canvas.parentElement
|
|
1334
|
-
const rect = container?.getBoundingClientRect()
|
|
1335
|
-
const [w, h] = rect ? [rect.width, rect.height] : [400, 400]
|
|
1336
|
-
|
|
1337
|
-
// Only update canvas dimensions if they actually changed
|
|
1338
|
-
// (assigning canvas.width/height clears the canvas even if values are the same)
|
|
1339
|
-
const new_width = Math.max(0, Math.round(w * dpr))
|
|
1340
|
-
const new_height = Math.max(0, Math.round(h * dpr))
|
|
1341
|
-
if (!ctx || canvas.width !== new_width || canvas.height !== new_height) {
|
|
1342
|
-
canvas.width = new_width
|
|
1343
|
-
canvas.height = new_height
|
|
1344
|
-
ctx = canvas.getContext(`2d`)
|
|
1345
|
-
if (ctx) {
|
|
1346
|
-
ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
|
|
1347
|
-
ctx.imageSmoothingEnabled = true
|
|
1348
|
-
ctx.imageSmoothingQuality = `high`
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
canvas_dims = { width: w, height: h, scale: Math.min(w, h) / 600 }
|
|
1352
|
-
render_once()
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
1030
|
// Reactive dark mode detection for canvas text color
|
|
1356
1031
|
let dark_mode = $state(is_dark_mode())
|
|
1357
1032
|
$effect(() => watch_dark_mode((dark) => dark_mode = dark))
|
|
1358
1033
|
const text_color = $derived(helpers.get_canvas_text_color(dark_mode))
|
|
1359
1034
|
|
|
1360
|
-
$effect(() => {
|
|
1361
|
-
if (!canvas) return
|
|
1362
|
-
|
|
1363
|
-
// Initial setup
|
|
1364
|
-
update_canvas_size()
|
|
1365
|
-
|
|
1366
|
-
// Watch for resize events - only update canvas, don't reset camera
|
|
1367
|
-
const resize_observer = new ResizeObserver(update_canvas_size)
|
|
1368
|
-
|
|
1369
|
-
const container = canvas.parentElement
|
|
1370
|
-
if (container) {
|
|
1371
|
-
resize_observer.observe(container)
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
return () => { // Cleanup on unmount
|
|
1375
|
-
if (frame_id) cancelAnimationFrame(frame_id)
|
|
1376
|
-
resize_observer.disconnect()
|
|
1377
|
-
}
|
|
1378
|
-
})
|
|
1379
|
-
|
|
1380
|
-
// Fullscreen handling with camera reset
|
|
1381
|
-
let was_fullscreen = $state(fullscreen)
|
|
1382
|
-
$effect(() => {
|
|
1383
|
-
setup_fullscreen_effect(fullscreen, wrapper, (entering_fullscreen) => {
|
|
1384
|
-
if (entering_fullscreen !== was_fullscreen) {
|
|
1385
|
-
camera.center_x = 0
|
|
1386
|
-
camera.center_y = -50
|
|
1387
|
-
was_fullscreen = entering_fullscreen
|
|
1388
|
-
}
|
|
1389
|
-
})
|
|
1390
|
-
set_fullscreen_bg(wrapper, fullscreen, `--hull-3d-bg-fullscreen`)
|
|
1391
|
-
})
|
|
1392
|
-
|
|
1393
1035
|
// Performance: Cache canvas dimensions and formation energy range
|
|
1394
1036
|
let canvas_dims = $state({ width: 600, height: 600, scale: 1 })
|
|
1395
1037
|
const energy_range = $derived.by(() => {
|
|
@@ -1404,56 +1046,30 @@
|
|
|
1404
1046
|
return { min, max, center: (min + max) / 2, z_scale }
|
|
1405
1047
|
})
|
|
1406
1048
|
|
|
1407
|
-
|
|
1408
|
-
const sorted_points_cache = $derived.by(() => {
|
|
1409
|
-
if (!canvas || visible_entries.length === 0) return []
|
|
1410
|
-
return visible_entries
|
|
1411
|
-
.map((entry) => ({
|
|
1412
|
-
entry,
|
|
1413
|
-
projected: project_3d_point(entry.x, entry.y, entry.z),
|
|
1414
|
-
}))
|
|
1415
|
-
.sort((left, right) => left.projected.depth - right.projected.depth)
|
|
1416
|
-
})
|
|
1417
|
-
|
|
1418
|
-
let style = $derived(
|
|
1419
|
-
`--hull-stable-color:${merged_config.colors?.stable || `#0072B2`};
|
|
1420
|
-
--hull-unstable-color:${merged_config.colors?.unstable || `#E69F00`};
|
|
1421
|
-
--hull-edge-color:${merged_config.colors?.edge || `var(--text-color, #212121)`};
|
|
1422
|
-
--hull-text-color:${
|
|
1423
|
-
merged_config.colors?.annotation || `var(--text-color, #212121)`
|
|
1424
|
-
}`,
|
|
1425
|
-
)
|
|
1049
|
+
let style = $derived(helpers.hull_style_css(merged_config.colors))
|
|
1426
1050
|
</script>
|
|
1427
1051
|
|
|
1428
1052
|
<svelte:document
|
|
1429
1053
|
onfullscreenchange={() => {
|
|
1430
|
-
fullscreen
|
|
1054
|
+
// tie fullscreen state to this component's own wrapper, not any fullscreen element
|
|
1055
|
+
fullscreen = document.fullscreenElement === wrapper
|
|
1431
1056
|
}}
|
|
1432
|
-
onmousemove={handle_mouse_move}
|
|
1433
|
-
onmouseup={
|
|
1057
|
+
onmousemove={interactions.handle_mouse_move}
|
|
1058
|
+
onmouseup={interactions.handle_mouse_up}
|
|
1434
1059
|
/>
|
|
1435
1060
|
|
|
1436
1061
|
<div
|
|
1437
1062
|
{...rest}
|
|
1438
1063
|
class="convex-hull-3d {rest.class ?? ``}"
|
|
1439
|
-
class:dragover={drag_over}
|
|
1064
|
+
class:dragover={interactions.drag_over}
|
|
1440
1065
|
style={`${style}; ${rest.style ?? ``}`}
|
|
1441
1066
|
data-has-selection={selected_entry !== null}
|
|
1442
|
-
data-has-hover={hover_data !== null}
|
|
1443
|
-
data-is-dragging={is_dragging}
|
|
1067
|
+
data-has-hover={interactions.hover_data !== null}
|
|
1068
|
+
data-is-dragging={interactions.is_dragging}
|
|
1444
1069
|
bind:this={wrapper}
|
|
1445
1070
|
role="application"
|
|
1446
1071
|
tabindex="-1"
|
|
1447
|
-
|
|
1448
|
-
ondrop={handle_file_drop}
|
|
1449
|
-
ondragover={(event) => {
|
|
1450
|
-
event.preventDefault()
|
|
1451
|
-
drag_over = true
|
|
1452
|
-
}}
|
|
1453
|
-
ondragleave={(event) => {
|
|
1454
|
-
event.preventDefault()
|
|
1455
|
-
drag_over = false
|
|
1456
|
-
}}
|
|
1072
|
+
{...interactions.wrapper_handlers}
|
|
1457
1073
|
aria-label="Ternary convex hull visualization"
|
|
1458
1074
|
>
|
|
1459
1075
|
{@render children?.({
|
|
@@ -1469,12 +1085,7 @@
|
|
|
1469
1085
|
bind:this={canvas}
|
|
1470
1086
|
tabindex="0"
|
|
1471
1087
|
aria-label={merged_controls.title || phase_stats?.chemical_system || `3D Convex Hull`}
|
|
1472
|
-
|
|
1473
|
-
onmousemove={handle_hover}
|
|
1474
|
-
onclick={handle_click}
|
|
1475
|
-
onkeydown={handle_keydown}
|
|
1476
|
-
ondblclick={handle_double_click}
|
|
1477
|
-
onwheel={handle_wheel}
|
|
1088
|
+
{...interactions.canvas_handlers}
|
|
1478
1089
|
></canvas>
|
|
1479
1090
|
|
|
1480
1091
|
{#if entries.length === 0}
|
|
@@ -1486,14 +1097,9 @@
|
|
|
1486
1097
|
|
|
1487
1098
|
<!-- Formation Energy Color Bar (bottom-left corner) -->
|
|
1488
1099
|
{#if color_mode === `energy` && plot_entries.length > 0}
|
|
1489
|
-
{@const hull_distances = plot_entries
|
|
1490
|
-
.map((entry) => entry.e_above_hull)
|
|
1491
|
-
.filter((value): value is number => typeof value === `number`)}
|
|
1492
|
-
{@const min_energy = hull_distances.length > 0 ? Math.min(...hull_distances) : 0}
|
|
1493
|
-
{@const max_energy = hull_distances.length > 0 ? Math.max(...hull_distances, 0.1) : 0.1}
|
|
1494
1100
|
<ColorBar
|
|
1495
1101
|
title="Energy above hull (eV/atom)"
|
|
1496
|
-
range={
|
|
1102
|
+
range={helpers.hull_distance_range(plot_entries)}
|
|
1497
1103
|
{color_scale}
|
|
1498
1104
|
wrapper_style="position: absolute; bottom: 16px; left: 1em; width: 200px;"
|
|
1499
1105
|
bar_style="height: 12px;"
|
|
@@ -1517,82 +1123,46 @@
|
|
|
1517
1123
|
/>
|
|
1518
1124
|
{/if}
|
|
1519
1125
|
|
|
1520
|
-
<!--
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
<!-- Legend controls pane -->
|
|
1561
|
-
{#if controls_config.visible(`controls`)}
|
|
1562
|
-
<ConvexHullControls
|
|
1563
|
-
bind:controls_open={legend_pane_open}
|
|
1564
|
-
bind:color_mode
|
|
1565
|
-
bind:color_scale
|
|
1566
|
-
bind:show_stable
|
|
1567
|
-
bind:show_unstable
|
|
1568
|
-
bind:show_stable_labels
|
|
1569
|
-
bind:show_unstable_labels
|
|
1570
|
-
bind:max_hull_dist_show_phases
|
|
1571
|
-
bind:max_hull_dist_show_labels
|
|
1572
|
-
{max_hull_dist_in_data}
|
|
1573
|
-
{stable_entries}
|
|
1574
|
-
{unstable_entries}
|
|
1575
|
-
{camera}
|
|
1576
|
-
{merged_controls}
|
|
1577
|
-
toggle_props={{ class: `legend-controls-btn` }}
|
|
1578
|
-
{show_hull_faces}
|
|
1579
|
-
on_hull_faces_change={(value: boolean) => show_hull_faces = value}
|
|
1580
|
-
{hull_face_color}
|
|
1581
|
-
on_hull_face_color_change={(value: string) => hull_face_color = value}
|
|
1582
|
-
{hull_face_opacity}
|
|
1583
|
-
on_hull_face_opacity_change={(value: number) => hull_face_opacity = value}
|
|
1584
|
-
{hull_face_color_mode}
|
|
1585
|
-
on_hull_face_color_mode_change={(value: HullFaceColorMode) =>
|
|
1586
|
-
hull_face_color_mode = value}
|
|
1587
|
-
bind:energy_source_mode
|
|
1588
|
-
{has_precomputed_e_form}
|
|
1589
|
-
{can_compute_e_form}
|
|
1590
|
-
{has_precomputed_hull}
|
|
1591
|
-
{can_compute_hull}
|
|
1592
|
-
/>
|
|
1593
|
-
{/if}
|
|
1594
|
-
</section>
|
|
1595
|
-
{/if}
|
|
1126
|
+
<!-- Toolbar + tooltip/copy-feedback/drag/structure-popup chrome -->
|
|
1127
|
+
<ConvexHullChrome
|
|
1128
|
+
{interactions}
|
|
1129
|
+
{hull_data}
|
|
1130
|
+
{controls_config}
|
|
1131
|
+
{reset_all}
|
|
1132
|
+
reset_title="Reset view and settings"
|
|
1133
|
+
{enable_info_pane}
|
|
1134
|
+
{phase_stats}
|
|
1135
|
+
{label_threshold}
|
|
1136
|
+
{fullscreen}
|
|
1137
|
+
{fullscreen_toggle}
|
|
1138
|
+
{wrapper}
|
|
1139
|
+
{camera}
|
|
1140
|
+
{merged_controls}
|
|
1141
|
+
{stable_entries}
|
|
1142
|
+
{unstable_entries}
|
|
1143
|
+
{get_point_color}
|
|
1144
|
+
{merged_highlight_style}
|
|
1145
|
+
{is_highlighted}
|
|
1146
|
+
{tooltip}
|
|
1147
|
+
{selected_entry}
|
|
1148
|
+
bind:show_hull_faces
|
|
1149
|
+
bind:hull_face_color
|
|
1150
|
+
bind:hull_face_opacity
|
|
1151
|
+
bind:hull_face_color_mode
|
|
1152
|
+
bind:info_pane_open
|
|
1153
|
+
bind:controls_open
|
|
1154
|
+
bind:color_mode
|
|
1155
|
+
bind:color_scale
|
|
1156
|
+
bind:show_stable
|
|
1157
|
+
bind:show_unstable
|
|
1158
|
+
{entry_category}
|
|
1159
|
+
bind:hidden_categories
|
|
1160
|
+
bind:show_stable_labels
|
|
1161
|
+
bind:show_unstable_labels
|
|
1162
|
+
bind:max_hull_dist_show_phases
|
|
1163
|
+
bind:max_hull_dist_show_labels
|
|
1164
|
+
bind:energy_source_mode
|
|
1165
|
+
/>
|
|
1596
1166
|
|
|
1597
1167
|
<!-- Orientation gizmo (configurable placement, default top-right) -->
|
|
1598
1168
|
{#if gizmo && typeof WebGLRenderingContext !== `undefined`}
|
|
@@ -1633,7 +1203,7 @@
|
|
|
1633
1203
|
(gas_analysis.has_gas_dependent_elements && merged_gas_config)}
|
|
1634
1204
|
<div class="right-controls">
|
|
1635
1205
|
{#if has_temp_data && temperature !== undefined}
|
|
1636
|
-
<TemperatureSlider {available_temperatures} bind:temperature />
|
|
1206
|
+
<TemperatureSlider available_temperatures={hull_data.available_temperatures} bind:temperature />
|
|
1637
1207
|
{/if}
|
|
1638
1208
|
{#if gas_analysis.has_gas_dependent_elements && merged_gas_config}
|
|
1639
1209
|
<GasPressureControls
|
|
@@ -1645,45 +1215,6 @@
|
|
|
1645
1215
|
</div>
|
|
1646
1216
|
{/if}
|
|
1647
1217
|
|
|
1648
|
-
<!-- Hover tooltip -->
|
|
1649
|
-
{#if hover_data}
|
|
1650
|
-
{@const { entry, position } = hover_data}
|
|
1651
|
-
{@const entry_highlight = is_highlighted(entry) ? merged_highlight_style : undefined}
|
|
1652
|
-
{@const tooltip_style =
|
|
1653
|
-
`z-index: ${CONVEX_HULL_STYLE.z_index.tooltip}; backdrop-filter: blur(4px);
|
|
1654
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);`}
|
|
1655
|
-
<PlotTooltip
|
|
1656
|
-
x={position.x}
|
|
1657
|
-
y={position.y}
|
|
1658
|
-
offset={{ x: 10, y: -10 }}
|
|
1659
|
-
bg_color={get_point_color(entry)}
|
|
1660
|
-
fixed
|
|
1661
|
-
style={tooltip_style}
|
|
1662
|
-
>
|
|
1663
|
-
<ConvexHullTooltip
|
|
1664
|
-
{entry}
|
|
1665
|
-
{polymorph_stats_map}
|
|
1666
|
-
highlight_style={entry_highlight}
|
|
1667
|
-
{tooltip}
|
|
1668
|
-
/>
|
|
1669
|
-
</PlotTooltip>
|
|
1670
|
-
{/if}
|
|
1671
|
-
|
|
1672
|
-
<ClickFeedback bind:visible={copy_feedback.visible} position={copy_feedback.position} />
|
|
1673
|
-
<DragOverlay visible={drag_over} />
|
|
1674
|
-
|
|
1675
|
-
{#if modal_open && selected_structure}
|
|
1676
|
-
<StructurePopup
|
|
1677
|
-
structure={selected_structure}
|
|
1678
|
-
place_right={modal_place_right}
|
|
1679
|
-
stats={{
|
|
1680
|
-
id: selected_entry?.entry_id,
|
|
1681
|
-
e_above_hull: selected_entry?.e_above_hull,
|
|
1682
|
-
e_form: selected_entry?.e_form_per_atom,
|
|
1683
|
-
}}
|
|
1684
|
-
onclose={close_structure_popup}
|
|
1685
|
-
/>
|
|
1686
|
-
{/if}
|
|
1687
1218
|
</div>
|
|
1688
1219
|
|
|
1689
1220
|
<style>
|
|
@@ -1763,39 +1294,4 @@
|
|
|
1763
1294
|
opacity: 1;
|
|
1764
1295
|
pointer-events: auto;
|
|
1765
1296
|
}
|
|
1766
|
-
.control-buttons {
|
|
1767
|
-
position: absolute;
|
|
1768
|
-
top: 1ex;
|
|
1769
|
-
right: 1ex;
|
|
1770
|
-
display: flex;
|
|
1771
|
-
gap: 8px;
|
|
1772
|
-
transition: opacity 0.2s ease-in-out;
|
|
1773
|
-
}
|
|
1774
|
-
.control-buttons.hover-visible {
|
|
1775
|
-
opacity: 0;
|
|
1776
|
-
pointer-events: none;
|
|
1777
|
-
}
|
|
1778
|
-
.convex-hull-3d:hover .control-buttons.hover-visible,
|
|
1779
|
-
.convex-hull-3d:focus-within .control-buttons.hover-visible {
|
|
1780
|
-
opacity: 1;
|
|
1781
|
-
pointer-events: auto;
|
|
1782
|
-
}
|
|
1783
|
-
.control-buttons.always-visible {
|
|
1784
|
-
opacity: 1;
|
|
1785
|
-
pointer-events: auto;
|
|
1786
|
-
}
|
|
1787
|
-
.control-buttons :global(button) {
|
|
1788
|
-
background: transparent;
|
|
1789
|
-
border: none;
|
|
1790
|
-
padding: 4px;
|
|
1791
|
-
cursor: pointer;
|
|
1792
|
-
border-radius: 3px;
|
|
1793
|
-
color: var(--text-color, currentColor);
|
|
1794
|
-
transition: background-color 0.2s;
|
|
1795
|
-
display: flex;
|
|
1796
|
-
font-size: clamp(0.85em, 2cqmin, 1.3em);
|
|
1797
|
-
}
|
|
1798
|
-
.control-buttons :global(button):hover {
|
|
1799
|
-
background-color: color-mix(in srgb, currentColor 8%, transparent);
|
|
1800
|
-
}
|
|
1801
1297
|
</style>
|