matterviz 0.3.7 → 0.4.0
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 +8 -3
- package/dist/brillouin/BrillouinZone.svelte.d.ts +2 -1
- package/dist/brillouin/BrillouinZoneScene.svelte +52 -6
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -0
- package/dist/brillouin/BrillouinZoneTooltip.svelte +16 -25
- package/dist/brillouin/compute.js +10 -14
- package/dist/chempot-diagram/ChemPotDiagram.svelte +14 -13
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +12 -15
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +8 -10
- package/dist/chempot-diagram/async-compute.svelte.js +3 -1
- package/dist/chempot-diagram/chempot-worker.js +2 -1
- package/dist/chempot-diagram/compute.d.ts +1 -1
- package/dist/chempot-diagram/compute.js +17 -19
- package/dist/colors/index.js +6 -5
- package/dist/composition/FormulaFilter.svelte +12 -6
- package/dist/composition/PieChart.svelte +6 -5
- package/dist/composition/chem-sys.d.ts +8 -0
- package/dist/composition/chem-sys.js +85 -0
- package/dist/composition/format.js +4 -2
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/composition/parse.js +25 -13
- package/dist/convex-hull/ConvexHull2D.svelte +12 -10
- package/dist/convex-hull/ConvexHull3D.svelte +5 -5
- package/dist/convex-hull/ConvexHull4D.svelte +5 -9
- package/dist/convex-hull/ConvexHullStats.svelte +12 -12
- package/dist/convex-hull/GasPressureControls.svelte +4 -4
- package/dist/convex-hull/TemperatureSlider.svelte +2 -2
- 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 +3 -0
- package/dist/convex-hull/helpers.js +17 -9
- package/dist/convex-hull/index.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +83 -78
- package/dist/convex-hull/types.d.ts +1 -1
- package/dist/coordination/CoordinationBarPlot.svelte +23 -23
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/element/ElementTile.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSlice.svelte +13 -5
- package/dist/fermi-surface/FermiSurface.svelte +11 -5
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +3 -0
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +8 -34
- package/dist/fermi-surface/compute.js +59 -59
- package/dist/fermi-surface/export.js +3 -2
- package/dist/fermi-surface/parse.js +7 -4
- package/dist/fermi-surface/types.d.ts +1 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +23 -21
- package/dist/heatmap-matrix/index.js +1 -1
- package/dist/io/decompress.js +4 -2
- package/dist/io/export.d.ts +4 -4
- package/dist/io/export.js +47 -25
- package/dist/io/fetch.js +5 -1
- package/dist/io/file-drop.d.ts +1 -1
- package/dist/io/file-drop.js +35 -36
- package/dist/io/url-drop.js +64 -33
- package/dist/isosurface/parse.js +6 -7
- 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 +8 -7
- package/dist/layout/PropertyFilter.svelte +3 -2
- package/dist/layout/SettingsSection.svelte +1 -1
- 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 +5 -1
- package/dist/math.js +24 -9
- package/dist/overlays/DraggablePane.svelte +4 -4
- package/dist/periodic-table/PeriodicTable.svelte +20 -9
- 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.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +1 -1
- package/dist/phase-diagram/build-diagram.js +2 -2
- 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} +229 -587
- package/dist/plot/{BarPlot.svelte.d.ts → bar/BarPlot.svelte.d.ts} +5 -5
- 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} +6 -6
- 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 +1462 -0
- package/dist/plot/box/BoxPlot.svelte.d.ts +94 -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 +55 -0
- package/dist/plot/box/box-plot.js +126 -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 +16 -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.js → core/auto-place.js} +2 -2
- 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} +36 -33
- package/dist/plot/{ColorBar.svelte.d.ts → core/components/ColorBar.svelte.d.ts} +2 -2
- 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} +30 -13
- package/dist/plot/{PlotAxis.svelte → core/components/PlotAxis.svelte} +7 -5
- package/dist/plot/{PlotAxis.svelte.d.ts → core/components/PlotAxis.svelte.d.ts} +3 -2
- 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} +4 -4
- package/dist/plot/{ReferenceLine3D.svelte.d.ts → core/components/ReferenceLine3D.svelte.d.ts} +2 -2
- package/dist/plot/{ReferencePlane.svelte → core/components/ReferencePlane.svelte} +7 -7
- package/dist/plot/{ReferencePlane.svelte.d.ts → core/components/ReferencePlane.svelte.d.ts} +2 -2
- 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} +3 -5
- 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 +33 -0
- package/dist/plot/core/fill-utils.js +388 -0
- package/dist/plot/{hover-lock.svelte.js → core/hover-lock.svelte.js} +5 -6
- package/dist/plot/core/index.d.ts +10 -0
- package/dist/plot/core/index.js +11 -0
- package/dist/plot/core/interactions.d.ts +35 -0
- package/dist/plot/core/interactions.js +195 -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/{reference-line.d.ts → core/reference-line.d.ts} +1 -1
- package/dist/plot/{reference-line.js → core/reference-line.js} +23 -36
- package/dist/plot/{scales.d.ts → core/scales.d.ts} +2 -2
- package/dist/plot/{scales.js → core/scales.js} +84 -85
- package/dist/plot/core/svg.d.ts +2 -0
- package/dist/plot/core/svg.js +41 -0
- package/dist/plot/{types.d.ts → core/types.d.ts} +19 -79
- package/dist/plot/{types.js → core/types.js} +1 -1
- package/dist/plot/{utils → core/utils}/label-placement.d.ts +2 -2
- 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 +11 -0
- package/dist/plot/core/utils.js +27 -0
- package/dist/plot/{Histogram.svelte → histogram/Histogram.svelte} +154 -294
- 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 +700 -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 +187 -0
- package/dist/plot/{BinnedScatterPlot.svelte → scatter/BinnedScatterPlot.svelte} +61 -59
- package/dist/plot/{BinnedScatterPlot.svelte.d.ts → scatter/BinnedScatterPlot.svelte.d.ts} +4 -4
- 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} +221 -642
- package/dist/plot/{ScatterPlot.svelte.d.ts → scatter/ScatterPlot.svelte.d.ts} +7 -7
- package/dist/plot/{ScatterPlotControls.svelte → scatter/ScatterPlotControls.svelte} +6 -5
- package/dist/plot/{ScatterPlotControls.svelte.d.ts → scatter/ScatterPlotControls.svelte.d.ts} +1 -1
- 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} +3 -3
- 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} +12 -10
- package/dist/plot/{ScatterPlot3D.svelte.d.ts → scatter-3d/ScatterPlot3D.svelte.d.ts} +7 -7
- package/dist/plot/{ScatterPlot3DControls.svelte → scatter-3d/ScatterPlot3DControls.svelte} +5 -4
- package/dist/plot/{ScatterPlot3DControls.svelte.d.ts → scatter-3d/ScatterPlot3DControls.svelte.d.ts} +2 -2
- package/dist/plot/{ScatterPlot3DScene.svelte → scatter-3d/ScatterPlot3DScene.svelte} +11 -11
- package/dist/plot/{ScatterPlot3DScene.svelte.d.ts → scatter-3d/ScatterPlot3DScene.svelte.d.ts} +3 -3
- package/dist/plot/{Surface3D.svelte → scatter-3d/Surface3D.svelte} +1 -1
- package/dist/plot/{Surface3D.svelte.d.ts → scatter-3d/Surface3D.svelte.d.ts} +1 -1
- 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 +1045 -0
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +96 -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 +266 -0
- package/dist/rdf/RdfPlot.svelte +2 -1
- package/dist/rdf/calc-rdf.js +11 -24
- package/dist/sanitize.js +1 -1
- package/dist/settings.d.ts +65 -1
- package/dist/settings.js +262 -0
- package/dist/spectral/Bands.svelte +39 -29
- package/dist/spectral/Bands.svelte.d.ts +3 -4
- package/dist/spectral/BandsAndDos.svelte +1 -1
- package/dist/spectral/BrillouinBandsDos.svelte +39 -27
- package/dist/spectral/Dos.svelte +10 -19
- package/dist/spectral/Dos.svelte.d.ts +2 -2
- package/dist/spectral/helpers.d.ts +3 -1
- package/dist/spectral/helpers.js +95 -29
- package/dist/structure/AtomLegend.svelte +8 -9
- package/dist/structure/CellSelect.svelte +1 -2
- package/dist/structure/Cylinder.svelte +12 -8
- package/dist/structure/Cylinder.svelte.d.ts +4 -1
- package/dist/structure/Structure.svelte +78 -72
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +5 -6
- package/dist/structure/StructureScene.svelte +11 -10
- package/dist/structure/atom-properties.js +6 -6
- package/dist/structure/bond-order-perception.js +1 -1
- package/dist/structure/bonding.d.ts +1 -0
- package/dist/structure/bonding.js +43 -15
- package/dist/structure/export.js +27 -23
- package/dist/structure/index.d.ts +2 -4
- package/dist/structure/index.js +1 -3
- package/dist/structure/label-placement.js +4 -4
- package/dist/structure/measure.d.ts +3 -2
- package/dist/structure/measure.js +6 -5
- package/dist/structure/parse.js +121 -103
- package/dist/structure/pbc.js +4 -0
- package/dist/symmetry/SymmetryStats.svelte +2 -2
- package/dist/symmetry/index.d.ts +1 -1
- package/dist/symmetry/index.js +22 -24
- package/dist/symmetry/spacegroups.d.ts +7 -0
- package/dist/symmetry/spacegroups.js +48 -13
- package/dist/table/HeatmapTable.svelte +63 -11
- 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 +66 -40
- package/dist/trajectory/Trajectory.svelte.d.ts +2 -1
- package/dist/trajectory/TrajectoryExportPane.svelte +2 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +2 -1
- package/dist/trajectory/format-detect.d.ts +1 -0
- package/dist/trajectory/format-detect.js +25 -11
- package/dist/trajectory/frame-reader.js +17 -50
- package/dist/trajectory/helpers.js +1 -1
- package/dist/trajectory/index.js +1 -1
- package/dist/trajectory/parse/hdf5.js +1 -1
- package/dist/trajectory/parse/index.js +14 -6
- package/dist/trajectory/parse/vasp.js +36 -17
- package/dist/trajectory/parse/xyz.d.ts +24 -0
- package/dist/trajectory/parse/xyz.js +102 -89
- package/dist/trajectory/plotting.d.ts +1 -1
- package/dist/trajectory/plotting.js +15 -15
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +6 -4
- package/dist/xrd/XrdPlot.svelte +2 -1
- package/dist/xrd/calc-xrd.js +15 -12
- package/dist/xrd/parse.js +2 -2
- package/package.json +22 -18
- 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/interactions.d.ts +0 -12
- package/dist/plot/interactions.js +0 -101
- 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/{auto-place.d.ts → core/auto-place.d.ts} +0 -0
- /package/dist/plot/{Line.svelte.d.ts → core/components/Line.svelte.d.ts} +0 -0
- /package/dist/plot/{PortalSelect.svelte.d.ts → core/components/PortalSelect.svelte.d.ts} +0 -0
- /package/dist/plot/{hover-lock.svelte.d.ts → core/hover-lock.svelte.d.ts} +0 -0
- /package/dist/plot/{utils → core/utils}/label-placement.js +0 -0
- /package/dist/plot/{binned-scatter-types.js → scatter/binned-scatter-types.js} +0 -0
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import Spinner from '../feedback/Spinner.svelte'
|
|
9
9
|
import Icon from '../Icon.svelte'
|
|
10
10
|
import { create_file_drop_handler, load_from_url } from '../io'
|
|
11
|
+
import { forward_window_keydown, handle_and_prevent } from '../keyboard'
|
|
11
12
|
import { parse_volumetric_file } from '../isosurface/parse'
|
|
12
13
|
import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types'
|
|
13
14
|
import {
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
import { get_property_colors } from './atom-properties'
|
|
57
58
|
import AtomLegend from './AtomLegend.svelte'
|
|
58
59
|
import CellSelect from './CellSelect.svelte'
|
|
59
|
-
import { BOND_ORDER_OPTIONS, merge_bond_edits } from './bonding'
|
|
60
|
+
import { BOND_ORDER_OPTIONS, merge_bond_edits, remap_bonds_after_deletion } from './bonding'
|
|
60
61
|
import type { StructureHandlerData } from './index'
|
|
61
62
|
import { MAX_SELECTED_SITES } from './measure'
|
|
62
63
|
import { normalize_fractional_coords, parse_any_structure } from './parse'
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
import StructureExportPane from './StructureExportPane.svelte'
|
|
65
66
|
import StructureInfoPane from './StructureInfoPane.svelte'
|
|
66
67
|
import StructureScene from './StructureScene.svelte'
|
|
68
|
+
import { to_error } from '../utils'
|
|
67
69
|
|
|
68
70
|
// Type alias for event handlers to reduce verbosity
|
|
69
71
|
type EventHandler = (data: StructureHandlerData) => void
|
|
@@ -302,7 +304,7 @@
|
|
|
302
304
|
emit_file_load_event(parsed, filename, content)
|
|
303
305
|
} catch (error) {
|
|
304
306
|
error_msg = `Failed to parse structure: ${
|
|
305
|
-
error
|
|
307
|
+
to_error(error).message
|
|
306
308
|
}`
|
|
307
309
|
on_error?.({ error_msg, filename })
|
|
308
310
|
}
|
|
@@ -333,7 +335,7 @@
|
|
|
333
335
|
}
|
|
334
336
|
} catch (err) {
|
|
335
337
|
error_msg = `Failed to parse structure from string: ${
|
|
336
|
-
err
|
|
338
|
+
to_error(err).message
|
|
337
339
|
}`
|
|
338
340
|
untrack(() => on_error?.({ error_msg, filename: `string` }))
|
|
339
341
|
} finally {
|
|
@@ -467,10 +469,13 @@
|
|
|
467
469
|
let bond_order_overrides = $state<StructureBond[]>([])
|
|
468
470
|
let bond_undo_stack = $state<BondEditHistorySnapshot[]>([])
|
|
469
471
|
let bond_redo_stack = $state<BondEditHistorySnapshot[]>([])
|
|
470
|
-
|
|
471
|
-
|
|
472
|
+
// These hold object-identity tokens (structure_identity) compared with ===/!==,
|
|
473
|
+
// so they must stay raw — proxying them via $state would break identity comparisons
|
|
474
|
+
// (state_proxy_equality_mismatch) against the raw `structure` prop.
|
|
475
|
+
let bond_history_context = $state.raw<BondEditContext>()
|
|
476
|
+
let last_bond_structure_identity = $state.raw(structure)
|
|
472
477
|
let last_emitted_bond_signature = $state<string>()
|
|
473
|
-
let bond_edit_snapshot = $state<BondEditSnapshot>()
|
|
478
|
+
let bond_edit_snapshot = $state.raw<BondEditSnapshot>()
|
|
474
479
|
let has_bond_edits = $derived(
|
|
475
480
|
added_bonds.length > 0 || removed_bonds.length > 0 ||
|
|
476
481
|
bond_order_overrides.length > 0,
|
|
@@ -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.
|
|
@@ -1477,6 +1498,11 @@
|
|
|
1477
1498
|
}}
|
|
1478
1499
|
/>
|
|
1479
1500
|
|
|
1501
|
+
<!-- Forward shortcuts to the hovered viewer when focus is on <body> (see
|
|
1502
|
+
forward_window_keydown). Edit modes are excluded so destructive keys
|
|
1503
|
+
(delete/undo) still require focus, not just a hovering mouse. -->
|
|
1504
|
+
<svelte:window onkeydown={forward_window_keydown(() => hovered, handle_hover_keydown)} />
|
|
1505
|
+
|
|
1480
1506
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
1481
1507
|
<div
|
|
1482
1508
|
class:dragover
|
|
@@ -1502,15 +1528,8 @@
|
|
|
1502
1528
|
if (!(target instanceof HTMLElement)) return
|
|
1503
1529
|
// Don't reset if double-click was on UI controls/panes/legend
|
|
1504
1530
|
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`
|
|
1531
|
+
[`.control-buttons`, `.structure-legend`, `.atom-legend`, `.info-pane`, `.export-pane`, `.controls-pane`].some((selector) => target.closest(selector))
|
|
1532
|
+
|| target.tagName === `BUTTON` || target.tagName === `INPUT` || target.tagName === `SELECT`
|
|
1514
1533
|
) return
|
|
1515
1534
|
// Reset camera for double-clicks on the 3D scene
|
|
1516
1535
|
reset_camera()
|
|
@@ -1525,7 +1544,7 @@
|
|
|
1525
1544
|
event.preventDefault()
|
|
1526
1545
|
dragover = false
|
|
1527
1546
|
}}
|
|
1528
|
-
onkeydown={handle_keydown}
|
|
1547
|
+
onkeydown={handle_and_prevent(handle_keydown)}
|
|
1529
1548
|
{...rest}
|
|
1530
1549
|
class="structure {rest.class ?? ``}"
|
|
1531
1550
|
>
|
|
@@ -1617,22 +1636,9 @@
|
|
|
1617
1636
|
{#each [
|
|
1618
1637
|
{ mode: `distance`, icon: `Ruler`, label: `Distance`, scale: 1.1 },
|
|
1619
1638
|
{ mode: `angle`, icon: `Angle`, label: `Angle`, scale: 1.3 },
|
|
1620
|
-
{
|
|
1621
|
-
|
|
1622
|
-
|
|
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
|
-
}
|
|
1639
|
+
{ mode: `edit-atoms`, icon: `Edit`, label: `Edit Atoms`, scale: 1.0 },
|
|
1640
|
+
{ mode: `edit-bonds`, icon: `Link`, label: `Edit Bonds`, scale: 1.0 },
|
|
1641
|
+
] as const as { mode, icon, label, scale } (mode)}
|
|
1636
1642
|
<button
|
|
1637
1643
|
class="view-mode-option"
|
|
1638
1644
|
class:selected={measure_mode === mode}
|
|
@@ -84,6 +84,6 @@ type $$ComponentProps = {
|
|
|
84
84
|
on_camera_reset?: EventHandler;
|
|
85
85
|
on_bonds_change?: (bonds: StructureBond[] | undefined) => void;
|
|
86
86
|
} & Omit<ComponentProps<typeof StructureControls>, `children` | `onclose`> & Omit<HTMLAttributes<HTMLDivElement>, `children`>;
|
|
87
|
-
declare const Structure: import("svelte").Component<$$ComponentProps, {}, "structure" | "height" | "width" | "
|
|
87
|
+
declare const Structure: import("svelte").Component<$$ComponentProps, {}, "structure" | "dragover" | "height" | "width" | "fullscreen" | "hovered" | "controls_open" | "loading" | "png_dpi" | "color_scheme" | "background_color" | "background_opacity" | "show_image_atoms" | "info_pane_open" | "wrapper" | "sym_data" | "error_msg" | "site_radius_overrides" | "atom_color_config" | "lattice_props" | "measure_mode" | "selected_sites" | "measured_sites" | "bond_edit_mode" | "bond_edit_order" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "volumetric_data" | "isosurface_settings" | "element_mapping" | "bonds" | "supercell_scaling" | "cell_type" | "active_volume_idx" | "scene_props" | "highlighted_sites" | "hovered_site_idx" | "enable_measure_mode" | "performance_mode" | "displayed_structure" | "symmetry_settings">;
|
|
88
88
|
type Structure = ReturnType<typeof Structure>;
|
|
89
89
|
export default Structure;
|
|
@@ -168,12 +168,11 @@
|
|
|
168
168
|
const get_element_name = (element: string): string =>
|
|
169
169
|
element_data?.find((element_record) => element_record.symbol === element)?.name || element
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
const site_summary = (card: SiteCard): string =>
|
|
172
|
+
[
|
|
173
173
|
card.element_name,
|
|
174
174
|
...card.details.map(({ label, value }) => `${label}: ${value}`),
|
|
175
175
|
].join(`; `)
|
|
176
|
-
}
|
|
177
176
|
|
|
178
177
|
function format_site_property(prop_key: string, prop_value: unknown): SiteDetail | null {
|
|
179
178
|
if (prop_value == null) return null
|
|
@@ -232,7 +231,7 @@
|
|
|
232
231
|
// Only display scalar values (skip arrays and objects)
|
|
233
232
|
if (value == null || typeof value === `object`) continue
|
|
234
233
|
structure_items.push({
|
|
235
|
-
label: key.
|
|
234
|
+
label: key.replaceAll('_', ` `).replaceAll(/\b\w/g, (char) => char.toUpperCase()),
|
|
236
235
|
value: String(value),
|
|
237
236
|
key: `structure-prop-${key}`,
|
|
238
237
|
})
|
|
@@ -281,7 +280,7 @@
|
|
|
281
280
|
international_short?: string
|
|
282
281
|
}).international_short
|
|
283
282
|
const space_group_symbol = (sym_data.hm_symbol ?? international_symbol)
|
|
284
|
-
?.
|
|
283
|
+
?.replaceAll(
|
|
285
284
|
/\s+/g,
|
|
286
285
|
``,
|
|
287
286
|
)
|
|
@@ -380,7 +379,7 @@
|
|
|
380
379
|
const selected_site_idx = selected_sites[0]
|
|
381
380
|
if (!pane_open || selected_site_idx === undefined) return
|
|
382
381
|
const visible_idx = visible_site_cards.findIndex(({ idx }) => idx === selected_site_idx)
|
|
383
|
-
if (visible_idx
|
|
382
|
+
if (visible_idx === -1) return
|
|
384
383
|
const selected_window_start = Math.floor(visible_idx / SITE_WINDOW_SIZE) *
|
|
385
384
|
SITE_WINDOW_SIZE
|
|
386
385
|
if (selected_window_start !== site_window_start) {
|
|
@@ -409,9 +409,8 @@
|
|
|
409
409
|
|
|
410
410
|
// Desaturate a color by blending it toward gray (for ghosting image atoms in edit mode)
|
|
411
411
|
const gray = new Color(0x999999)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
412
|
+
const desaturate = (hex: string | undefined, amount = 0.4): string =>
|
|
413
|
+
`#${new Color(hex ?? 0x999999).lerp(gray, amount).getHexString()}`
|
|
415
414
|
|
|
416
415
|
// === Edit-atoms mode state ===
|
|
417
416
|
let transform_object = $state<Mesh | undefined>(undefined)
|
|
@@ -1090,7 +1089,7 @@
|
|
|
1090
1089
|
|
|
1091
1090
|
const bond_directions_by_site = new SvelteMap<number, Vec3[]>()
|
|
1092
1091
|
const add_bond_direction = (site_idx: number, pos_1: Vec3, pos_2: Vec3) => {
|
|
1093
|
-
const direction = math.
|
|
1092
|
+
const direction = math.normalize_vec(
|
|
1094
1093
|
math.subtract(pos_2, pos_1),
|
|
1095
1094
|
[0, 0, 0],
|
|
1096
1095
|
)
|
|
@@ -1253,9 +1252,9 @@
|
|
|
1253
1252
|
let mean: Vec3 = [0, 0, 0]
|
|
1254
1253
|
for (const key of site_keys) {
|
|
1255
1254
|
const vec = vec_map.get(key)
|
|
1256
|
-
if (vec) mean = math.add(mean, math.
|
|
1255
|
+
if (vec) mean = math.add(mean, math.normalize_vec(vec)) as Vec3
|
|
1257
1256
|
}
|
|
1258
|
-
const mean_dir = math.
|
|
1257
|
+
const mean_dir = math.normalize_vec(mean, [0, 1, 0] as Vec3)
|
|
1259
1258
|
const [u_vec, v_vec] = math.compute_in_plane_basis(mean_dir)
|
|
1260
1259
|
const offsets = new SvelteMap<string, Vec3>()
|
|
1261
1260
|
for (const [idx, key] of site_keys.entries()) {
|
|
@@ -1317,7 +1316,7 @@
|
|
|
1317
1316
|
|
|
1318
1317
|
const offset = site_offsets?.[site_idx]?.get(key)
|
|
1319
1318
|
const position = offset ? math.add(site.xyz, offset) as Vec3 : site.xyz
|
|
1320
|
-
const arrow_vec = vector_normalize ? math.
|
|
1319
|
+
const arrow_vec = vector_normalize ? math.normalize_vec(vec) : vec
|
|
1321
1320
|
|
|
1322
1321
|
return {
|
|
1323
1322
|
site_idx,
|
|
@@ -2096,7 +2095,7 @@
|
|
|
2096
2095
|
] as Vec3}
|
|
2097
2096
|
{@const direct = math.euclidean_dist(pos_i, pos_j)}
|
|
2098
2097
|
{@const pbc = lattice
|
|
2099
|
-
? measure.distance_pbc(pos_i, pos_j, lattice.matrix)
|
|
2098
|
+
? measure.distance_pbc(pos_i, pos_j, lattice.matrix, undefined, lattice.pbc)
|
|
2100
2099
|
: direct}
|
|
2101
2100
|
{@const differ = lattice ? Math.abs(pbc - direct) > 1e-6 : false}
|
|
2102
2101
|
<extras.HTML center position={midpoint}>
|
|
@@ -2125,8 +2124,10 @@
|
|
|
2125
2124
|
}
|
|
2126
2125
|
{@const site_a = structure.sites[idx_a]}
|
|
2127
2126
|
{@const site_b = structure.sites[idx_b]}
|
|
2128
|
-
{@const
|
|
2129
|
-
|
|
2127
|
+
{@const disp = (to: Vec3) =>
|
|
2128
|
+
measure.displacement_pbc(center.xyz, to, lattice?.matrix, undefined, lattice?.pbc)}
|
|
2129
|
+
{@const v1 = disp(site_a.xyz)}
|
|
2130
|
+
{@const v2 = disp(site_b.xyz)}
|
|
2130
2131
|
{@const n1 = Math.hypot(v1[0], v1[1], v1[2])}
|
|
2131
2132
|
{@const n2 = Math.hypot(v2[0], v2[1], v2[2])}
|
|
2132
2133
|
{@const angle_deg = measure.angle_between_vectors(v1, v2, `degrees`)}
|
|
@@ -55,7 +55,7 @@ const build_prop_colors = (vals, colors, unique_values) => {
|
|
|
55
55
|
return { colors, values: vals, min_value, max_value, unique_values: uniq };
|
|
56
56
|
};
|
|
57
57
|
export function apply_color_scale(vals, scale = DEFAULT_COLOR_SCALE, type = `continuous`) {
|
|
58
|
-
if (
|
|
58
|
+
if (vals.length === 0)
|
|
59
59
|
return { colors: [] };
|
|
60
60
|
if (type === `categorical`) {
|
|
61
61
|
const result = make_categorical(vals, scale, (val_a, val_b) => val_a - val_b);
|
|
@@ -74,7 +74,7 @@ export function apply_color_scale(vals, scale = DEFAULT_COLOR_SCALE, type = `con
|
|
|
74
74
|
colors: vals.map((val) => to_hex(interp_fn, max === min ? 0.5 : (val - min) / (max - min))),
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
-
export const apply_categorical_color_scale = (vals, scale = DEFAULT_COLOR_SCALE) => vals.length ? make_categorical(vals, scale) : { colors: [], unique_values: [] };
|
|
77
|
+
export const apply_categorical_color_scale = (vals, scale = DEFAULT_COLOR_SCALE) => vals.length > 0 ? make_categorical(vals, scale) : { colors: [], unique_values: [] };
|
|
78
78
|
// Get original site index for property color lookup.
|
|
79
79
|
// Supercell atoms use orig_unit_cell_idx, image atoms use orig_site_idx, otherwise use site_idx.
|
|
80
80
|
export const get_orig_site_idx = (site, site_idx) => typeof site?.properties?.orig_unit_cell_idx === `number`
|
|
@@ -84,7 +84,7 @@ export const get_orig_site_idx = (site, site_idx) => typeof site?.properties?.or
|
|
|
84
84
|
: site_idx;
|
|
85
85
|
// Expand structure with PBC images - use minimal expansion based on atom positions
|
|
86
86
|
function expand_structure_for_pbc(structure) {
|
|
87
|
-
if (!(`lattice` in structure) || !structure.lattice ||
|
|
87
|
+
if (!(`lattice` in structure) || !structure.lattice || structure.sites.length === 0) {
|
|
88
88
|
return structure;
|
|
89
89
|
}
|
|
90
90
|
const { sites, lattice } = structure;
|
|
@@ -92,7 +92,7 @@ function expand_structure_for_pbc(structure) {
|
|
|
92
92
|
const pbc = lattice.pbc ?? [true, true, true];
|
|
93
93
|
const all_offsets = get_all_offsets(pbc);
|
|
94
94
|
// Small structures: expand all atoms
|
|
95
|
-
if (sites.length < 20 || !pbc.some(
|
|
95
|
+
if (sites.length < 20 || !pbc.some(Boolean)) {
|
|
96
96
|
const image_sites = sites.flatMap((site, orig_idx) => all_offsets.map((offset) => build_image_site(site, frac_to_cart, offset, orig_idx)));
|
|
97
97
|
return { ...structure, sites: [...sites, ...image_sites] };
|
|
98
98
|
}
|
|
@@ -113,7 +113,7 @@ export function get_coordination_colors(structure, strategy = `electroneg_ratio`
|
|
|
113
113
|
// Check if structure has periodic boundary conditions
|
|
114
114
|
const has_lattice = `lattice` in structure && structure.lattice !== undefined;
|
|
115
115
|
const pbc = has_lattice ? structure.lattice.pbc : undefined;
|
|
116
|
-
const has_pbc = has_lattice && (pbc === undefined || pbc.some(
|
|
116
|
+
const has_pbc = has_lattice && (pbc === undefined || pbc.some(Boolean));
|
|
117
117
|
// For PBC structures, expand with images from neighboring cells for accurate coordination
|
|
118
118
|
const coord_structure = has_pbc ? expand_structure_for_pbc(structure) : structure;
|
|
119
119
|
// Calculate coordination numbers on the (potentially expanded) structure
|
|
@@ -196,5 +196,5 @@ export function get_property_colors(structure, config, bonding_strategy, sym_dat
|
|
|
196
196
|
if (!structure || config.mode === `element`)
|
|
197
197
|
return null;
|
|
198
198
|
const result = get_atom_colors(structure, config, bonding_strategy, sym_data);
|
|
199
|
-
return result.colors.length ? result : null;
|
|
199
|
+
return result.colors.length > 0 ? result : null;
|
|
200
200
|
}
|
|
@@ -2,6 +2,7 @@ import type { Vec3 } from '../math';
|
|
|
2
2
|
import type { AnyStructure, BondOrder, BondPair, Site, StructureBond } from './';
|
|
3
3
|
export declare const normalize_structure_bond: (site_idx_1: number, site_idx_2: number, order: BondOrder, cell_shift?: Vec3) => StructureBond;
|
|
4
4
|
export declare const get_bond_key: (idx_1: number, idx_2: number, cell_shift?: Vec3) => string;
|
|
5
|
+
export declare function remap_bonds_after_deletion(bonds: readonly StructureBond[], deleted_indices: ReadonlySet<number>): StructureBond[];
|
|
5
6
|
export type BondEditState = {
|
|
6
7
|
added_bonds: StructureBond[];
|
|
7
8
|
removed_bonds: StructureBond[];
|
|
@@ -45,6 +45,31 @@ export const get_bond_key = (idx_1, idx_2, cell_shift) => {
|
|
|
45
45
|
const normalized = normalize_bond_endpoints(idx_1, idx_2, cell_shift);
|
|
46
46
|
return `${normalized.site_idx_1}-${normalized.site_idx_2}${format_cell_shift(normalized.cell_shift)}`;
|
|
47
47
|
};
|
|
48
|
+
// Remap explicit bond metadata after site deletion: drop bonds touching deleted
|
|
49
|
+
// sites and shift each surviving index down by the number of deleted indices below it.
|
|
50
|
+
export function remap_bonds_after_deletion(bonds, deleted_indices) {
|
|
51
|
+
// Sort the deleted indices once; shift each surviving index down by the count of deleted
|
|
52
|
+
// indices below it via binary search (O(log m) per lookup vs re-filtering the set each call).
|
|
53
|
+
const sorted = [...deleted_indices].sort((idx_a, idx_b) => idx_a - idx_b);
|
|
54
|
+
const shift = (idx) => {
|
|
55
|
+
let [lo, hi] = [0, sorted.length];
|
|
56
|
+
while (lo < hi) {
|
|
57
|
+
const mid = (lo + hi) >> 1;
|
|
58
|
+
if (sorted[mid] < idx)
|
|
59
|
+
lo = mid + 1;
|
|
60
|
+
else
|
|
61
|
+
hi = mid;
|
|
62
|
+
}
|
|
63
|
+
return idx - lo; // lo == count of deleted indices < idx
|
|
64
|
+
};
|
|
65
|
+
return bonds
|
|
66
|
+
.filter((bond) => !deleted_indices.has(bond.site_idx_1) && !deleted_indices.has(bond.site_idx_2))
|
|
67
|
+
.map((bond) => ({
|
|
68
|
+
...bond,
|
|
69
|
+
site_idx_1: shift(bond.site_idx_1),
|
|
70
|
+
site_idx_2: shift(bond.site_idx_2),
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
48
73
|
export const BOND_ORDER_OPTIONS = [
|
|
49
74
|
{ order: 1, label: `Single` },
|
|
50
75
|
{ order: 1.5, label: `1.5` },
|
|
@@ -364,23 +389,26 @@ export function scale_and_offset_bond_matrix(transform_matrix, offset, radius_sc
|
|
|
364
389
|
export function get_bond_render_matrices(bond, bond_thickness) {
|
|
365
390
|
const order = bond.bond_order ?? 1;
|
|
366
391
|
const gap = bond_thickness * 1.8;
|
|
367
|
-
|
|
368
|
-
|
|
392
|
+
// Parallel cylinder [offset, radius_scale] pairs per bond order; empty → a single
|
|
393
|
+
// full-width bond (handled by the fallback below)
|
|
394
|
+
let offsets_and_scales = [];
|
|
395
|
+
if (order === 2)
|
|
396
|
+
offsets_and_scales = [
|
|
369
397
|
[-gap / 2, 0.65],
|
|
370
398
|
[gap / 2, 0.65],
|
|
371
|
-
]
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
399
|
+
];
|
|
400
|
+
else if (order === 3)
|
|
401
|
+
offsets_and_scales = [
|
|
402
|
+
[-gap, 0.55],
|
|
403
|
+
[0, 0.55],
|
|
404
|
+
[gap, 0.55],
|
|
405
|
+
];
|
|
406
|
+
else if (order === 1.5 || order === `aromatic`) {
|
|
407
|
+
offsets_and_scales = [
|
|
408
|
+
[-gap / 2, 0.75],
|
|
409
|
+
[gap / 2, 0.4],
|
|
410
|
+
];
|
|
411
|
+
}
|
|
384
412
|
return offsets_and_scales.length === 0
|
|
385
413
|
? [bond.transform_matrix]
|
|
386
414
|
: offsets_and_scales.map(([offset, radius_scale]) => scale_and_offset_bond_matrix(bond.transform_matrix, offset, radius_scale));
|