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
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { ColorSchemeName } from '../colors'
|
|
3
3
|
import { ELEMENT_COLOR_SCHEMES } from '../colors'
|
|
4
|
-
import type
|
|
5
|
-
import {
|
|
6
|
-
import type { ElementSymbol } from '../element'
|
|
4
|
+
import { normalize_show_controls, type ShowControlsProp } from '../controls'
|
|
5
|
+
import { coerce_elem_symbol, type ElementSymbol } from '../element'
|
|
7
6
|
import { StatusMessage } from '../feedback'
|
|
8
7
|
import Spinner from '../feedback/Spinner.svelte'
|
|
9
8
|
import Icon from '../Icon.svelte'
|
|
10
|
-
import { create_file_drop_handler, load_from_url } from '../io'
|
|
9
|
+
import { create_file_drop_handler, drag_over_handlers, load_from_url } from '../io'
|
|
10
|
+
import { forward_window_keydown, handle_and_prevent } from '../keyboard'
|
|
11
11
|
import { parse_volumetric_file } from '../isosurface/parse'
|
|
12
12
|
import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types'
|
|
13
13
|
import {
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
DEFAULT_ISOSURFACE_SETTINGS,
|
|
16
16
|
tile_volumetric_data,
|
|
17
17
|
} from '../isosurface/types'
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
18
|
+
import { type FullscreenToggleProp, toggle_fullscreen, ViewerChrome } from '../layout'
|
|
19
|
+
import { sync_fullscreen } from '../layout/fullscreen.svelte'
|
|
20
20
|
import type { Vec3 } from '../math'
|
|
21
21
|
import { create_cart_to_frac, create_frac_to_cart } from '../math'
|
|
22
22
|
import { DEFAULTS } from '../settings'
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
import { get_property_colors } from './atom-properties'
|
|
57
57
|
import AtomLegend from './AtomLegend.svelte'
|
|
58
58
|
import CellSelect from './CellSelect.svelte'
|
|
59
|
-
import { BOND_ORDER_OPTIONS, merge_bond_edits } from './bonding'
|
|
59
|
+
import { BOND_ORDER_OPTIONS, merge_bond_edits, remap_bonds_after_deletion } from './bonding'
|
|
60
60
|
import type { StructureHandlerData } from './index'
|
|
61
61
|
import { MAX_SELECTED_SITES } from './measure'
|
|
62
62
|
import { normalize_fractional_coords, parse_any_structure } from './parse'
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
import StructureExportPane from './StructureExportPane.svelte'
|
|
65
65
|
import StructureInfoPane from './StructureInfoPane.svelte'
|
|
66
66
|
import StructureScene from './StructureScene.svelte'
|
|
67
|
+
import { to_error } from '../utils'
|
|
67
68
|
|
|
68
69
|
// Type alias for event handlers to reduce verbosity
|
|
69
70
|
type EventHandler = (data: StructureHandlerData) => void
|
|
@@ -187,15 +188,13 @@
|
|
|
187
188
|
structure?: AnyStructure
|
|
188
189
|
bonds?: StructureBond[]
|
|
189
190
|
scene_props?: ComponentProps<typeof StructureScene>
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
* Control names: 'reset-camera', 'fullscreen', 'measure-mode', 'info-pane', 'export-pane', 'controls'
|
|
198
|
-
*/
|
|
191
|
+
// Controls visibility configuration.
|
|
192
|
+
// - 'always': controls always visible
|
|
193
|
+
// - 'hover': controls visible on component hover (default)
|
|
194
|
+
// - 'never': controls never visible
|
|
195
|
+
// - object: { mode, hidden, style } for fine-grained control
|
|
196
|
+
//
|
|
197
|
+
// Control names: 'reset-camera', 'fullscreen', 'measure-mode', 'info-pane', 'export-pane', 'controls'
|
|
199
198
|
show_controls?: ShowControlsProp
|
|
200
199
|
fullscreen?: boolean
|
|
201
200
|
// bindable width of the canvas
|
|
@@ -216,7 +215,7 @@
|
|
|
216
215
|
bond_edit_mode?: BondEditMode
|
|
217
216
|
bond_edit_order?: BondOrder
|
|
218
217
|
info_pane_open?: boolean
|
|
219
|
-
fullscreen_toggle?:
|
|
218
|
+
fullscreen_toggle?: FullscreenToggleProp
|
|
220
219
|
bottom_left?: Snippet<[{ structure?: AnyStructure }]>
|
|
221
220
|
top_right_controls?: Snippet // Additional controls to render at the end of the control buttons row
|
|
222
221
|
data_url?: string // URL to load structure from (alternative to providing structure directly)
|
|
@@ -302,7 +301,7 @@
|
|
|
302
301
|
emit_file_load_event(parsed, filename, content)
|
|
303
302
|
} catch (error) {
|
|
304
303
|
error_msg = `Failed to parse structure: ${
|
|
305
|
-
error
|
|
304
|
+
to_error(error).message
|
|
306
305
|
}`
|
|
307
306
|
on_error?.({ error_msg, filename })
|
|
308
307
|
}
|
|
@@ -333,7 +332,7 @@
|
|
|
333
332
|
}
|
|
334
333
|
} catch (err) {
|
|
335
334
|
error_msg = `Failed to parse structure from string: ${
|
|
336
|
-
err
|
|
335
|
+
to_error(err).message
|
|
337
336
|
}`
|
|
338
337
|
untrack(() => on_error?.({ error_msg, filename: `string` }))
|
|
339
338
|
} finally {
|
|
@@ -467,10 +466,13 @@
|
|
|
467
466
|
let bond_order_overrides = $state<StructureBond[]>([])
|
|
468
467
|
let bond_undo_stack = $state<BondEditHistorySnapshot[]>([])
|
|
469
468
|
let bond_redo_stack = $state<BondEditHistorySnapshot[]>([])
|
|
470
|
-
|
|
471
|
-
|
|
469
|
+
// These hold object-identity tokens (structure_identity) compared with ===/!==,
|
|
470
|
+
// so they must stay raw — proxying them via $state would break identity comparisons
|
|
471
|
+
// (state_proxy_equality_mismatch) against the raw `structure` prop.
|
|
472
|
+
let bond_history_context = $state.raw<BondEditContext>()
|
|
473
|
+
let last_bond_structure_identity = $state.raw(structure)
|
|
472
474
|
let last_emitted_bond_signature = $state<string>()
|
|
473
|
-
let bond_edit_snapshot = $state<BondEditSnapshot>()
|
|
475
|
+
let bond_edit_snapshot = $state.raw<BondEditSnapshot>()
|
|
474
476
|
let has_bond_edits = $derived(
|
|
475
477
|
added_bonds.length > 0 || removed_bonds.length > 0 ||
|
|
476
478
|
bond_order_overrides.length > 0,
|
|
@@ -638,6 +640,10 @@
|
|
|
638
640
|
emit_bonds(edited_bonds)
|
|
639
641
|
})
|
|
640
642
|
|
|
643
|
+
// Elements currently anchoring polyhedra (written by StructureScene, read by
|
|
644
|
+
// StructureControls so per-element toggles reflect actual render state)
|
|
645
|
+
let polyhedra_rendered_elements = $state<string[]>([])
|
|
646
|
+
|
|
641
647
|
// === Edit-atoms mode state ===
|
|
642
648
|
let dragging_atoms = $state(false)
|
|
643
649
|
let undo_stack = $state<AnyStructure[]>([])
|
|
@@ -677,9 +683,8 @@
|
|
|
677
683
|
|
|
678
684
|
// Normalize and validate element symbol (e.g. "fe" → "Fe", "Xx" → null)
|
|
679
685
|
function normalize_element(input: string): ElementSymbol | null {
|
|
680
|
-
const normalized =
|
|
681
|
-
|
|
682
|
-
return ELEM_SYMBOLS.includes(normalized) ? normalized : null
|
|
686
|
+
const normalized = input.charAt(0).toUpperCase() + input.slice(1).toLowerCase()
|
|
687
|
+
return coerce_elem_symbol(normalized) ?? null
|
|
683
688
|
}
|
|
684
689
|
|
|
685
690
|
function clear_selection() {
|
|
@@ -776,7 +781,13 @@
|
|
|
776
781
|
})
|
|
777
782
|
|
|
778
783
|
let controls_config = $derived(normalize_show_controls(show_controls))
|
|
779
|
-
|
|
784
|
+
// $effect instead of `$derived(hovered || focused)`: the $derived reading the $bindable
|
|
785
|
+
// `hovered` prop went stale after the first hover/leave cycle, so the gizmo + mode toggle only
|
|
786
|
+
// appeared on the first mouseenter until reload.
|
|
787
|
+
let viewer_active = $state(false)
|
|
788
|
+
$effect(() => {
|
|
789
|
+
viewer_active = hovered || focused
|
|
790
|
+
})
|
|
780
791
|
let scene_gizmo = $derived(viewer_active && (scene_props.gizmo ?? scene_props.show_gizmo))
|
|
781
792
|
let active_scene_sites = $derived([
|
|
782
793
|
...new SvelteSet([...(scene_props.active_sites ?? []), ...highlighted_sites]),
|
|
@@ -822,7 +833,7 @@
|
|
|
822
833
|
let supercell_structure = $state(structure)
|
|
823
834
|
let supercell_loading = $state(false)
|
|
824
835
|
let has_supercell = $derived(
|
|
825
|
-
|
|
836
|
+
Boolean(supercell_scaling) && ![``, `1x1x1`, `1`].includes(supercell_scaling),
|
|
826
837
|
)
|
|
827
838
|
let bond_edits_enabled = $derived(
|
|
828
839
|
cell_type === `original` && !has_supercell && !supercell_loading,
|
|
@@ -865,8 +876,8 @@
|
|
|
865
876
|
// For large supercells, show loading state and use async generation
|
|
866
877
|
const sites_count = base_structure.sites?.length || 0
|
|
867
878
|
const [nx_str, ny_str, nz_str] = supercell_scaling.split(/[x×]/)
|
|
868
|
-
const scaling_mult = (parseInt(nx_str) || 1) * (parseInt(ny_str) || 1) *
|
|
869
|
-
(parseInt(nz_str) || 1)
|
|
879
|
+
const scaling_mult = (parseInt(nx_str, 10) || 1) * (parseInt(ny_str, 10) || 1) *
|
|
880
|
+
(parseInt(nz_str, 10) || 1)
|
|
870
881
|
const estimated_sites = sites_count * scaling_mult
|
|
871
882
|
|
|
872
883
|
// Show spinner for supercells with >1000 estimated sites or scaling >8
|
|
@@ -1124,7 +1135,7 @@
|
|
|
1124
1135
|
emit_file_load_event(parsed, filename, content)
|
|
1125
1136
|
} catch (err) {
|
|
1126
1137
|
error_msg = `Failed to parse structure: ${
|
|
1127
|
-
err
|
|
1138
|
+
to_error(err).message
|
|
1128
1139
|
}`
|
|
1129
1140
|
on_error?.({ error_msg, filename })
|
|
1130
1141
|
}
|
|
@@ -1139,7 +1150,9 @@
|
|
|
1139
1150
|
},
|
|
1140
1151
|
})
|
|
1141
1152
|
|
|
1142
|
-
|
|
1153
|
+
// Handle keyboard shortcuts. Returns true if the key was handled, so the caller
|
|
1154
|
+
// (handle_and_prevent / forward_window_keydown) can suppress the browser default.
|
|
1155
|
+
function handle_keydown(event: KeyboardEvent): boolean {
|
|
1143
1156
|
// Don't handle shortcuts if user is typing in an input field
|
|
1144
1157
|
const target = event.target
|
|
1145
1158
|
const is_input_focused =
|
|
@@ -1151,45 +1164,39 @@
|
|
|
1151
1164
|
|
|
1152
1165
|
// Allow Escape to cancel add-atom mode even when the element input is focused
|
|
1153
1166
|
if (event.key === `Escape` && measure_mode === `edit-atoms` && add_atom_mode) {
|
|
1154
|
-
event.preventDefault()
|
|
1155
1167
|
add_atom_mode = false
|
|
1156
|
-
return
|
|
1168
|
+
return true
|
|
1157
1169
|
}
|
|
1158
1170
|
|
|
1159
|
-
if (is_input_focused) return
|
|
1171
|
+
if (is_input_focused) return false
|
|
1160
1172
|
|
|
1161
1173
|
if (measure_mode === `edit-bonds`) {
|
|
1162
1174
|
const key = event.key.toLowerCase()
|
|
1163
1175
|
const plain = !event.ctrlKey && !event.metaKey && !event.altKey
|
|
1164
1176
|
if (event.ctrlKey || event.metaKey) {
|
|
1165
1177
|
if (key === `z` && !event.shiftKey) {
|
|
1166
|
-
if (bond_undo_stack.length === 0) return
|
|
1167
|
-
event.preventDefault()
|
|
1178
|
+
if (bond_undo_stack.length === 0) return false
|
|
1168
1179
|
undo_bond_edit()
|
|
1169
1180
|
show_toast(`Undo bond edit (${bond_undo_stack.length} left)`)
|
|
1170
|
-
return
|
|
1181
|
+
return true
|
|
1171
1182
|
} else if (key === `y` || (key === `z` && event.shiftKey)) {
|
|
1172
|
-
if (bond_redo_stack.length === 0) return
|
|
1173
|
-
event.preventDefault()
|
|
1183
|
+
if (bond_redo_stack.length === 0) return false
|
|
1174
1184
|
redo_bond_edit()
|
|
1175
1185
|
show_toast(`Redo bond edit (${bond_redo_stack.length} left)`)
|
|
1176
|
-
return
|
|
1186
|
+
return true
|
|
1177
1187
|
}
|
|
1178
1188
|
}
|
|
1179
1189
|
if (key === `a` && plain) {
|
|
1180
|
-
event.preventDefault()
|
|
1181
1190
|
bond_edit_mode = `add`
|
|
1182
|
-
return
|
|
1191
|
+
return true
|
|
1183
1192
|
}
|
|
1184
1193
|
if (key === `d` && plain) {
|
|
1185
|
-
event.preventDefault()
|
|
1186
1194
|
bond_edit_mode = `delete`
|
|
1187
|
-
return
|
|
1195
|
+
return true
|
|
1188
1196
|
}
|
|
1189
1197
|
if (event.key === `Escape` && selected_sites.length > 0) {
|
|
1190
|
-
event.preventDefault()
|
|
1191
1198
|
clear_selection()
|
|
1192
|
-
return
|
|
1199
|
+
return true
|
|
1193
1200
|
}
|
|
1194
1201
|
}
|
|
1195
1202
|
|
|
@@ -1199,61 +1206,66 @@
|
|
|
1199
1206
|
if (event.ctrlKey || event.metaKey) {
|
|
1200
1207
|
const key = event.key.toLowerCase()
|
|
1201
1208
|
if (key === `z` && !event.shiftKey) {
|
|
1202
|
-
if (undo_stack.length === 0) return
|
|
1203
|
-
event.preventDefault()
|
|
1209
|
+
if (undo_stack.length === 0) return false
|
|
1204
1210
|
undo()
|
|
1205
1211
|
show_toast(`Undo (${undo_stack.length} left)`)
|
|
1206
|
-
return
|
|
1212
|
+
return true
|
|
1207
1213
|
} else if (key === `y` || (key === `z` && event.shiftKey)) {
|
|
1208
|
-
if (redo_stack.length === 0) return
|
|
1209
|
-
event.preventDefault()
|
|
1214
|
+
if (redo_stack.length === 0) return false
|
|
1210
1215
|
redo()
|
|
1211
1216
|
show_toast(`Redo (${redo_stack.length} left)`)
|
|
1212
|
-
return
|
|
1217
|
+
return true
|
|
1213
1218
|
}
|
|
1214
1219
|
}
|
|
1215
1220
|
|
|
1216
1221
|
if (event.key === `Delete` || event.key === `Backspace`) {
|
|
1217
1222
|
// Delete selected atoms
|
|
1218
1223
|
if (selected_sites.length > 0 && structure?.sites) {
|
|
1219
|
-
event.preventDefault()
|
|
1220
1224
|
is_internal_edit = true
|
|
1221
1225
|
push_undo()
|
|
1222
1226
|
const to_delete = scene_to_structure_indices(selected_sites, true)
|
|
1223
1227
|
const n_deleted = to_delete.size
|
|
1224
1228
|
clear_selection()
|
|
1229
|
+
// Remap explicit bond metadata so surviving bonds track shifted site indices.
|
|
1230
|
+
// structure_with_bonds prefers the bindable `bonds` prop, so remap that too.
|
|
1231
|
+
if (bonds !== undefined) bonds = remap_bonds_after_deletion(bonds, to_delete)
|
|
1232
|
+
const old_bonds = structure.properties?.bonds
|
|
1225
1233
|
structure = {
|
|
1226
1234
|
...structure,
|
|
1227
1235
|
sites: structure.sites.filter((_, idx) => !to_delete.has(idx)),
|
|
1236
|
+
...(old_bonds && {
|
|
1237
|
+
properties: {
|
|
1238
|
+
...structure.properties,
|
|
1239
|
+
bonds: remap_bonds_after_deletion(old_bonds, to_delete),
|
|
1240
|
+
},
|
|
1241
|
+
}),
|
|
1228
1242
|
}
|
|
1229
1243
|
// Clear per-site overrides since indices shifted after deletion
|
|
1230
1244
|
if (site_radius_overrides?.size > 0) site_radius_overrides.clear()
|
|
1231
1245
|
clear_bond_edits()
|
|
1232
1246
|
show_toast(`Deleted ${n_deleted} site${n_deleted > 1 ? `s` : ``}`)
|
|
1247
|
+
return true
|
|
1233
1248
|
}
|
|
1234
|
-
return
|
|
1249
|
+
return false
|
|
1235
1250
|
}
|
|
1236
1251
|
const key = event.key.toLowerCase()
|
|
1237
1252
|
const plain = !event.ctrlKey && !event.metaKey && !event.altKey
|
|
1238
1253
|
|
|
1239
1254
|
if (key === `a` && plain) {
|
|
1240
1255
|
// Enter add-atom sub-mode (plain 'a' only, not Ctrl+A/Cmd+A/Alt+A)
|
|
1241
|
-
event.preventDefault()
|
|
1242
1256
|
add_atom_mode = !add_atom_mode
|
|
1243
|
-
return
|
|
1257
|
+
return true
|
|
1244
1258
|
}
|
|
1245
1259
|
// Change element of selected atoms
|
|
1246
1260
|
if (key === `e` && plain && selected_sites.length > 0) {
|
|
1247
|
-
event.preventDefault()
|
|
1248
1261
|
change_element_mode = !change_element_mode
|
|
1249
|
-
return
|
|
1262
|
+
return true
|
|
1250
1263
|
}
|
|
1251
1264
|
// Duplicate selected atoms at a small offset
|
|
1252
1265
|
if (
|
|
1253
1266
|
key === `d` && (event.ctrlKey || event.metaKey) &&
|
|
1254
1267
|
selected_sites.length > 0 && structure?.sites
|
|
1255
1268
|
) {
|
|
1256
|
-
event.preventDefault()
|
|
1257
1269
|
is_internal_edit = true
|
|
1258
1270
|
push_undo()
|
|
1259
1271
|
const orig_indices = scene_to_structure_indices(selected_sites)
|
|
@@ -1284,18 +1296,18 @@
|
|
|
1284
1296
|
show_toast(
|
|
1285
1297
|
`Duplicated ${new_sites.length} site${new_sites.length > 1 ? `s` : ``}`,
|
|
1286
1298
|
)
|
|
1287
|
-
return
|
|
1299
|
+
return true
|
|
1288
1300
|
}
|
|
1289
1301
|
|
|
1290
1302
|
// add_atom_mode Escape is already handled above (before is_input_focused guard)
|
|
1291
1303
|
if (event.key === `Escape`) {
|
|
1292
1304
|
if (change_element_mode) {
|
|
1293
1305
|
change_element_mode = false
|
|
1294
|
-
return
|
|
1306
|
+
return true
|
|
1295
1307
|
}
|
|
1296
1308
|
if (selected_sites.length > 0) {
|
|
1297
1309
|
clear_selection()
|
|
1298
|
-
return
|
|
1310
|
+
return true
|
|
1299
1311
|
}
|
|
1300
1312
|
}
|
|
1301
1313
|
}
|
|
@@ -1303,11 +1315,11 @@
|
|
|
1303
1315
|
// Interface shortcuts (require Ctrl/Cmd modifier to avoid accidental triggers)
|
|
1304
1316
|
const has_modifier = event.ctrlKey || event.metaKey
|
|
1305
1317
|
if (event.key === `f` && has_modifier && fullscreen_toggle) {
|
|
1306
|
-
event.preventDefault()
|
|
1307
1318
|
toggle_fullscreen(wrapper)
|
|
1319
|
+
return true
|
|
1308
1320
|
} else if (event.key === `i` && has_modifier && enable_info_pane) {
|
|
1309
|
-
event.preventDefault()
|
|
1310
1321
|
info_pane_open = !info_pane_open
|
|
1322
|
+
return true
|
|
1311
1323
|
} else if (event.key === `Escape`) {
|
|
1312
1324
|
// Prioritize closing panes, then exit edit modes, then exit fullscreen
|
|
1313
1325
|
if (info_pane_open) info_pane_open = false
|
|
@@ -1315,10 +1327,19 @@
|
|
|
1315
1327
|
else if (export_pane_open) export_pane_open = false
|
|
1316
1328
|
else if (measure_mode === `edit-bonds` || measure_mode === `edit-atoms`) {
|
|
1317
1329
|
measure_mode = `distance`
|
|
1318
|
-
}
|
|
1330
|
+
} else return false
|
|
1331
|
+
return true
|
|
1319
1332
|
}
|
|
1333
|
+
return false
|
|
1320
1334
|
}
|
|
1321
1335
|
|
|
1336
|
+
// Hover (window) path: skip edit-mode mutations so destructive keys (delete/undo)
|
|
1337
|
+
// require focus, not just a hovering mouse.
|
|
1338
|
+
const handle_hover_keydown = (event: KeyboardEvent): boolean =>
|
|
1339
|
+
measure_mode === `edit-atoms` || measure_mode === `edit-bonds`
|
|
1340
|
+
? false
|
|
1341
|
+
: handle_keydown(event)
|
|
1342
|
+
|
|
1322
1343
|
// === Edit-atoms mode helpers ===
|
|
1323
1344
|
|
|
1324
1345
|
// Map scene indices (into displayed_structure) back to raw structure indices.
|
|
@@ -1458,24 +1479,19 @@
|
|
|
1458
1479
|
}
|
|
1459
1480
|
})
|
|
1460
1481
|
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
set_fullscreen_bg(wrapper, fullscreen, `--struct-bg-fullscreen`)
|
|
1482
|
+
sync_fullscreen({
|
|
1483
|
+
get_wrapper: () => wrapper,
|
|
1484
|
+
get_fullscreen: () => fullscreen,
|
|
1485
|
+
set_fullscreen: (val) => (fullscreen = val),
|
|
1486
|
+
bg_css_var: `--struct-bg-fullscreen`,
|
|
1487
|
+
on_change: (val) => on_fullscreen_change?.({ structure, fullscreen: val }),
|
|
1470
1488
|
})
|
|
1471
1489
|
</script>
|
|
1472
1490
|
|
|
1473
|
-
<
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
}}
|
|
1478
|
-
/>
|
|
1491
|
+
<!-- Forward shortcuts to the hovered viewer when focus is on <body> (see
|
|
1492
|
+
forward_window_keydown). Edit modes are excluded so destructive keys
|
|
1493
|
+
(delete/undo) still require focus, not just a hovering mouse. -->
|
|
1494
|
+
<svelte:window onkeydown={forward_window_keydown(() => hovered, handle_hover_keydown)} />
|
|
1479
1495
|
|
|
1480
1496
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
1481
1497
|
<div
|
|
@@ -1502,30 +1518,15 @@
|
|
|
1502
1518
|
if (!(target instanceof HTMLElement)) return
|
|
1503
1519
|
// Don't reset if double-click was on UI controls/panes/legend
|
|
1504
1520
|
if (
|
|
1505
|
-
|
|
1506
|
-
target.
|
|
1507
|
-
target.closest(`.atom-legend`) ||
|
|
1508
|
-
target.closest(`.info-pane`) ||
|
|
1509
|
-
target.closest(`.export-pane`) ||
|
|
1510
|
-
target.closest(`.controls-pane`) ||
|
|
1511
|
-
target.tagName === `BUTTON` ||
|
|
1512
|
-
target.tagName === `INPUT` ||
|
|
1513
|
-
target.tagName === `SELECT`
|
|
1521
|
+
[`.control-buttons`, `.structure-legend`, `.atom-legend`, `.info-pane`, `.export-pane`, `.controls-pane`].some((selector) => target.closest(selector))
|
|
1522
|
+
|| target.tagName === `BUTTON` || target.tagName === `INPUT` || target.tagName === `SELECT`
|
|
1514
1523
|
) return
|
|
1515
1524
|
// Reset camera for double-clicks on the 3D scene
|
|
1516
1525
|
reset_camera()
|
|
1517
1526
|
}}
|
|
1518
1527
|
ondrop={handle_file_drop}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
if (!allow_file_drop) return
|
|
1522
|
-
dragover = true
|
|
1523
|
-
}}
|
|
1524
|
-
ondragleave={(event) => {
|
|
1525
|
-
event.preventDefault()
|
|
1526
|
-
dragover = false
|
|
1527
|
-
}}
|
|
1528
|
-
onkeydown={handle_keydown}
|
|
1528
|
+
{...drag_over_handlers({ allow: () => allow_file_drop, set_dragover: (over) => dragover = over })}
|
|
1529
|
+
onkeydown={handle_and_prevent(handle_keydown)}
|
|
1529
1530
|
{...rest}
|
|
1530
1531
|
class="structure {rest.class ?? ``}"
|
|
1531
1532
|
>
|
|
@@ -1539,307 +1540,282 @@
|
|
|
1539
1540
|
{:else if error_msg}
|
|
1540
1541
|
<StatusMessage bind:message={error_msg} type="error" dismissible />
|
|
1541
1542
|
{:else if (structure?.sites?.length ?? 0) > 0}
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1543
|
+
{#snippet reset_camera_btn()}
|
|
1544
|
+
{#if camera_has_moved && controls_config.visible(`reset-camera`)}
|
|
1545
|
+
<button class="reset-camera" onclick={reset_camera} title={reset_text}>
|
|
1546
|
+
<!-- Target/Focus icon for reset camera -->
|
|
1547
|
+
<Icon icon="Reset" />
|
|
1548
|
+
</button>
|
|
1549
|
+
{/if}
|
|
1550
|
+
{/snippet}
|
|
1551
|
+
<ViewerChrome
|
|
1552
|
+
{controls_config}
|
|
1553
|
+
{fullscreen}
|
|
1554
|
+
{fullscreen_toggle}
|
|
1555
|
+
fullscreen_btn_style="padding: 0 3px"
|
|
1556
|
+
{wrapper}
|
|
1557
|
+
before={reset_camera_btn}
|
|
1558
|
+
style="--viewer-buttons-gap: 4pt; --viewer-buttons-btn-padding: 1px 6px; --viewer-buttons-align: stretch"
|
|
1545
1559
|
>
|
|
1546
|
-
{#if controls_config.mode
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
</button>
|
|
1552
|
-
{/if}
|
|
1553
|
-
{#if fullscreen_toggle && controls_config.visible(`fullscreen`)}
|
|
1560
|
+
{#if enable_measure_mode && controls_config.visible(`measure-mode`)}
|
|
1561
|
+
<div
|
|
1562
|
+
class="measure-mode-dropdown"
|
|
1563
|
+
{@attach click_outside({ callback: () => measure_menu_open = false })}
|
|
1564
|
+
>
|
|
1554
1565
|
<button
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
style="
|
|
1561
|
-
{@attach tooltip()}
|
|
1566
|
+
onclick={() => (measure_menu_open = !measure_menu_open)}
|
|
1567
|
+
title="Measure / Edit"
|
|
1568
|
+
class="view-mode-button"
|
|
1569
|
+
class:active={measure_menu_open}
|
|
1570
|
+
aria-expanded={measure_menu_open}
|
|
1571
|
+
style="transform: scale(1.2)"
|
|
1562
1572
|
>
|
|
1563
|
-
{#if
|
|
1564
|
-
|
|
1573
|
+
{#if show_measure_selection_limit}
|
|
1574
|
+
<span class="selection-limit-text">
|
|
1575
|
+
{measured_sites.length}/{MAX_SELECTED_SITES}
|
|
1576
|
+
</span>
|
|
1565
1577
|
{:else}
|
|
1566
|
-
<Icon
|
|
1578
|
+
<Icon
|
|
1579
|
+
icon={({
|
|
1580
|
+
distance: `Ruler`,
|
|
1581
|
+
angle: `Angle`,
|
|
1582
|
+
'edit-bonds': `Link`,
|
|
1583
|
+
'edit-atoms': `Edit`,
|
|
1584
|
+
} as const)[measure_mode]}
|
|
1585
|
+
/>
|
|
1567
1586
|
{/if}
|
|
1587
|
+
<Icon
|
|
1588
|
+
icon="Arrow{measure_menu_open ? `Up` : `Down`}"
|
|
1589
|
+
style="margin-left: -2px"
|
|
1590
|
+
/>
|
|
1568
1591
|
</button>
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
{#if enable_measure_mode && controls_config.visible(`measure-mode`)}
|
|
1572
|
-
<div
|
|
1573
|
-
class="measure-mode-dropdown"
|
|
1574
|
-
{@attach click_outside({ callback: () => measure_menu_open = false })}
|
|
1575
|
-
>
|
|
1592
|
+
{#if show_selection_reset}
|
|
1576
1593
|
<button
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1594
|
+
type="button"
|
|
1595
|
+
aria-label="Reset selection and bond edits"
|
|
1596
|
+
onclick={() => {
|
|
1597
|
+
clear_selection()
|
|
1598
|
+
clear_bond_edits()
|
|
1599
|
+
}}
|
|
1583
1600
|
>
|
|
1584
|
-
|
|
1585
|
-
<span class="selection-limit-text">
|
|
1586
|
-
{measured_sites.length}/{MAX_SELECTED_SITES}
|
|
1587
|
-
</span>
|
|
1588
|
-
{:else}
|
|
1589
|
-
<Icon
|
|
1590
|
-
icon={({
|
|
1591
|
-
distance: `Ruler`,
|
|
1592
|
-
angle: `Angle`,
|
|
1593
|
-
'edit-bonds': `Link`,
|
|
1594
|
-
'edit-atoms': `Edit`,
|
|
1595
|
-
} as const)[measure_mode]}
|
|
1596
|
-
/>
|
|
1597
|
-
{/if}
|
|
1598
|
-
<Icon
|
|
1599
|
-
icon="Arrow{measure_menu_open ? `Up` : `Down`}"
|
|
1600
|
-
style="margin-left: -2px"
|
|
1601
|
-
/>
|
|
1601
|
+
<Icon icon="Reset" style="margin-left: -4px" />
|
|
1602
1602
|
</button>
|
|
1603
|
-
{#if show_selection_reset}
|
|
1604
|
-
<button
|
|
1605
|
-
type="button"
|
|
1606
|
-
aria-label="Reset selection and bond edits"
|
|
1607
|
-
onclick={() => {
|
|
1608
|
-
clear_selection()
|
|
1609
|
-
clear_bond_edits()
|
|
1610
|
-
}}
|
|
1611
|
-
>
|
|
1612
|
-
<Icon icon="Reset" style="margin-left: -4px" />
|
|
1613
|
-
</button>
|
|
1614
|
-
{/if}
|
|
1615
|
-
{#if measure_menu_open}
|
|
1616
|
-
<div class="view-mode-dropdown">
|
|
1617
|
-
{#each [
|
|
1618
|
-
{ mode: `distance`, icon: `Ruler`, label: `Distance`, scale: 1.1 },
|
|
1619
|
-
{ mode: `angle`, icon: `Angle`, label: `Angle`, scale: 1.3 },
|
|
1620
|
-
{
|
|
1621
|
-
mode: `edit-atoms`,
|
|
1622
|
-
icon: `Edit`,
|
|
1623
|
-
label: `Edit Atoms`,
|
|
1624
|
-
scale: 1.0,
|
|
1625
|
-
},
|
|
1626
|
-
{
|
|
1627
|
-
mode: `edit-bonds`,
|
|
1628
|
-
icon: `Link`,
|
|
1629
|
-
label: `Edit Bonds`,
|
|
1630
|
-
scale: 1.0,
|
|
1631
|
-
},
|
|
1632
|
-
] as const as
|
|
1633
|
-
{ mode, icon, label, scale }
|
|
1634
|
-
(mode)
|
|
1635
|
-
}
|
|
1636
|
-
<button
|
|
1637
|
-
class="view-mode-option"
|
|
1638
|
-
class:selected={measure_mode === mode}
|
|
1639
|
-
disabled={mode === `edit-bonds` && !bond_edits_enabled}
|
|
1640
|
-
title={mode === `edit-bonds` && !bond_edits_enabled
|
|
1641
|
-
? `Bond editing is only available for the original 1x1x1 cell`
|
|
1642
|
-
: label}
|
|
1643
|
-
onclick={() => {
|
|
1644
|
-
if (mode === `edit-bonds` && !bond_edits_enabled) return
|
|
1645
|
-
;[measure_mode, measure_menu_open] = [mode, false]
|
|
1646
|
-
}}
|
|
1647
|
-
>
|
|
1648
|
-
<Icon {icon} style="transform: scale({scale})" />
|
|
1649
|
-
<span>{label}</span>
|
|
1650
|
-
</button>
|
|
1651
|
-
{/each}
|
|
1652
|
-
</div>
|
|
1653
|
-
{/if}
|
|
1654
|
-
</div>
|
|
1655
|
-
|
|
1656
|
-
<!-- Undo/redo buttons (only in edit-atoms mode) -->
|
|
1657
|
-
{#if measure_mode === `edit-atoms`}
|
|
1658
|
-
<div class="undo-redo-container">
|
|
1659
|
-
<button
|
|
1660
|
-
type="button"
|
|
1661
|
-
aria-label="Undo (Cmd/Ctrl+Z)"
|
|
1662
|
-
disabled={undo_stack.length === 0}
|
|
1663
|
-
onclick={undo}
|
|
1664
|
-
title="Undo (Cmd/Ctrl+Z)"
|
|
1665
|
-
class="undo-redo-btn"
|
|
1666
|
-
>
|
|
1667
|
-
<Icon icon="Undo" />
|
|
1668
|
-
{#if undo_stack.length > 0}
|
|
1669
|
-
<span class="history-count">{undo_stack.length}</span>
|
|
1670
|
-
{/if}
|
|
1671
|
-
</button>
|
|
1672
|
-
<button
|
|
1673
|
-
type="button"
|
|
1674
|
-
aria-label="Redo (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1675
|
-
disabled={redo_stack.length === 0}
|
|
1676
|
-
onclick={redo}
|
|
1677
|
-
title="Redo (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1678
|
-
class="undo-redo-btn"
|
|
1679
|
-
>
|
|
1680
|
-
<Icon icon="Redo" />
|
|
1681
|
-
{#if redo_stack.length > 0}
|
|
1682
|
-
<span class="history-count">{redo_stack.length}</span>
|
|
1683
|
-
{/if}
|
|
1684
|
-
</button>
|
|
1685
|
-
</div>
|
|
1686
1603
|
{/if}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
{
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
>
|
|
1712
|
-
{label}
|
|
1713
|
-
</button>
|
|
1714
|
-
{/each}
|
|
1715
|
-
</div>
|
|
1716
|
-
</div>
|
|
1717
|
-
<div class="undo-redo-container">
|
|
1718
|
-
<button
|
|
1719
|
-
type="button"
|
|
1720
|
-
aria-label="Undo bond edit (Cmd/Ctrl+Z)"
|
|
1721
|
-
disabled={bond_undo_stack.length === 0}
|
|
1722
|
-
onclick={undo_bond_edit}
|
|
1723
|
-
title="Undo bond edit (Cmd/Ctrl+Z)"
|
|
1724
|
-
class="undo-redo-btn"
|
|
1725
|
-
>
|
|
1726
|
-
<Icon icon="Undo" />
|
|
1727
|
-
{#if bond_undo_stack.length > 0}
|
|
1728
|
-
<span class="history-count">{bond_undo_stack.length}</span>
|
|
1729
|
-
{/if}
|
|
1730
|
-
</button>
|
|
1731
|
-
<button
|
|
1732
|
-
type="button"
|
|
1733
|
-
aria-label="Redo bond edit (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1734
|
-
disabled={bond_redo_stack.length === 0}
|
|
1735
|
-
onclick={redo_bond_edit}
|
|
1736
|
-
title="Redo bond edit (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1737
|
-
class="undo-redo-btn"
|
|
1738
|
-
>
|
|
1739
|
-
<Icon icon="Redo" />
|
|
1740
|
-
{#if bond_redo_stack.length > 0}
|
|
1741
|
-
<span class="history-count">{bond_redo_stack.length}</span>
|
|
1742
|
-
{/if}
|
|
1743
|
-
</button>
|
|
1604
|
+
{#if measure_menu_open}
|
|
1605
|
+
<div class="view-mode-dropdown">
|
|
1606
|
+
{#each [
|
|
1607
|
+
{ mode: `distance`, icon: `Ruler`, label: `Distance`, scale: 1.1 },
|
|
1608
|
+
{ mode: `angle`, icon: `Angle`, label: `Angle`, scale: 1.3 },
|
|
1609
|
+
{ mode: `edit-atoms`, icon: `Edit`, label: `Edit Atoms`, scale: 1.0 },
|
|
1610
|
+
{ mode: `edit-bonds`, icon: `Link`, label: `Edit Bonds`, scale: 1.0 },
|
|
1611
|
+
] as const as { mode, icon, label, scale } (mode)}
|
|
1612
|
+
<button
|
|
1613
|
+
class="view-mode-option"
|
|
1614
|
+
class:selected={measure_mode === mode}
|
|
1615
|
+
disabled={mode === `edit-bonds` && !bond_edits_enabled}
|
|
1616
|
+
title={mode === `edit-bonds` && !bond_edits_enabled
|
|
1617
|
+
? `Bond editing is only available for the original 1x1x1 cell`
|
|
1618
|
+
: label}
|
|
1619
|
+
onclick={() => {
|
|
1620
|
+
if (mode === `edit-bonds` && !bond_edits_enabled) return
|
|
1621
|
+
;[measure_mode, measure_menu_open] = [mode, false]
|
|
1622
|
+
}}
|
|
1623
|
+
>
|
|
1624
|
+
<Icon {icon} style="transform: scale({scale})" />
|
|
1625
|
+
<span>{label}</span>
|
|
1626
|
+
</button>
|
|
1627
|
+
{/each}
|
|
1744
1628
|
</div>
|
|
1745
1629
|
{/if}
|
|
1630
|
+
</div>
|
|
1746
1631
|
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1632
|
+
<!-- Undo/redo buttons (only in edit-atoms mode) -->
|
|
1633
|
+
{#if measure_mode === `edit-atoms`}
|
|
1634
|
+
<div class="undo-redo-container">
|
|
1635
|
+
<button
|
|
1636
|
+
type="button"
|
|
1637
|
+
aria-label="Undo (Cmd/Ctrl+Z)"
|
|
1638
|
+
disabled={undo_stack.length === 0}
|
|
1639
|
+
onclick={undo}
|
|
1640
|
+
title="Undo (Cmd/Ctrl+Z)"
|
|
1641
|
+
class="undo-redo-btn"
|
|
1642
|
+
>
|
|
1643
|
+
<Icon icon="Undo" />
|
|
1644
|
+
{#if undo_stack.length > 0}
|
|
1645
|
+
<span class="history-count">{undo_stack.length}</span>
|
|
1646
|
+
{/if}
|
|
1647
|
+
</button>
|
|
1648
|
+
<button
|
|
1649
|
+
type="button"
|
|
1650
|
+
aria-label="Redo (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1651
|
+
disabled={redo_stack.length === 0}
|
|
1652
|
+
onclick={redo}
|
|
1653
|
+
title="Redo (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1654
|
+
class="undo-redo-btn"
|
|
1655
|
+
>
|
|
1656
|
+
<Icon icon="Redo" />
|
|
1657
|
+
{#if redo_stack.length > 0}
|
|
1658
|
+
<span class="history-count">{redo_stack.length}</span>
|
|
1659
|
+
{/if}
|
|
1660
|
+
</button>
|
|
1661
|
+
</div>
|
|
1662
|
+
{/if}
|
|
1763
1663
|
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
<div class="add-atom-input">
|
|
1664
|
+
{#if measure_mode === `edit-bonds`}
|
|
1665
|
+
<div class="bond-edit-toolbar" aria-label="Bond editing controls">
|
|
1666
|
+
{#if bond_edit_mode === `add`}
|
|
1768
1667
|
<label>
|
|
1769
|
-
<span>
|
|
1770
|
-
<
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
style="width: 3em; text-align: center"
|
|
1776
|
-
onkeydown={(event: KeyboardEvent) => {
|
|
1777
|
-
if (event.key === `Enter`) {
|
|
1778
|
-
handle_change_element(change_element_value)
|
|
1779
|
-
} else if (event.key === `Escape`) {
|
|
1780
|
-
change_element_mode = false
|
|
1781
|
-
}
|
|
1782
|
-
event.stopPropagation()
|
|
1783
|
-
}}
|
|
1784
|
-
{@attach (node: HTMLInputElement) => {
|
|
1785
|
-
node.focus()
|
|
1786
|
-
}}
|
|
1787
|
-
/>
|
|
1668
|
+
<span>Bond order</span>
|
|
1669
|
+
<select bind:value={bond_edit_order}>
|
|
1670
|
+
{#each BOND_ORDER_OPTIONS as { order, label } (label)}
|
|
1671
|
+
<option value={order}>{label}</option>
|
|
1672
|
+
{/each}
|
|
1673
|
+
</select>
|
|
1788
1674
|
</label>
|
|
1789
|
-
|
|
1675
|
+
{/if}
|
|
1676
|
+
<div class="bond-edit-mode-toggle">
|
|
1677
|
+
{#each [
|
|
1678
|
+
{ mode: `add`, label: `Add`, title: `Add: click two atoms` },
|
|
1679
|
+
{ mode: `delete`, label: `Delete`, title: `Delete: click a bond` },
|
|
1680
|
+
] as const as { mode, label, title } (mode)}
|
|
1681
|
+
<button
|
|
1682
|
+
type="button"
|
|
1683
|
+
class:selected={bond_edit_mode === mode}
|
|
1684
|
+
aria-pressed={bond_edit_mode === mode}
|
|
1685
|
+
title="{title} ({label[0]})"
|
|
1686
|
+
onclick={() => (bond_edit_mode = mode)}
|
|
1687
|
+
>
|
|
1688
|
+
{label}
|
|
1689
|
+
</button>
|
|
1690
|
+
{/each}
|
|
1790
1691
|
</div>
|
|
1791
|
-
|
|
1692
|
+
</div>
|
|
1693
|
+
<div class="undo-redo-container">
|
|
1694
|
+
<button
|
|
1695
|
+
type="button"
|
|
1696
|
+
aria-label="Undo bond edit (Cmd/Ctrl+Z)"
|
|
1697
|
+
disabled={bond_undo_stack.length === 0}
|
|
1698
|
+
onclick={undo_bond_edit}
|
|
1699
|
+
title="Undo bond edit (Cmd/Ctrl+Z)"
|
|
1700
|
+
class="undo-redo-btn"
|
|
1701
|
+
>
|
|
1702
|
+
<Icon icon="Undo" />
|
|
1703
|
+
{#if bond_undo_stack.length > 0}
|
|
1704
|
+
<span class="history-count">{bond_undo_stack.length}</span>
|
|
1705
|
+
{/if}
|
|
1706
|
+
</button>
|
|
1707
|
+
<button
|
|
1708
|
+
type="button"
|
|
1709
|
+
aria-label="Redo bond edit (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1710
|
+
disabled={bond_redo_stack.length === 0}
|
|
1711
|
+
onclick={redo_bond_edit}
|
|
1712
|
+
title="Redo bond edit (Cmd/Ctrl+Y or Cmd+Shift+Z)"
|
|
1713
|
+
class="undo-redo-btn"
|
|
1714
|
+
>
|
|
1715
|
+
<Icon icon="Redo" />
|
|
1716
|
+
{#if bond_redo_stack.length > 0}
|
|
1717
|
+
<span class="history-count">{bond_redo_stack.length}</span>
|
|
1718
|
+
{/if}
|
|
1719
|
+
</button>
|
|
1720
|
+
</div>
|
|
1792
1721
|
{/if}
|
|
1793
1722
|
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
<
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1723
|
+
<!-- Add-atom element input (shown when add_atom_mode is active) -->
|
|
1724
|
+
{#if measure_mode === `edit-atoms` && add_atom_mode}
|
|
1725
|
+
<div class="add-atom-input">
|
|
1726
|
+
<label>
|
|
1727
|
+
<span>Element:</span>
|
|
1728
|
+
<input
|
|
1729
|
+
type="text"
|
|
1730
|
+
bind:value={add_element}
|
|
1731
|
+
maxlength="2"
|
|
1732
|
+
placeholder="C"
|
|
1733
|
+
style="width: 3em; text-align: center"
|
|
1734
|
+
/>
|
|
1735
|
+
</label>
|
|
1736
|
+
<span style="font-size: 0.75em; opacity: 0.7">Click to place</span>
|
|
1737
|
+
</div>
|
|
1805
1738
|
{/if}
|
|
1806
1739
|
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1740
|
+
<!-- Change-element input (shown when 'e' pressed with selection) -->
|
|
1741
|
+
{#if measure_mode === `edit-atoms` && change_element_mode &&
|
|
1742
|
+
selected_sites.length > 0}
|
|
1743
|
+
<div class="add-atom-input">
|
|
1744
|
+
<label>
|
|
1745
|
+
<span>New element:</span>
|
|
1746
|
+
<input
|
|
1747
|
+
type="text"
|
|
1748
|
+
bind:value={change_element_value}
|
|
1749
|
+
maxlength="2"
|
|
1750
|
+
placeholder="Fe"
|
|
1751
|
+
style="width: 3em; text-align: center"
|
|
1752
|
+
onkeydown={(event: KeyboardEvent) => {
|
|
1753
|
+
if (event.key === `Enter`) {
|
|
1754
|
+
handle_change_element(change_element_value)
|
|
1755
|
+
} else if (event.key === `Escape`) {
|
|
1756
|
+
change_element_mode = false
|
|
1757
|
+
}
|
|
1758
|
+
event.stopPropagation()
|
|
1759
|
+
}}
|
|
1760
|
+
{@attach (node: HTMLInputElement) => {
|
|
1761
|
+
node.focus()
|
|
1762
|
+
}}
|
|
1763
|
+
/>
|
|
1764
|
+
</label>
|
|
1765
|
+
<span style="font-size: 0.75em; opacity: 0.7">Enter to apply</span>
|
|
1766
|
+
</div>
|
|
1817
1767
|
{/if}
|
|
1768
|
+
{/if}
|
|
1818
1769
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
bind:volumetric_data
|
|
1832
|
-
bind:isosurface_settings
|
|
1833
|
-
bind:active_volume_idx
|
|
1834
|
-
{structure}
|
|
1835
|
-
{supercell_loading}
|
|
1836
|
-
{sym_data}
|
|
1837
|
-
/>
|
|
1838
|
-
{/if}
|
|
1770
|
+
{#if enable_info_pane && normalized_structure &&
|
|
1771
|
+
controls_config.visible(`info-pane`)}
|
|
1772
|
+
<StructureInfoPane
|
|
1773
|
+
structure={normalized_structure}
|
|
1774
|
+
bind:pane_open={info_pane_open}
|
|
1775
|
+
bind:highlighted_sites
|
|
1776
|
+
bind:hovered_site_idx
|
|
1777
|
+
bind:selected_sites
|
|
1778
|
+
{sym_data}
|
|
1779
|
+
{@attach tooltip({ content: `Structure info pane` })}
|
|
1780
|
+
/>
|
|
1781
|
+
{/if}
|
|
1839
1782
|
|
|
1840
|
-
|
|
1783
|
+
{#if controls_config.visible(`export-pane`)}
|
|
1784
|
+
<StructureExportPane
|
|
1785
|
+
bind:export_pane_open
|
|
1786
|
+
structure={normalized_structure}
|
|
1787
|
+
{wrapper}
|
|
1788
|
+
{scene}
|
|
1789
|
+
{camera}
|
|
1790
|
+
bind:png_dpi
|
|
1791
|
+
pane_props={{ style: `max-height: calc(${height}px - 50px)` }}
|
|
1792
|
+
/>
|
|
1793
|
+
{/if}
|
|
1794
|
+
|
|
1795
|
+
{#if controls_config.visible(`controls`)}
|
|
1796
|
+
<StructureControls
|
|
1797
|
+
bind:controls_open
|
|
1798
|
+
bind:scene_props
|
|
1799
|
+
bind:lattice_props
|
|
1800
|
+
bind:show_image_atoms
|
|
1801
|
+
bind:supercell_scaling
|
|
1802
|
+
bind:background_color
|
|
1803
|
+
bind:background_opacity
|
|
1804
|
+
bind:color_scheme
|
|
1805
|
+
bind:atom_color_config
|
|
1806
|
+
bind:cell_type
|
|
1807
|
+
bind:volumetric_data
|
|
1808
|
+
bind:isosurface_settings
|
|
1809
|
+
bind:active_volume_idx
|
|
1810
|
+
{structure}
|
|
1811
|
+
{supercell_loading}
|
|
1812
|
+
{sym_data}
|
|
1813
|
+
{polyhedra_rendered_elements}
|
|
1814
|
+
/>
|
|
1841
1815
|
{/if}
|
|
1842
|
-
|
|
1816
|
+
|
|
1817
|
+
{@render top_right_controls?.()}
|
|
1818
|
+
</ViewerChrome>
|
|
1843
1819
|
|
|
1844
1820
|
<AtomLegend
|
|
1845
1821
|
bind:atom_color_config
|
|
@@ -1855,15 +1831,18 @@
|
|
|
1855
1831
|
show_mode_toggle={viewer_active}
|
|
1856
1832
|
{sym_data}
|
|
1857
1833
|
>
|
|
1858
|
-
{#
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1834
|
+
{#snippet children({ mode_menu_open })}
|
|
1835
|
+
{#if structure && `lattice` in structure}
|
|
1836
|
+
<CellSelect
|
|
1837
|
+
bind:supercell_scaling
|
|
1838
|
+
bind:cell_type
|
|
1839
|
+
{sym_data}
|
|
1840
|
+
loading={supercell_loading}
|
|
1841
|
+
direction="up"
|
|
1842
|
+
suppress_hover={mode_menu_open}
|
|
1843
|
+
/>
|
|
1844
|
+
{/if}
|
|
1845
|
+
{/snippet}
|
|
1867
1846
|
</AtomLegend>
|
|
1868
1847
|
|
|
1869
1848
|
<!-- prevent from rendering in vitest runner since WebGLRenderingContext not available -->
|
|
@@ -1912,6 +1891,7 @@
|
|
|
1912
1891
|
bind:add_element
|
|
1913
1892
|
bind:cursor={canvas_cursor}
|
|
1914
1893
|
bind:dragging_atoms
|
|
1894
|
+
bind:polyhedra_rendered_elements
|
|
1915
1895
|
/>
|
|
1916
1896
|
</Canvas>
|
|
1917
1897
|
</div>
|
|
@@ -1980,7 +1960,7 @@
|
|
|
1980
1960
|
}
|
|
1981
1961
|
/* Avoid accidental text selection while interacting with the viewer */
|
|
1982
1962
|
.structure :global(canvas),
|
|
1983
|
-
.structure section.control-buttons,
|
|
1963
|
+
.structure :global(section.control-buttons),
|
|
1984
1964
|
.structure .bottom-left {
|
|
1985
1965
|
user-select: none;
|
|
1986
1966
|
}
|
|
@@ -1991,44 +1971,6 @@
|
|
|
1991
1971
|
font-size: var(--struct-bottom-left-font-size, 1.2em);
|
|
1992
1972
|
padding: var(--struct-bottom-left-padding, 1pt 5pt);
|
|
1993
1973
|
}
|
|
1994
|
-
section.control-buttons {
|
|
1995
|
-
position: absolute;
|
|
1996
|
-
display: flex;
|
|
1997
|
-
top: var(--struct-buttons-top, var(--ctrl-btn-top, 1ex));
|
|
1998
|
-
right: var(--struct-buttons-right, var(--ctrl-btn-right, 1ex));
|
|
1999
|
-
gap: 4pt;
|
|
2000
|
-
/* buttons need higher z-index than AtomLegend to make info/controls panes occlude legend */
|
|
2001
|
-
/* we also need crazy high z-index to make info/control pane occlude threlte/extras' <HTML> elements for site labels */
|
|
2002
|
-
z-index: var(
|
|
2003
|
-
--struct-buttons-z-index,
|
|
2004
|
-
var(--z-index-overlay-controls, 100000000)
|
|
2005
|
-
);
|
|
2006
|
-
opacity: 0;
|
|
2007
|
-
pointer-events: none;
|
|
2008
|
-
transition: opacity 0.2s ease;
|
|
2009
|
-
}
|
|
2010
|
-
/* Mode: always - controls always visible */
|
|
2011
|
-
section.control-buttons.always-visible {
|
|
2012
|
-
opacity: 1;
|
|
2013
|
-
pointer-events: auto;
|
|
2014
|
-
}
|
|
2015
|
-
/* Mode: hover - controls visible on component hover */
|
|
2016
|
-
.structure:hover section.control-buttons.hover-visible,
|
|
2017
|
-
.structure:focus-within section.control-buttons.hover-visible {
|
|
2018
|
-
opacity: 1;
|
|
2019
|
-
pointer-events: auto;
|
|
2020
|
-
}
|
|
2021
|
-
/* Mode: never - stays hidden (default state, no additional CSS needed) */
|
|
2022
|
-
section.control-buttons > :global(button) {
|
|
2023
|
-
background-color: transparent;
|
|
2024
|
-
display: flex;
|
|
2025
|
-
padding: 1px 6px;
|
|
2026
|
-
border-radius: var(--border-radius, 3pt);
|
|
2027
|
-
font-size: clamp(0.85em, 2cqmin, 1.3em);
|
|
2028
|
-
}
|
|
2029
|
-
section.control-buttons :global(button:hover) {
|
|
2030
|
-
background-color: color-mix(in srgb, currentColor 8%, transparent);
|
|
2031
|
-
}
|
|
2032
1974
|
/* Match Trajectory dropdown UI */
|
|
2033
1975
|
.view-mode-dropdown {
|
|
2034
1976
|
position: absolute;
|