matterviz 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte.d.ts +9 -0
- package/dist/FilePicker.svelte +360 -0
- package/dist/FilePicker.svelte.d.ts +17 -0
- package/dist/Icon.svelte.d.ts +13 -0
- package/dist/MillerIndexInput.svelte +66 -0
- package/dist/MillerIndexInput.svelte.d.ts +7 -0
- package/dist/api/mp.d.ts +6 -0
- package/dist/api/mp.js +22 -0
- package/dist/api/optimade.d.ts +45 -0
- package/dist/api/optimade.js +135 -0
- package/dist/brillouin/BrillouinZone.svelte +549 -0
- package/dist/brillouin/BrillouinZone.svelte.d.ts +83 -0
- package/dist/brillouin/BrillouinZoneControls.svelte +144 -0
- package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +17 -0
- package/dist/brillouin/BrillouinZoneExportPane.svelte +146 -0
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +15 -0
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +146 -0
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +13 -0
- package/dist/brillouin/BrillouinZoneScene.svelte +476 -0
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +48 -0
- package/dist/brillouin/BrillouinZoneTooltip.svelte +92 -0
- package/dist/brillouin/BrillouinZoneTooltip.svelte.d.ts +8 -0
- package/dist/brillouin/compute.d.ts +17 -0
- package/dist/brillouin/compute.js +426 -0
- package/dist/brillouin/index.d.ts +8 -0
- package/dist/brillouin/index.js +7 -0
- package/dist/brillouin/types.d.ts +43 -0
- package/dist/brillouin/types.js +1 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte +327 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +846 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +3193 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
- package/dist/chempot-diagram/async-compute.svelte.js +78 -0
- package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
- package/dist/chempot-diagram/chempot-worker.js +11 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +32 -0
- package/dist/chempot-diagram/compute.d.ts +48 -0
- package/dist/chempot-diagram/compute.js +806 -0
- package/dist/chempot-diagram/index.d.ts +6 -0
- package/dist/chempot-diagram/index.js +6 -0
- package/dist/chempot-diagram/pointer.d.ts +16 -0
- package/dist/chempot-diagram/pointer.js +40 -0
- package/dist/chempot-diagram/temperature.d.ts +15 -0
- package/dist/chempot-diagram/temperature.js +34 -0
- package/dist/chempot-diagram/types.d.ts +81 -0
- package/dist/chempot-diagram/types.js +28 -0
- package/dist/colors/index.d.ts +47 -0
- package/dist/colors/index.js +203 -0
- package/dist/composition/BarChart.svelte +297 -0
- package/dist/composition/BarChart.svelte.d.ts +39 -0
- package/dist/composition/BubbleChart.svelte +218 -0
- package/dist/composition/BubbleChart.svelte.d.ts +28 -0
- package/dist/composition/Composition.svelte +165 -0
- package/dist/composition/Composition.svelte.d.ts +15 -0
- package/dist/composition/Formula.svelte +268 -0
- package/dist/composition/Formula.svelte.d.ts +19 -0
- package/dist/composition/FormulaFilter.svelte +1257 -0
- package/dist/composition/FormulaFilter.svelte.d.ts +51 -0
- package/dist/composition/PieChart.svelte +323 -0
- package/dist/composition/PieChart.svelte.d.ts +37 -0
- package/dist/composition/format.d.ts +15 -0
- package/dist/composition/format.js +109 -0
- package/dist/composition/index.d.ts +20 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +56 -0
- package/dist/composition/parse.js +474 -0
- package/dist/constants.d.ts +29 -0
- package/dist/constants.js +99 -0
- package/dist/controls.d.ts +14 -0
- package/dist/controls.js +30 -0
- package/dist/convex-hull/ConvexHull.svelte +157 -0
- package/dist/convex-hull/ConvexHull.svelte.d.ts +13 -0
- package/dist/convex-hull/ConvexHull2D.svelte +825 -0
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +11 -0
- package/dist/convex-hull/ConvexHull3D.svelte +1801 -0
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +8 -0
- package/dist/convex-hull/ConvexHull4D.svelte +1398 -0
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +8 -0
- package/dist/convex-hull/ConvexHullControls.svelte +535 -0
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +48 -0
- package/dist/convex-hull/ConvexHullInfoPane.svelte +125 -0
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +20 -0
- package/dist/convex-hull/ConvexHullStats.svelte +929 -0
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +17 -0
- package/dist/convex-hull/ConvexHullTooltip.svelte +131 -0
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +33 -0
- package/dist/convex-hull/GasPressureControls.svelte +247 -0
- package/dist/convex-hull/GasPressureControls.svelte.d.ts +11 -0
- package/dist/convex-hull/StructurePopup.svelte +151 -0
- package/dist/convex-hull/StructurePopup.svelte.d.ts +18 -0
- package/dist/convex-hull/TemperatureSlider.svelte.d.ts +8 -0
- package/dist/convex-hull/barycentric-coords.d.ts +18 -0
- package/dist/convex-hull/barycentric-coords.js +182 -0
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +40 -0
- package/dist/convex-hull/gas-thermodynamics.d.ts +16 -0
- package/dist/convex-hull/gas-thermodynamics.js +314 -0
- package/dist/convex-hull/helpers.d.ts +114 -0
- package/dist/convex-hull/helpers.js +710 -0
- package/dist/convex-hull/index.d.ts +119 -0
- package/dist/convex-hull/index.js +58 -0
- package/dist/convex-hull/thermodynamics.d.ts +67 -0
- package/dist/convex-hull/thermodynamics.js +1752 -0
- package/dist/convex-hull/types.d.ts +162 -0
- package/dist/convex-hull/types.js +36 -0
- package/dist/coordination/CoordinationBarPlot.svelte +311 -0
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +30 -0
- package/dist/coordination/calc-coordination.d.ts +15 -0
- package/dist/coordination/calc-coordination.js +63 -0
- package/dist/coordination/index.d.ts +8 -0
- package/dist/coordination/index.js +7 -0
- package/dist/effects.svelte.d.ts +12 -0
- package/dist/effects.svelte.js +37 -0
- package/dist/element/BohrAtom.svelte.d.ts +20 -0
- package/dist/element/ElementHeading.svelte +26 -0
- package/dist/element/ElementHeading.svelte.d.ts +8 -0
- package/dist/element/ElementPhoto.svelte +57 -0
- package/dist/element/ElementPhoto.svelte.d.ts +9 -0
- package/dist/element/ElementStats.svelte +80 -0
- package/dist/element/ElementStats.svelte.d.ts +8 -0
- package/dist/element/ElementTile.svelte +484 -0
- package/dist/element/ElementTile.svelte.d.ts +29 -0
- package/dist/element/Nucleus.svelte.d.ts +17 -0
- package/dist/element/data.d.ts +2 -0
- package/dist/element/data.js +2 -0
- package/dist/element/index.d.ts +8 -0
- package/dist/element/index.js +7 -0
- package/dist/element/types.d.ts +57 -0
- package/dist/element/types.js +1 -0
- package/dist/feedback/ClickFeedback.svelte +58 -0
- package/dist/feedback/ClickFeedback.svelte.d.ts +12 -0
- package/dist/feedback/DragOverlay.svelte +42 -0
- package/dist/feedback/DragOverlay.svelte.d.ts +7 -0
- package/dist/feedback/Spinner.svelte.d.ts +7 -0
- package/dist/feedback/StatusMessage.svelte.d.ts +9 -0
- package/dist/feedback/index.d.ts +4 -0
- package/dist/feedback/index.js +4 -0
- package/dist/fermi-surface/FermiSlice.svelte +189 -0
- package/dist/fermi-surface/FermiSlice.svelte.d.ts +24 -0
- package/dist/fermi-surface/FermiSurface.svelte +600 -0
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +83 -0
- package/dist/fermi-surface/FermiSurfaceControls.svelte +448 -0
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +35 -0
- package/dist/fermi-surface/FermiSurfaceScene.svelte +794 -0
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +50 -0
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +111 -0
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte.d.ts +8 -0
- package/dist/fermi-surface/compute.d.ts +5 -0
- package/dist/fermi-surface/compute.js +538 -0
- package/dist/fermi-surface/constants.d.ts +9 -0
- package/dist/fermi-surface/constants.js +27 -0
- package/dist/fermi-surface/export.d.ts +5 -0
- package/dist/fermi-surface/export.js +50 -0
- package/dist/fermi-surface/index.d.ts +12 -0
- package/dist/fermi-surface/index.js +13 -0
- package/dist/fermi-surface/marching-cubes.d.ts +2 -0
- package/dist/fermi-surface/marching-cubes.js +2 -0
- package/dist/fermi-surface/parse.d.ts +2 -0
- package/dist/fermi-surface/parse.js +491 -0
- package/dist/fermi-surface/symmetry.d.ts +3 -0
- package/dist/fermi-surface/symmetry.js +46 -0
- package/dist/fermi-surface/types.d.ts +110 -0
- package/dist/fermi-surface/types.js +4 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1545 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +225 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +30 -0
- package/dist/heatmap-matrix/index.d.ts +53 -0
- package/dist/heatmap-matrix/index.js +100 -0
- package/dist/heatmap-matrix/shared.d.ts +2 -0
- package/dist/heatmap-matrix/shared.js +4 -0
- package/dist/icons.d.ts +569 -0
- package/dist/icons.js +648 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +39 -0
- package/dist/io/decompress.d.ts +11 -0
- package/dist/io/decompress.js +74 -0
- package/dist/io/export.d.ts +16 -0
- package/dist/io/export.js +316 -0
- package/dist/io/fetch.d.ts +5 -0
- package/dist/io/fetch.js +39 -0
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +43 -0
- package/dist/io/index.d.ts +7 -0
- package/dist/io/index.js +6 -0
- package/dist/io/is-binary.d.ts +1 -0
- package/dist/io/is-binary.js +20 -0
- package/dist/io/types.d.ts +8 -0
- package/dist/io/types.js +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +123 -0
- package/dist/isosurface/Isosurface.svelte +285 -0
- package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
- package/dist/isosurface/IsosurfaceControls.svelte +277 -0
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
- package/dist/isosurface/index.d.ts +5 -0
- package/dist/isosurface/index.js +6 -0
- package/dist/isosurface/parse.d.ts +6 -0
- package/dist/isosurface/parse.js +553 -0
- package/dist/isosurface/slice.d.ts +11 -0
- package/dist/isosurface/slice.js +140 -0
- package/dist/isosurface/types.d.ts +56 -0
- package/dist/isosurface/types.js +227 -0
- package/dist/labels.d.ts +53 -0
- package/dist/labels.js +277 -0
- package/dist/layout/FullscreenToggle.svelte +50 -0
- package/dist/layout/FullscreenToggle.svelte.d.ts +7 -0
- package/dist/layout/InfoCard.svelte +120 -0
- package/dist/layout/InfoCard.svelte.d.ts +21 -0
- package/dist/layout/InfoTag.svelte +185 -0
- package/dist/layout/InfoTag.svelte.d.ts +19 -0
- package/dist/layout/PropertyFilter.svelte +246 -0
- package/dist/layout/PropertyFilter.svelte.d.ts +24 -0
- package/dist/layout/SettingsSection.svelte +148 -0
- package/dist/layout/SettingsSection.svelte.d.ts +17 -0
- package/dist/layout/SubpageGrid.svelte +82 -0
- package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
- package/dist/layout/fullscreen.d.ts +9 -0
- package/dist/layout/fullscreen.js +53 -0
- package/dist/layout/index.d.ts +10 -0
- package/dist/layout/index.js +8 -0
- package/dist/layout/json-tree/JsonNode.svelte +548 -0
- package/dist/layout/json-tree/JsonNode.svelte.d.ts +11 -0
- package/dist/layout/json-tree/JsonTree.svelte +1230 -0
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +6 -0
- package/dist/layout/json-tree/JsonValue.svelte.d.ts +9 -0
- package/dist/layout/json-tree/index.d.ts +3 -0
- package/dist/layout/json-tree/index.js +3 -0
- package/dist/layout/json-tree/types.d.ts +74 -0
- package/dist/layout/json-tree/types.js +2 -0
- package/dist/layout/json-tree/utils.d.ts +29 -0
- package/dist/layout/json-tree/utils.js +641 -0
- package/dist/marching-cubes.d.ts +14 -0
- package/dist/marching-cubes.js +540 -0
- package/dist/math.d.ts +101 -0
- package/dist/math.js +905 -0
- package/dist/overlays/ContextMenu.svelte +162 -0
- package/dist/overlays/ContextMenu.svelte.d.ts +25 -0
- package/dist/overlays/CopyButton.svelte +45 -0
- package/dist/overlays/CopyButton.svelte.d.ts +8 -0
- package/dist/overlays/DragControlTab.svelte +98 -0
- package/dist/overlays/DragControlTab.svelte.d.ts +8 -0
- package/dist/overlays/DraggablePane.svelte +487 -0
- package/dist/overlays/DraggablePane.svelte.d.ts +36 -0
- package/dist/overlays/InfoPaneCards.svelte +149 -0
- package/dist/overlays/InfoPaneCards.svelte.d.ts +22 -0
- package/dist/overlays/index.d.ts +3 -0
- package/dist/overlays/index.js +3 -0
- package/dist/periodic-table/PeriodicTable.svelte +469 -0
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +55 -0
- package/dist/periodic-table/PeriodicTableControls.svelte +557 -0
- package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +24 -0
- package/dist/periodic-table/PropertySelect.svelte +37 -0
- package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
- package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
- package/dist/periodic-table/index.d.ts +10 -0
- package/dist/periodic-table/index.js +4 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +1086 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +44 -0
- package/dist/phase-diagram/PhaseDiagramControls.svelte +444 -0
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +30 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +126 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +184 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +19 -0
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +391 -0
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +16 -0
- package/dist/phase-diagram/TdbInfoPanel.svelte +203 -0
- package/dist/phase-diagram/TdbInfoPanel.svelte.d.ts +12 -0
- package/dist/phase-diagram/build-diagram.d.ts +11 -0
- package/dist/phase-diagram/build-diagram.js +160 -0
- package/dist/phase-diagram/colors.d.ts +35 -0
- package/dist/phase-diagram/colors.js +51 -0
- package/dist/phase-diagram/diagram-input.d.ts +29 -0
- package/dist/phase-diagram/diagram-input.js +3 -0
- package/dist/phase-diagram/index.d.ts +13 -0
- package/dist/phase-diagram/index.js +11 -0
- package/dist/phase-diagram/parse.d.ts +55 -0
- package/dist/phase-diagram/parse.js +272 -0
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +867 -0
- package/dist/phase-diagram/types.d.ts +93 -0
- package/dist/phase-diagram/types.js +1 -0
- package/dist/phase-diagram/utils.d.ts +118 -0
- package/dist/phase-diagram/utils.js +604 -0
- package/dist/plot/AxisLabel.svelte +51 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +2113 -0
- package/dist/plot/BarPlot.svelte.d.ts +84 -0
- package/dist/plot/BarPlotControls.svelte +66 -0
- package/dist/plot/BarPlotControls.svelte.d.ts +18 -0
- package/dist/plot/BinnedScatterPlot.svelte +1114 -0
- package/dist/plot/BinnedScatterPlot.svelte.d.ts +66 -0
- package/dist/plot/ColorBar.svelte +721 -0
- package/dist/plot/ColorBar.svelte.d.ts +31 -0
- package/dist/plot/ColorScaleSelect.svelte +54 -0
- package/dist/plot/ColorScaleSelect.svelte.d.ts +15 -0
- package/dist/plot/ElementScatter.svelte +63 -0
- package/dist/plot/ElementScatter.svelte.d.ts +14 -0
- package/dist/plot/FillArea.svelte.d.ts +21 -0
- package/dist/plot/Histogram.svelte +1558 -0
- package/dist/plot/Histogram.svelte.d.ts +50 -0
- package/dist/plot/HistogramControls.svelte +212 -0
- package/dist/plot/HistogramControls.svelte.d.ts +22 -0
- package/dist/plot/InteractiveAxisLabel.svelte +96 -0
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +14 -0
- package/dist/plot/Line.svelte +84 -0
- package/dist/plot/Line.svelte.d.ts +15 -0
- package/dist/plot/PlotAxis.svelte +169 -0
- package/dist/plot/PlotAxis.svelte.d.ts +24 -0
- package/dist/plot/PlotControls.svelte +537 -0
- package/dist/plot/PlotControls.svelte.d.ts +4 -0
- package/dist/plot/PlotLegend.svelte +569 -0
- package/dist/plot/PlotLegend.svelte.d.ts +29 -0
- package/dist/plot/PlotTooltip.svelte +67 -0
- package/dist/plot/PlotTooltip.svelte.d.ts +17 -0
- package/dist/plot/PortalSelect.svelte +253 -0
- package/dist/plot/PortalSelect.svelte.d.ts +16 -0
- package/dist/plot/ReferenceLine.svelte.d.ts +20 -0
- package/dist/plot/ReferenceLine3D.svelte +156 -0
- package/dist/plot/ReferenceLine3D.svelte.d.ts +14 -0
- package/dist/plot/ReferencePlane.svelte +175 -0
- package/dist/plot/ReferencePlane.svelte.d.ts +14 -0
- package/dist/plot/ScatterPlot.svelte +2778 -0
- package/dist/plot/ScatterPlot.svelte.d.ts +96 -0
- package/dist/plot/ScatterPlot3D.svelte +529 -0
- package/dist/plot/ScatterPlot3D.svelte.d.ts +95 -0
- package/dist/plot/ScatterPlot3DControls.svelte +437 -0
- package/dist/plot/ScatterPlot3DControls.svelte.d.ts +20 -0
- package/dist/plot/ScatterPlot3DScene.svelte +912 -0
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +74 -0
- package/dist/plot/ScatterPlotControls.svelte +306 -0
- package/dist/plot/ScatterPlotControls.svelte.d.ts +17 -0
- package/dist/plot/ScatterPoint.svelte +182 -0
- package/dist/plot/ScatterPoint.svelte.d.ts +22 -0
- package/dist/plot/SpacegroupBarPlot.svelte +293 -0
- package/dist/plot/SpacegroupBarPlot.svelte.d.ts +9 -0
- package/dist/plot/Surface3D.svelte +197 -0
- package/dist/plot/Surface3D.svelte.d.ts +13 -0
- package/dist/plot/ZeroLines.svelte +97 -0
- package/dist/plot/ZeroLines.svelte.d.ts +33 -0
- package/dist/plot/ZoomRect.svelte +23 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/adaptive-density.d.ts +69 -0
- package/dist/plot/adaptive-density.js +191 -0
- package/dist/plot/auto-place.d.ts +43 -0
- package/dist/plot/auto-place.js +122 -0
- package/dist/plot/axis-utils.d.ts +19 -0
- package/dist/plot/axis-utils.js +78 -0
- package/dist/plot/binned-scatter-types.d.ts +59 -0
- package/dist/plot/binned-scatter-types.js +1 -0
- package/dist/plot/data-cleaning.d.ts +37 -0
- package/dist/plot/data-cleaning.js +855 -0
- package/dist/plot/data-transform.d.ts +16 -0
- package/dist/plot/data-transform.js +45 -0
- package/dist/plot/defaults.d.ts +19 -0
- package/dist/plot/defaults.js +9 -0
- package/dist/plot/fill-utils.d.ts +46 -0
- package/dist/plot/fill-utils.js +322 -0
- package/dist/plot/hover-lock.svelte.d.ts +14 -0
- package/dist/plot/hover-lock.svelte.js +46 -0
- package/dist/plot/index.d.ts +41 -0
- package/dist/plot/index.js +39 -0
- package/dist/plot/interactions.d.ts +12 -0
- package/dist/plot/interactions.js +101 -0
- package/dist/plot/layout.d.ts +78 -0
- package/dist/plot/layout.js +273 -0
- package/dist/plot/reference-line.d.ts +60 -0
- package/dist/plot/reference-line.js +314 -0
- package/dist/plot/scales.d.ts +48 -0
- package/dist/plot/scales.js +481 -0
- package/dist/plot/svg.d.ts +1 -0
- package/dist/plot/svg.js +11 -0
- package/dist/plot/types.d.ts +831 -0
- package/dist/plot/types.js +99 -0
- package/dist/plot/utils/label-placement.d.ts +68 -0
- package/dist/plot/utils/label-placement.js +326 -0
- package/dist/plot/utils/series-visibility.d.ts +15 -0
- package/dist/plot/utils/series-visibility.js +85 -0
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +247 -0
- package/dist/rdf/RdfPlot.svelte.d.ts +27 -0
- package/dist/rdf/calc-rdf.d.ts +4 -0
- package/dist/rdf/calc-rdf.js +111 -0
- package/dist/rdf/index.d.ts +23 -0
- package/dist/rdf/index.js +2 -0
- package/dist/sanitize.d.ts +6 -0
- package/dist/sanitize.js +116 -0
- package/dist/settings.d.ts +255 -0
- package/dist/settings.js +1132 -0
- package/dist/spectral/Bands.svelte +1040 -0
- package/dist/spectral/Bands.svelte.d.ts +40 -0
- package/dist/spectral/BandsAndDos.svelte +134 -0
- package/dist/spectral/BandsAndDos.svelte.d.ts +18 -0
- package/dist/spectral/BrillouinBandsDos.svelte +252 -0
- package/dist/spectral/BrillouinBandsDos.svelte.d.ts +20 -0
- package/dist/spectral/Dos.svelte +697 -0
- package/dist/spectral/Dos.svelte.d.ts +29 -0
- package/dist/spectral/helpers.d.ts +119 -0
- package/dist/spectral/helpers.js +1032 -0
- package/dist/spectral/index.d.ts +6 -0
- package/dist/spectral/index.js +6 -0
- package/dist/spectral/types.d.ts +84 -0
- package/dist/spectral/types.js +2 -0
- package/dist/state.svelte.d.ts +25 -0
- package/dist/state.svelte.js +45 -0
- package/dist/structure/Arrow.svelte +72 -0
- package/dist/structure/Arrow.svelte.d.ts +15 -0
- package/dist/structure/AtomLegend.svelte +815 -0
- package/dist/structure/AtomLegend.svelte.d.ts +35 -0
- package/dist/structure/Bond.svelte +140 -0
- package/dist/structure/Bond.svelte.d.ts +9 -0
- package/dist/structure/CanvasTooltip.svelte +33 -0
- package/dist/structure/CanvasTooltip.svelte.d.ts +12 -0
- package/dist/structure/CellSelect.svelte +349 -0
- package/dist/structure/CellSelect.svelte.d.ts +13 -0
- package/dist/structure/Cylinder.svelte +45 -0
- package/dist/structure/Cylinder.svelte.d.ts +10 -0
- package/dist/structure/Lattice.svelte +196 -0
- package/dist/structure/Lattice.svelte.d.ts +17 -0
- package/dist/structure/Structure.svelte +2248 -0
- package/dist/structure/Structure.svelte.d.ts +89 -0
- package/dist/structure/StructureControls.svelte +1273 -0
- package/dist/structure/StructureControls.svelte.d.ts +31 -0
- package/dist/structure/StructureExportPane.svelte +252 -0
- package/dist/structure/StructureExportPane.svelte.d.ts +17 -0
- package/dist/structure/StructureInfoPane.svelte +737 -0
- package/dist/structure/StructureInfoPane.svelte.d.ts +19 -0
- package/dist/structure/StructureScene.svelte +2255 -0
- package/dist/structure/StructureScene.svelte.d.ts +111 -0
- package/dist/structure/atom-properties.d.ts +37 -0
- package/dist/structure/atom-properties.js +200 -0
- package/dist/structure/bond-order-perception.d.ts +13 -0
- package/dist/structure/bond-order-perception.js +384 -0
- package/dist/structure/bonding.d.ts +68 -0
- package/dist/structure/bonding.js +696 -0
- package/dist/structure/export.d.ts +20 -0
- package/dist/structure/export.js +727 -0
- package/dist/structure/index.d.ts +126 -0
- package/dist/structure/index.js +169 -0
- package/dist/structure/label-placement.d.ts +14 -0
- package/dist/structure/label-placement.js +72 -0
- package/dist/structure/measure.d.ts +6 -0
- package/dist/structure/measure.js +29 -0
- package/dist/structure/parse.d.ts +66 -0
- package/dist/structure/parse.js +1392 -0
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +99 -0
- package/dist/structure/pbc.d.ts +9 -0
- package/dist/structure/pbc.js +123 -0
- package/dist/structure/supercell.d.ts +8 -0
- package/dist/structure/supercell.js +170 -0
- package/dist/structure/validation.d.ts +2 -0
- package/dist/structure/validation.js +10 -0
- package/dist/symmetry/SymmetryStats.svelte +226 -0
- package/dist/symmetry/SymmetryStats.svelte.d.ts +21 -0
- package/dist/symmetry/WyckoffTable.svelte +120 -0
- package/dist/symmetry/WyckoffTable.svelte.d.ts +11 -0
- package/dist/symmetry/cell-transform.d.ts +12 -0
- package/dist/symmetry/cell-transform.js +91 -0
- package/dist/symmetry/index.d.ts +43 -0
- package/dist/symmetry/index.js +228 -0
- package/dist/symmetry/spacegroups.d.ts +9 -0
- package/dist/symmetry/spacegroups.js +394 -0
- package/dist/table/HeatmapTable.svelte +1833 -0
- package/dist/table/HeatmapTable.svelte.d.ts +49 -0
- package/dist/table/ToggleMenu.svelte +385 -0
- package/dist/table/ToggleMenu.svelte.d.ts +11 -0
- package/dist/table/index.d.ts +74 -0
- package/dist/table/index.js +38 -0
- package/dist/theme/ThemeControl.svelte +53 -0
- package/dist/theme/ThemeControl.svelte.d.ts +9 -0
- package/dist/theme/index.d.ts +29 -0
- package/dist/theme/index.js +79 -0
- package/dist/time.d.ts +4 -0
- package/dist/time.js +70 -0
- package/dist/tooltip/TooltipContent.svelte +58 -0
- package/dist/tooltip/TooltipContent.svelte.d.ts +31 -0
- package/dist/tooltip/index.d.ts +2 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/tooltip/types.d.ts +8 -0
- package/dist/tooltip/types.js +1 -0
- package/dist/trajectory/Trajectory.svelte +1545 -0
- package/dist/trajectory/Trajectory.svelte.d.ts +77 -0
- package/dist/trajectory/TrajectoryError.svelte +128 -0
- package/dist/trajectory/TrajectoryError.svelte.d.ts +13 -0
- package/dist/trajectory/TrajectoryExportPane.svelte +357 -0
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +17 -0
- package/dist/trajectory/TrajectoryInfoPane.svelte +313 -0
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +17 -0
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.d.ts +5 -0
- package/dist/trajectory/extract.js +162 -0
- package/dist/trajectory/format-detect.d.ts +9 -0
- package/dist/trajectory/format-detect.js +76 -0
- package/dist/trajectory/frame-reader.d.ts +17 -0
- package/dist/trajectory/frame-reader.js +332 -0
- package/dist/trajectory/helpers.d.ts +15 -0
- package/dist/trajectory/helpers.js +164 -0
- package/dist/trajectory/index.d.ts +63 -0
- package/dist/trajectory/index.js +126 -0
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +73 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +127 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +298 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +179 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +68 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +110 -0
- package/dist/trajectory/plotting.d.ts +28 -0
- package/dist/trajectory/plotting.js +423 -0
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +45 -0
- package/dist/xrd/XrdPlot.svelte +615 -0
- package/dist/xrd/XrdPlot.svelte.d.ts +28 -0
- package/dist/xrd/broadening.d.ts +20 -0
- package/dist/xrd/broadening.js +97 -0
- package/dist/xrd/calc-xrd.d.ts +37 -0
- package/dist/xrd/calc-xrd.js +336 -0
- package/dist/xrd/index.d.ts +37 -0
- package/dist/xrd/index.js +4 -0
- package/dist/xrd/parse.d.ts +13 -0
- package/dist/xrd/parse.js +749 -0
- package/license +1 -1
- package/package.json +232 -1457
- package/readme.md +98 -171
- package/.vscode/launch.json +0 -13
- package/.vscodeignore +0 -7
- package/dist/assets/STLExporter-BpTH3YHE.js +0 -8
- package/dist/assets/browser-DdDecX_W.js +0 -1
- package/dist/assets/export-qgn-H9y6.js +0 -2
- package/dist/assets/main-DiKYzti2.css +0 -1
- package/dist/assets/moyo_wasm_bg-0ocwg7xY.wasm +0 -0
- package/dist/extension.js +0 -31293
- package/dist/src/lib/FilePicker.svelte +0 -360
- package/dist/src/lib/MillerIndexInput.svelte +0 -66
- package/dist/src/lib/api/mp.ts +0 -26
- package/dist/src/lib/api/optimade.ts +0 -204
- package/dist/src/lib/brillouin/BrillouinZone.svelte +0 -549
- package/dist/src/lib/brillouin/BrillouinZoneControls.svelte +0 -144
- package/dist/src/lib/brillouin/BrillouinZoneExportPane.svelte +0 -146
- package/dist/src/lib/brillouin/BrillouinZoneInfoPane.svelte +0 -146
- package/dist/src/lib/brillouin/BrillouinZoneScene.svelte +0 -476
- package/dist/src/lib/brillouin/BrillouinZoneTooltip.svelte +0 -92
- package/dist/src/lib/brillouin/compute.ts +0 -529
- package/dist/src/lib/brillouin/index.ts +0 -8
- package/dist/src/lib/brillouin/types.ts +0 -51
- package/dist/src/lib/chempot-diagram/ChemPotDiagram.svelte +0 -327
- package/dist/src/lib/chempot-diagram/ChemPotDiagram2D.svelte +0 -846
- package/dist/src/lib/chempot-diagram/ChemPotDiagram3D.svelte +0 -3193
- package/dist/src/lib/chempot-diagram/async-compute.svelte.ts +0 -94
- package/dist/src/lib/chempot-diagram/chempot-worker.ts +0 -11
- package/dist/src/lib/chempot-diagram/color.ts +0 -42
- package/dist/src/lib/chempot-diagram/compute.ts +0 -1014
- package/dist/src/lib/chempot-diagram/index.ts +0 -6
- package/dist/src/lib/chempot-diagram/pointer.ts +0 -56
- package/dist/src/lib/chempot-diagram/temperature.ts +0 -77
- package/dist/src/lib/chempot-diagram/types.ts +0 -130
- package/dist/src/lib/colors/index.ts +0 -249
- package/dist/src/lib/composition/BarChart.svelte +0 -297
- package/dist/src/lib/composition/BubbleChart.svelte +0 -218
- package/dist/src/lib/composition/Composition.svelte +0 -165
- package/dist/src/lib/composition/Formula.svelte +0 -268
- package/dist/src/lib/composition/FormulaFilter.svelte +0 -1257
- package/dist/src/lib/composition/PieChart.svelte +0 -323
- package/dist/src/lib/composition/format.ts +0 -155
- package/dist/src/lib/composition/index.ts +0 -37
- package/dist/src/lib/composition/parse.ts +0 -605
- package/dist/src/lib/constants.ts +0 -134
- package/dist/src/lib/controls.ts +0 -42
- package/dist/src/lib/convex-hull/ConvexHull.svelte +0 -157
- package/dist/src/lib/convex-hull/ConvexHull2D.svelte +0 -825
- package/dist/src/lib/convex-hull/ConvexHull3D.svelte +0 -1801
- package/dist/src/lib/convex-hull/ConvexHull4D.svelte +0 -1398
- package/dist/src/lib/convex-hull/ConvexHullControls.svelte +0 -535
- package/dist/src/lib/convex-hull/ConvexHullInfoPane.svelte +0 -125
- package/dist/src/lib/convex-hull/ConvexHullStats.svelte +0 -929
- package/dist/src/lib/convex-hull/ConvexHullTooltip.svelte +0 -131
- package/dist/src/lib/convex-hull/GasPressureControls.svelte +0 -247
- package/dist/src/lib/convex-hull/StructurePopup.svelte +0 -151
- package/dist/src/lib/convex-hull/barycentric-coords.ts +0 -246
- package/dist/src/lib/convex-hull/demo-temperature.ts +0 -63
- package/dist/src/lib/convex-hull/gas-thermodynamics.ts +0 -405
- package/dist/src/lib/convex-hull/helpers.ts +0 -932
- package/dist/src/lib/convex-hull/index.ts +0 -202
- package/dist/src/lib/convex-hull/thermodynamics.ts +0 -2192
- package/dist/src/lib/convex-hull/types.ts +0 -267
- package/dist/src/lib/coordination/CoordinationBarPlot.svelte +0 -311
- package/dist/src/lib/coordination/calc-coordination.ts +0 -93
- package/dist/src/lib/coordination/index.ts +0 -9
- package/dist/src/lib/effects.svelte.ts +0 -48
- package/dist/src/lib/element/ElementHeading.svelte +0 -26
- package/dist/src/lib/element/ElementPhoto.svelte +0 -57
- package/dist/src/lib/element/ElementStats.svelte +0 -80
- package/dist/src/lib/element/ElementTile.svelte +0 -484
- package/dist/src/lib/element/data.ts +0 -14
- package/dist/src/lib/element/index.ts +0 -8
- package/dist/src/lib/element/types.ts +0 -62
- package/dist/src/lib/feedback/ClickFeedback.svelte +0 -58
- package/dist/src/lib/feedback/DragOverlay.svelte +0 -42
- package/dist/src/lib/feedback/index.ts +0 -4
- package/dist/src/lib/fermi-surface/FermiSlice.svelte +0 -189
- package/dist/src/lib/fermi-surface/FermiSurface.svelte +0 -600
- package/dist/src/lib/fermi-surface/FermiSurfaceControls.svelte +0 -448
- package/dist/src/lib/fermi-surface/FermiSurfaceScene.svelte +0 -794
- package/dist/src/lib/fermi-surface/FermiSurfaceTooltip.svelte +0 -111
- package/dist/src/lib/fermi-surface/compute.ts +0 -728
- package/dist/src/lib/fermi-surface/constants.ts +0 -32
- package/dist/src/lib/fermi-surface/export.ts +0 -64
- package/dist/src/lib/fermi-surface/index.ts +0 -14
- package/dist/src/lib/fermi-surface/marching-cubes.ts +0 -3
- package/dist/src/lib/fermi-surface/parse.ts +0 -574
- package/dist/src/lib/fermi-surface/symmetry.ts +0 -56
- package/dist/src/lib/fermi-surface/types.ts +0 -159
- package/dist/src/lib/heatmap-matrix/HeatmapMatrix.svelte +0 -1545
- package/dist/src/lib/heatmap-matrix/HeatmapMatrixControls.svelte +0 -225
- package/dist/src/lib/heatmap-matrix/index.ts +0 -167
- package/dist/src/lib/heatmap-matrix/shared.ts +0 -7
- package/dist/src/lib/icons.ts +0 -650
- package/dist/src/lib/index.ts +0 -61
- package/dist/src/lib/io/decompress.ts +0 -92
- package/dist/src/lib/io/export.ts +0 -385
- package/dist/src/lib/io/fetch.ts +0 -46
- package/dist/src/lib/io/file-drop.ts +0 -51
- package/dist/src/lib/io/index.ts +0 -7
- package/dist/src/lib/io/is-binary.ts +0 -24
- package/dist/src/lib/io/types.ts +0 -8
- package/dist/src/lib/io/url-drop.ts +0 -141
- package/dist/src/lib/isosurface/Isosurface.svelte +0 -285
- package/dist/src/lib/isosurface/IsosurfaceControls.svelte +0 -277
- package/dist/src/lib/isosurface/index.ts +0 -7
- package/dist/src/lib/isosurface/parse.ts +0 -656
- package/dist/src/lib/isosurface/slice.ts +0 -175
- package/dist/src/lib/isosurface/types.ts +0 -309
- package/dist/src/lib/labels.ts +0 -320
- package/dist/src/lib/layout/FullscreenToggle.svelte +0 -50
- package/dist/src/lib/layout/InfoCard.svelte +0 -120
- package/dist/src/lib/layout/InfoTag.svelte +0 -185
- package/dist/src/lib/layout/PropertyFilter.svelte +0 -246
- package/dist/src/lib/layout/SettingsSection.svelte +0 -148
- package/dist/src/lib/layout/SubpageGrid.svelte +0 -82
- package/dist/src/lib/layout/fullscreen.ts +0 -65
- package/dist/src/lib/layout/index.ts +0 -11
- package/dist/src/lib/layout/json-tree/JsonNode.svelte +0 -548
- package/dist/src/lib/layout/json-tree/JsonTree.svelte +0 -1230
- package/dist/src/lib/layout/json-tree/index.ts +0 -3
- package/dist/src/lib/layout/json-tree/types.ts +0 -126
- package/dist/src/lib/layout/json-tree/utils.ts +0 -682
- package/dist/src/lib/marching-cubes.ts +0 -614
- package/dist/src/lib/math.ts +0 -1081
- package/dist/src/lib/overlays/ContextMenu.svelte +0 -162
- package/dist/src/lib/overlays/CopyButton.svelte +0 -45
- package/dist/src/lib/overlays/DragControlTab.svelte +0 -98
- package/dist/src/lib/overlays/DraggablePane.svelte +0 -487
- package/dist/src/lib/overlays/InfoPaneCards.svelte +0 -149
- package/dist/src/lib/overlays/index.ts +0 -3
- package/dist/src/lib/periodic-table/PeriodicTable.svelte +0 -469
- package/dist/src/lib/periodic-table/PeriodicTableControls.svelte +0 -557
- package/dist/src/lib/periodic-table/PropertySelect.svelte +0 -37
- package/dist/src/lib/periodic-table/index.ts +0 -12
- package/dist/src/lib/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +0 -1086
- package/dist/src/lib/phase-diagram/PhaseDiagramControls.svelte +0 -444
- package/dist/src/lib/phase-diagram/PhaseDiagramEditorPane.svelte +0 -126
- package/dist/src/lib/phase-diagram/PhaseDiagramExportPane.svelte +0 -184
- package/dist/src/lib/phase-diagram/PhaseDiagramTooltip.svelte +0 -391
- package/dist/src/lib/phase-diagram/TdbInfoPanel.svelte +0 -203
- package/dist/src/lib/phase-diagram/build-diagram.ts +0 -186
- package/dist/src/lib/phase-diagram/colors.ts +0 -58
- package/dist/src/lib/phase-diagram/diagram-input.ts +0 -40
- package/dist/src/lib/phase-diagram/index.ts +0 -13
- package/dist/src/lib/phase-diagram/parse.ts +0 -348
- package/dist/src/lib/phase-diagram/svg-to-diagram.ts +0 -1023
- package/dist/src/lib/phase-diagram/types.ts +0 -144
- package/dist/src/lib/phase-diagram/utils.ts +0 -775
- package/dist/src/lib/plot/AxisLabel.svelte +0 -51
- package/dist/src/lib/plot/BarPlot.svelte +0 -2113
- package/dist/src/lib/plot/BarPlotControls.svelte +0 -66
- package/dist/src/lib/plot/BinnedScatterPlot.svelte +0 -1114
- package/dist/src/lib/plot/ColorBar.svelte +0 -721
- package/dist/src/lib/plot/ColorScaleSelect.svelte +0 -54
- package/dist/src/lib/plot/ElementScatter.svelte +0 -63
- package/dist/src/lib/plot/Histogram.svelte +0 -1558
- package/dist/src/lib/plot/HistogramControls.svelte +0 -212
- package/dist/src/lib/plot/InteractiveAxisLabel.svelte +0 -96
- package/dist/src/lib/plot/Line.svelte +0 -84
- package/dist/src/lib/plot/PlotAxis.svelte +0 -169
- package/dist/src/lib/plot/PlotControls.svelte +0 -537
- package/dist/src/lib/plot/PlotLegend.svelte +0 -569
- package/dist/src/lib/plot/PlotTooltip.svelte +0 -67
- package/dist/src/lib/plot/PortalSelect.svelte +0 -253
- package/dist/src/lib/plot/ReferenceLine3D.svelte +0 -156
- package/dist/src/lib/plot/ReferencePlane.svelte +0 -175
- package/dist/src/lib/plot/ScatterPlot.svelte +0 -2778
- package/dist/src/lib/plot/ScatterPlot3D.svelte +0 -529
- package/dist/src/lib/plot/ScatterPlot3DControls.svelte +0 -437
- package/dist/src/lib/plot/ScatterPlot3DScene.svelte +0 -912
- package/dist/src/lib/plot/ScatterPlotControls.svelte +0 -306
- package/dist/src/lib/plot/ScatterPoint.svelte +0 -182
- package/dist/src/lib/plot/SpacegroupBarPlot.svelte +0 -293
- package/dist/src/lib/plot/Surface3D.svelte +0 -197
- package/dist/src/lib/plot/ZeroLines.svelte +0 -97
- package/dist/src/lib/plot/ZoomRect.svelte +0 -23
- package/dist/src/lib/plot/adaptive-density.ts +0 -316
- package/dist/src/lib/plot/auto-place.ts +0 -184
- package/dist/src/lib/plot/axis-utils.ts +0 -122
- package/dist/src/lib/plot/binned-scatter-types.ts +0 -83
- package/dist/src/lib/plot/data-cleaning.ts +0 -1069
- package/dist/src/lib/plot/data-transform.ts +0 -69
- package/dist/src/lib/plot/defaults.ts +0 -9
- package/dist/src/lib/plot/fill-utils.ts +0 -494
- package/dist/src/lib/plot/hover-lock.svelte.ts +0 -60
- package/dist/src/lib/plot/index.ts +0 -53
- package/dist/src/lib/plot/interactions.ts +0 -119
- package/dist/src/lib/plot/layout.ts +0 -425
- package/dist/src/lib/plot/reference-line.ts +0 -426
- package/dist/src/lib/plot/scales.ts +0 -654
- package/dist/src/lib/plot/svg.ts +0 -23
- package/dist/src/lib/plot/types.ts +0 -1144
- package/dist/src/lib/plot/utils/label-placement.ts +0 -541
- package/dist/src/lib/plot/utils/series-visibility.ts +0 -140
- package/dist/src/lib/plot/utils.ts +0 -11
- package/dist/src/lib/rdf/RdfPlot.svelte +0 -247
- package/dist/src/lib/rdf/calc-rdf.ts +0 -167
- package/dist/src/lib/rdf/index.ts +0 -27
- package/dist/src/lib/sanitize.ts +0 -126
- package/dist/src/lib/settings.ts +0 -1479
- package/dist/src/lib/spectral/Bands.svelte +0 -1040
- package/dist/src/lib/spectral/BandsAndDos.svelte +0 -134
- package/dist/src/lib/spectral/BrillouinBandsDos.svelte +0 -252
- package/dist/src/lib/spectral/Dos.svelte +0 -697
- package/dist/src/lib/spectral/helpers.ts +0 -1381
- package/dist/src/lib/spectral/index.ts +0 -8
- package/dist/src/lib/spectral/types.ts +0 -112
- package/dist/src/lib/state.svelte.ts +0 -64
- package/dist/src/lib/structure/Arrow.svelte +0 -72
- package/dist/src/lib/structure/AtomLegend.svelte +0 -815
- package/dist/src/lib/structure/Bond.svelte +0 -140
- package/dist/src/lib/structure/CanvasTooltip.svelte +0 -33
- package/dist/src/lib/structure/CellSelect.svelte +0 -349
- package/dist/src/lib/structure/Cylinder.svelte +0 -45
- package/dist/src/lib/structure/Lattice.svelte +0 -196
- package/dist/src/lib/structure/Structure.svelte +0 -2248
- package/dist/src/lib/structure/StructureControls.svelte +0 -1273
- package/dist/src/lib/structure/StructureExportPane.svelte +0 -252
- package/dist/src/lib/structure/StructureInfoPane.svelte +0 -737
- package/dist/src/lib/structure/StructureScene.svelte +0 -2255
- package/dist/src/lib/structure/atom-properties.ts +0 -316
- package/dist/src/lib/structure/bond-order-perception.ts +0 -447
- package/dist/src/lib/structure/bonding.ts +0 -944
- package/dist/src/lib/structure/export.ts +0 -861
- package/dist/src/lib/structure/index.ts +0 -291
- package/dist/src/lib/structure/label-placement.ts +0 -130
- package/dist/src/lib/structure/measure.ts +0 -45
- package/dist/src/lib/structure/parse.ts +0 -1705
- package/dist/src/lib/structure/partial-occupancy.ts +0 -183
- package/dist/src/lib/structure/pbc.ts +0 -164
- package/dist/src/lib/structure/supercell.ts +0 -226
- package/dist/src/lib/structure/validation.ts +0 -11
- package/dist/src/lib/symmetry/SymmetryStats.svelte +0 -226
- package/dist/src/lib/symmetry/WyckoffTable.svelte +0 -120
- package/dist/src/lib/symmetry/cell-transform.ts +0 -118
- package/dist/src/lib/symmetry/index.ts +0 -348
- package/dist/src/lib/symmetry/spacegroups.ts +0 -404
- package/dist/src/lib/table/HeatmapTable.svelte +0 -1833
- package/dist/src/lib/table/ToggleMenu.svelte +0 -385
- package/dist/src/lib/table/index.ts +0 -139
- package/dist/src/lib/theme/ThemeControl.svelte +0 -53
- package/dist/src/lib/theme/index.ts +0 -107
- package/dist/src/lib/time.ts +0 -71
- package/dist/src/lib/tooltip/TooltipContent.svelte +0 -58
- package/dist/src/lib/tooltip/index.ts +0 -2
- package/dist/src/lib/tooltip/types.ts +0 -13
- package/dist/src/lib/trajectory/Trajectory.svelte +0 -1545
- package/dist/src/lib/trajectory/TrajectoryError.svelte +0 -128
- package/dist/src/lib/trajectory/TrajectoryExportPane.svelte +0 -357
- package/dist/src/lib/trajectory/TrajectoryInfoPane.svelte +0 -313
- package/dist/src/lib/trajectory/constants.ts +0 -7
- package/dist/src/lib/trajectory/extract.ts +0 -196
- package/dist/src/lib/trajectory/format-detect.ts +0 -96
- package/dist/src/lib/trajectory/frame-reader.ts +0 -456
- package/dist/src/lib/trajectory/helpers.ts +0 -217
- package/dist/src/lib/trajectory/index.ts +0 -218
- package/dist/src/lib/trajectory/parse/ase.ts +0 -109
- package/dist/src/lib/trajectory/parse/hdf5.ts +0 -173
- package/dist/src/lib/trajectory/parse/index.ts +0 -411
- package/dist/src/lib/trajectory/parse/lammps.ts +0 -215
- package/dist/src/lib/trajectory/parse/vasp.ts +0 -102
- package/dist/src/lib/trajectory/parse/xyz.ts +0 -143
- package/dist/src/lib/trajectory/plotting.ts +0 -599
- package/dist/src/lib/trajectory/types.ts +0 -13
- package/dist/src/lib/utils.ts +0 -56
- package/dist/src/lib/xrd/XrdPlot.svelte +0 -615
- package/dist/src/lib/xrd/broadening.ts +0 -130
- package/dist/src/lib/xrd/calc-xrd.ts +0 -397
- package/dist/src/lib/xrd/index.ts +0 -38
- package/dist/src/lib/xrd/parse.ts +0 -858
- package/dist/webview.js +0 -29421
- package/icon.png +0 -0
- package/matterviz-0.3.2.vsix +0 -0
- package/matterviz-0.3.4.vsix +0 -0
- package/matterviz-0.3.5.vsix +0 -0
- package/scripts/sync-config.ts +0 -101
- package/src/declarations.d.ts +0 -2
- package/src/extension.ts +0 -972
- package/src/node-io.ts +0 -65
- package/src/types.ts +0 -17
- package/src/webview/JsonBrowser.svelte +0 -1079
- package/src/webview/PlotPanel.svelte +0 -346
- package/src/webview/detect.ts +0 -444
- package/src/webview/main.ts +0 -764
- package/src/webview/plot-utils.ts +0 -250
- package/test-fixtures/all-viz-types.json.gz +0 -0
- package/test-fixtures/plot-demo-data.json.gz +0 -0
- package/tests/detect.test.ts +0 -604
- package/tests/extension.test.ts +0 -2041
- package/tests/node-io.test.ts +0 -39
- package/tests/plot-utils.test.ts +0 -302
- package/tests/vite-plugin-json-gz.test.ts +0 -114
- package/tests/vscode-mock.ts +0 -18
- package/tests/webview.test.ts +0 -231
- package/tsconfig.json +0 -20
- package/vite-plugin-json-gz.ts +0 -29
- package/vite.config.ts +0 -34
- package/vite.extension.config.ts +0 -34
- /package/dist/{src/lib/EmptyState.svelte → EmptyState.svelte} +0 -0
- /package/dist/{src/lib/Icon.svelte → Icon.svelte} +0 -0
- /package/dist/{src/lib/app.css → app.css} +0 -0
- /package/dist/{src/lib/chempot-diagram → chempot-diagram}/ChemPotScene3D.svelte +0 -0
- /package/dist/{src/lib/colors → colors}/alloy-colors.json +0 -0
- /package/dist/{src/lib/colors → colors}/dark-mode-colors.json +0 -0
- /package/dist/{src/lib/colors → colors}/jmol-colors.json +0 -0
- /package/dist/{src/lib/colors → colors}/muted-colors.json +0 -0
- /package/dist/{src/lib/colors → colors}/pastel-colors.json +0 -0
- /package/dist/{src/lib/colors → colors}/vesta-colors.json +0 -0
- /package/dist/{src/lib/convex-hull → convex-hull}/TemperatureSlider.svelte +0 -0
- /package/dist/{src/lib/element → element}/BohrAtom.svelte +0 -0
- /package/dist/{src/lib/element → element}/Nucleus.svelte +0 -0
- /package/dist/{src/lib/element → element}/data.json +0 -0
- /package/dist/{src/lib/element → element}/data.json.gz +0 -0
- /package/dist/{src/lib/element → element}/data.json.gz.d.ts +0 -0
- /package/dist/{src/lib/element → element}/data.schema.json +0 -0
- /package/dist/{src/lib/element-image-urls.json → element-image-urls.json} +0 -0
- /package/dist/{src/lib/feedback → feedback}/Spinner.svelte +0 -0
- /package/dist/{src/lib/feedback → feedback}/StatusMessage.svelte +0 -0
- /package/dist/{src/lib/layout → layout}/json-tree/JsonValue.svelte +0 -0
- /package/dist/{src/lib/periodic-table → periodic-table}/TableInset.svelte +0 -0
- /package/dist/{src/lib/plot → plot}/FillArea.svelte +0 -0
- /package/dist/{src/lib/plot → plot}/ReferenceLine.svelte +0 -0
- /package/dist/{src/lib/theme → theme}/themes.mjs +0 -0
- /package/dist/{src/lib/xrd → xrd}/atomic_scattering_params.json +0 -0
|
@@ -0,0 +1,1545 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ShowControlsProp } from '../controls'
|
|
3
|
+
import { normalize_show_controls } from '../controls'
|
|
4
|
+
import type { ElementSymbol } from '../element'
|
|
5
|
+
import EmptyState from '../EmptyState.svelte'
|
|
6
|
+
import Spinner from '../feedback/Spinner.svelte'
|
|
7
|
+
import Icon from '../Icon.svelte'
|
|
8
|
+
import { handle_url_drop, load_from_url } from '../io'
|
|
9
|
+
import { format_num, trajectory_property_config } from '../labels'
|
|
10
|
+
import { sanitize_html } from '../sanitize'
|
|
11
|
+
import { toggle_fullscreen } from '../layout'
|
|
12
|
+
import type { ControlsConfig, DataSeries, Orientation, Point } from '../plot'
|
|
13
|
+
import type { ScatterHandlerProps } from '../plot/types'
|
|
14
|
+
import { Histogram, ScatterPlot } from '../plot'
|
|
15
|
+
import { toggle_series_visibility } from '../plot/utils/series-visibility'
|
|
16
|
+
import { DEFAULTS } from '../settings'
|
|
17
|
+
import Structure from '../structure/Structure.svelte'
|
|
18
|
+
import { scaleLinear } from 'd3-scale'
|
|
19
|
+
import type { ComponentProps, Snippet } from 'svelte'
|
|
20
|
+
import { untrack } from 'svelte'
|
|
21
|
+
import { tooltip } from 'svelte-multiselect/attachments'
|
|
22
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
23
|
+
import { full_data_extractor } from './extract'
|
|
24
|
+
import type {
|
|
25
|
+
ParseProgress,
|
|
26
|
+
TrajectoryDataExtractor,
|
|
27
|
+
TrajectoryFrame,
|
|
28
|
+
TrajectoryType,
|
|
29
|
+
TrajHandlerData,
|
|
30
|
+
} from './index'
|
|
31
|
+
import { TrajectoryError, TrajectoryExportPane, TrajectoryInfoPane } from './index'
|
|
32
|
+
import type { AtomTypeMapping, LoadingOptions } from './parse'
|
|
33
|
+
import {
|
|
34
|
+
create_frame_loader,
|
|
35
|
+
get_unsupported_format_message,
|
|
36
|
+
MAX_BIN_FILE_SIZE,
|
|
37
|
+
MAX_TEXT_FILE_SIZE,
|
|
38
|
+
parse_trajectory_async,
|
|
39
|
+
} from './parse'
|
|
40
|
+
import {
|
|
41
|
+
generate_axis_labels,
|
|
42
|
+
generate_plot_series,
|
|
43
|
+
generate_streaming_plot_series,
|
|
44
|
+
should_hide_plot,
|
|
45
|
+
} from './plotting'
|
|
46
|
+
|
|
47
|
+
type EventHandlers = {
|
|
48
|
+
on_play?: (data: TrajHandlerData) => void
|
|
49
|
+
on_pause?: (data: TrajHandlerData) => void
|
|
50
|
+
on_step_change?: (data: TrajHandlerData) => void
|
|
51
|
+
on_end?: (data: TrajHandlerData) => void
|
|
52
|
+
on_loop?: (data: TrajHandlerData) => void
|
|
53
|
+
on_frame_rate_change?: (data: TrajHandlerData) => void
|
|
54
|
+
on_display_mode_change?: (data: TrajHandlerData) => void
|
|
55
|
+
on_fullscreen_change?: (data: TrajHandlerData) => void
|
|
56
|
+
on_file_load?: (data: TrajHandlerData) => void
|
|
57
|
+
on_error?: (data: TrajHandlerData) => void
|
|
58
|
+
}
|
|
59
|
+
type ControlsProps = {
|
|
60
|
+
trajectory: TrajectoryType
|
|
61
|
+
current_step_idx: number
|
|
62
|
+
total_frames: number
|
|
63
|
+
on_step_change: (idx: number) => void
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let {
|
|
67
|
+
trajectory = $bindable(),
|
|
68
|
+
data_url,
|
|
69
|
+
current_step_idx = $bindable(0),
|
|
70
|
+
data_extractor = full_data_extractor,
|
|
71
|
+
allow_file_drop = true,
|
|
72
|
+
layout = `auto`,
|
|
73
|
+
structure_props = {},
|
|
74
|
+
scatter_props = {},
|
|
75
|
+
histogram_props = {},
|
|
76
|
+
spinner_props = {},
|
|
77
|
+
trajectory_controls,
|
|
78
|
+
error_snippet,
|
|
79
|
+
show_controls,
|
|
80
|
+
fullscreen_toggle = DEFAULTS.trajectory.fullscreen_toggle,
|
|
81
|
+
auto_play = false,
|
|
82
|
+
display_mode = $bindable(`structure+scatter`),
|
|
83
|
+
step_labels = 5,
|
|
84
|
+
visible_properties = $bindable(),
|
|
85
|
+
ELEM_PROPERTY_LABELS,
|
|
86
|
+
on_play,
|
|
87
|
+
on_pause,
|
|
88
|
+
on_step_change,
|
|
89
|
+
on_end,
|
|
90
|
+
on_loop,
|
|
91
|
+
on_frame_rate_change,
|
|
92
|
+
on_display_mode_change,
|
|
93
|
+
on_fullscreen_change,
|
|
94
|
+
on_file_load,
|
|
95
|
+
on_error,
|
|
96
|
+
fps_range = DEFAULTS.trajectory.fps_range,
|
|
97
|
+
fps = $bindable(5),
|
|
98
|
+
loading_options = {},
|
|
99
|
+
atom_type_mapping,
|
|
100
|
+
plot_skimming = true,
|
|
101
|
+
...rest
|
|
102
|
+
}: EventHandlers & HTMLAttributes<HTMLDivElement> & {
|
|
103
|
+
// trajectory data - can be provided directly or loaded from file
|
|
104
|
+
trajectory?: TrajectoryType
|
|
105
|
+
// URL to load trajectory from (alternative to providing trajectory directly)
|
|
106
|
+
data_url?: string
|
|
107
|
+
// current step index being displayed
|
|
108
|
+
current_step_idx?: number
|
|
109
|
+
// custom function to extract plot data from trajectory frames
|
|
110
|
+
data_extractor?: TrajectoryDataExtractor
|
|
111
|
+
|
|
112
|
+
// file drop handlers
|
|
113
|
+
allow_file_drop?: boolean
|
|
114
|
+
// layout configuration - 'auto' (default) adapts to element size, 'horizontal'/'vertical' forces layout
|
|
115
|
+
layout?: `auto` | Orientation
|
|
116
|
+
// structure viewer props (passed to Structure component)
|
|
117
|
+
structure_props?: ComponentProps<typeof Structure>
|
|
118
|
+
// plot props (passed to ScatterPlot component)
|
|
119
|
+
scatter_props?: ComponentProps<typeof ScatterPlot>
|
|
120
|
+
// histogram props (passed to Histogram component, excluding series which is handled separately)
|
|
121
|
+
histogram_props?: Omit<ComponentProps<typeof Histogram>, `series`>
|
|
122
|
+
// spinner props (passed to Spinner component)
|
|
123
|
+
spinner_props?: ComponentProps<typeof Spinner>
|
|
124
|
+
// custom snippets for additional UI elements
|
|
125
|
+
trajectory_controls?: Snippet<[ControlsProps]>
|
|
126
|
+
// Custom error snippet for advanced error handling
|
|
127
|
+
error_snippet?: Snippet<[{ error_msg: string; on_dismiss: () => void }]>
|
|
128
|
+
// Controls visibility configuration.
|
|
129
|
+
// - 'always': controls always visible
|
|
130
|
+
// - 'hover': controls visible on component hover (default)
|
|
131
|
+
// - 'never': controls never visible
|
|
132
|
+
// - object: { mode, hidden, style } for fine-grained control
|
|
133
|
+
// Control names: 'filename', 'nav', 'step', 'fps', 'info-pane', 'export-pane', 'view-mode', 'fullscreen'
|
|
134
|
+
show_controls?: ShowControlsProp
|
|
135
|
+
// show/hide the fullscreen button
|
|
136
|
+
fullscreen_toggle?: Snippet<[{ fullscreen: boolean }]> | boolean
|
|
137
|
+
// automatically start playing when trajectory data is loaded
|
|
138
|
+
auto_play?: boolean
|
|
139
|
+
// display mode: 'structure+scatter' (default), 'structure' (only structure), 'scatter' (only scatter), 'histogram' (only histogram), 'structure+histogram' (structure with histogram)
|
|
140
|
+
display_mode?:
|
|
141
|
+
| `structure+scatter`
|
|
142
|
+
| `structure`
|
|
143
|
+
| `scatter`
|
|
144
|
+
| `histogram`
|
|
145
|
+
| `structure+histogram`
|
|
146
|
+
// step labels configuration for slider
|
|
147
|
+
// - positive number: number of evenly spaced ticks
|
|
148
|
+
// - negative number: spacing between ticks (e.g. -10 = every 10th step)
|
|
149
|
+
// - array: exact step indices to label
|
|
150
|
+
// - undefined: no labels
|
|
151
|
+
step_labels?: number | number[]
|
|
152
|
+
// visible properties - bindable array of property keys currently shown in the plot
|
|
153
|
+
// - controls which trajectory properties are plotted (e.g. ['energy', 'volume', 'force_max'])
|
|
154
|
+
// - bindable: reflects current visibility state and can be used for external control
|
|
155
|
+
// - if not provided, uses default visible properties (energy, force_max, stress_frobenius)
|
|
156
|
+
// - if specified properties don't exist in data, falls back to automatic selection
|
|
157
|
+
visible_properties?: string[]
|
|
158
|
+
// custom labels for trajectory properties - maps property keys to display labels
|
|
159
|
+
// - e.g. {energy: 'Total Energy', volume: 'Cell Volume', force_max: 'Max Force'}
|
|
160
|
+
// - merged with built-in trajectory_property_config
|
|
161
|
+
ELEM_PROPERTY_LABELS?: Record<string, string>
|
|
162
|
+
// units configuration - developers can override these (deprecated - use ELEM_PROPERTY_LABELS instead)
|
|
163
|
+
units?: {
|
|
164
|
+
energy?: string
|
|
165
|
+
energy_per_atom?: string
|
|
166
|
+
force_max?: string
|
|
167
|
+
force_norm?: string
|
|
168
|
+
stress_max?: string
|
|
169
|
+
volume?: string
|
|
170
|
+
density?: string
|
|
171
|
+
temperature?: string
|
|
172
|
+
pressure?: string
|
|
173
|
+
length?: string
|
|
174
|
+
a?: string
|
|
175
|
+
b?: string
|
|
176
|
+
c?: string
|
|
177
|
+
[key: string]: string | undefined
|
|
178
|
+
}
|
|
179
|
+
fps_range?: [number, number] // allowed FPS range [min_fps, max_fps]
|
|
180
|
+
fps?: number // frame rate for playback
|
|
181
|
+
// Loading options for large files
|
|
182
|
+
loading_options?: LoadingOptions
|
|
183
|
+
// Map LAMMPS atom types to element symbols (e.g. {1: 'Na', 2: 'Cl'})
|
|
184
|
+
atom_type_mapping?: AtomTypeMapping
|
|
185
|
+
// Disable plot skimming (mouse over plot doesn't update structure/step slider)
|
|
186
|
+
plot_skimming?: boolean
|
|
187
|
+
} = $props()
|
|
188
|
+
|
|
189
|
+
let dragover = $state(false)
|
|
190
|
+
let loading = $state(false)
|
|
191
|
+
let error_msg = $state<string | null>(null)
|
|
192
|
+
let is_playing = $state(false)
|
|
193
|
+
let play_interval: ReturnType<typeof setInterval> | undefined = $state(undefined)
|
|
194
|
+
|
|
195
|
+
// Ensure fps is within the allowed range
|
|
196
|
+
$effect(() => {
|
|
197
|
+
if (fps < fps_range[0]) {
|
|
198
|
+
fps = fps_range[0]
|
|
199
|
+
} else if (fps > fps_range[1]) {
|
|
200
|
+
fps = fps_range[1]
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
let current_filename = $state<string | undefined>(undefined)
|
|
204
|
+
let current_file_path = $state<string | null>(null)
|
|
205
|
+
let file_size = $state<number | undefined>(undefined)
|
|
206
|
+
let file_object = $state<File | null>(null)
|
|
207
|
+
let wrapper = $state<HTMLDivElement | undefined>(undefined)
|
|
208
|
+
let info_pane_open = $state(false)
|
|
209
|
+
let parsing_progress = $state<ParseProgress | null>(null)
|
|
210
|
+
let element_size = $state({ width: 0, height: 0 })
|
|
211
|
+
let filename_copied = $state(false)
|
|
212
|
+
let orig_data = $state<string | ArrayBuffer | null>(null)
|
|
213
|
+
|
|
214
|
+
let controls_config = $derived(normalize_show_controls(show_controls))
|
|
215
|
+
|
|
216
|
+
// Reactive layout based on element aspect ratio (for auto mode)
|
|
217
|
+
let actual_layout = $derived.by(() => {
|
|
218
|
+
if (layout === `horizontal` || layout === `vertical`) return layout
|
|
219
|
+
// For auto layout, use element dimensions to determine orientation
|
|
220
|
+
if (element_size.width > 0 && element_size.height > 0) {
|
|
221
|
+
return element_size.width > element_size.height ? `horizontal` : `vertical`
|
|
222
|
+
}
|
|
223
|
+
return `horizontal` // Fallback to horizontal if dimensions not available yet
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// Get total frame count (supports both regular and indexed trajectories)
|
|
227
|
+
let total_frames = $derived(
|
|
228
|
+
trajectory?.total_frames || trajectory?.frames.length || 0,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
// Current frame - load on demand for indexed trajectories
|
|
232
|
+
let current_frame = $state<TrajectoryFrame | null>(null)
|
|
233
|
+
let frame_load_request_id = 0
|
|
234
|
+
|
|
235
|
+
// Auto-play when trajectory changes (handles both props and file loading)
|
|
236
|
+
$effect(() => {
|
|
237
|
+
if (auto_play && trajectory && !untrack(() => is_playing) && total_frames > 1) {
|
|
238
|
+
start_playback()
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
// Update current frame when step changes
|
|
243
|
+
$effect(() => {
|
|
244
|
+
if (trajectory && current_step_idx >= 0 && current_step_idx < total_frames) {
|
|
245
|
+
if (trajectory.frame_loader) {
|
|
246
|
+
// Load frame on demand (works for both indexed files and external streaming)
|
|
247
|
+
load_frame_on_demand(current_step_idx)
|
|
248
|
+
} else {
|
|
249
|
+
// Use in-memory frame for regular trajectories
|
|
250
|
+
current_frame = trajectory.frames[current_step_idx] || null
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
current_frame = null
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
// Load frame on demand - works for both indexed files and external streaming
|
|
258
|
+
async function load_frame_on_demand(frame_idx: number) {
|
|
259
|
+
const load_trajectory = trajectory
|
|
260
|
+
const frame_loader = load_trajectory?.frame_loader
|
|
261
|
+
if (!load_trajectory || !frame_loader) return
|
|
262
|
+
|
|
263
|
+
const request_id = ++frame_load_request_id
|
|
264
|
+
const request_is_current = () =>
|
|
265
|
+
request_id === frame_load_request_id &&
|
|
266
|
+
trajectory === load_trajectory &&
|
|
267
|
+
current_step_idx === frame_idx
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const frame = await frame_loader.load_frame(
|
|
271
|
+
orig_data || ``, // Use original_data for indexed files, empty string for external streaming
|
|
272
|
+
frame_idx,
|
|
273
|
+
)
|
|
274
|
+
if (!request_is_current()) return
|
|
275
|
+
current_frame = frame
|
|
276
|
+
} catch (error) {
|
|
277
|
+
if (!request_is_current()) return
|
|
278
|
+
console.error(`Failed to load frame ${frame_idx}:`, error)
|
|
279
|
+
current_frame = null
|
|
280
|
+
on_error?.({
|
|
281
|
+
error_msg: `Failed to load frame ${frame_idx}: ${error}`,
|
|
282
|
+
filename: current_filename,
|
|
283
|
+
file_size,
|
|
284
|
+
step_idx: frame_idx,
|
|
285
|
+
frame_count: total_frames,
|
|
286
|
+
})
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Current frame structure for display
|
|
291
|
+
let current_structure = $derived(current_frame?.structure)
|
|
292
|
+
|
|
293
|
+
// Track hidden elements (persists across frame changes)
|
|
294
|
+
let hidden_elements = $state(new Set<ElementSymbol>())
|
|
295
|
+
|
|
296
|
+
let step_label_positions = $derived.by((): number[] => {
|
|
297
|
+
if (!step_labels || total_frames <= 1) return []
|
|
298
|
+
|
|
299
|
+
if (Array.isArray(step_labels)) {
|
|
300
|
+
return step_labels.filter((idx) => idx >= 0 && idx < total_frames)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (typeof step_labels === `number`) {
|
|
304
|
+
if (step_labels > 0) {
|
|
305
|
+
return scaleLinear().domain([0, total_frames - 1]).nice()
|
|
306
|
+
.ticks(Math.min(step_labels, total_frames))
|
|
307
|
+
.map((tick) => Math.round(tick))
|
|
308
|
+
.filter((tick, idx, ticks) =>
|
|
309
|
+
tick >= 0 && tick < total_frames && ticks.indexOf(tick) === idx
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
if (step_labels < 0) {
|
|
313
|
+
const spacing = Math.abs(step_labels)
|
|
314
|
+
const positions = Array.from(
|
|
315
|
+
{ length: Math.ceil(total_frames / spacing) },
|
|
316
|
+
(_, idx) => idx * spacing,
|
|
317
|
+
)
|
|
318
|
+
return positions.at(-1) === total_frames - 1
|
|
319
|
+
? positions
|
|
320
|
+
: [...positions, total_frames - 1]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return []
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
// Build extended property config with custom labels if provided
|
|
327
|
+
let extended_config = $derived.by(() => {
|
|
328
|
+
if (!ELEM_PROPERTY_LABELS) return trajectory_property_config
|
|
329
|
+
|
|
330
|
+
const custom_config: Record<string, { label: string; unit: string }> = {}
|
|
331
|
+
for (const [key, label] of Object.entries(ELEM_PROPERTY_LABELS)) {
|
|
332
|
+
const existing = trajectory_property_config[key] ||
|
|
333
|
+
trajectory_property_config[key.toLowerCase()]
|
|
334
|
+
custom_config[key] = { label, unit: existing?.unit || `` }
|
|
335
|
+
}
|
|
336
|
+
return { ...trajectory_property_config, ...custom_config }
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
// Plot series state (not derived so we can update on legend toggle)
|
|
340
|
+
let plot_series = $state<DataSeries[]>([])
|
|
341
|
+
// Prevent circular updates when syncing legend toggles back to bindable visible_properties.
|
|
342
|
+
let syncing_visible_properties = false
|
|
343
|
+
|
|
344
|
+
// Regenerate plot series when trajectory, config, or visible_properties change
|
|
345
|
+
$effect(() => {
|
|
346
|
+
if (syncing_visible_properties) return
|
|
347
|
+
const keys_set = visible_properties ? new Set(visible_properties) : undefined
|
|
348
|
+
|
|
349
|
+
if (trajectory?.plot_metadata) {
|
|
350
|
+
plot_series = generate_streaming_plot_series(trajectory.plot_metadata, {
|
|
351
|
+
property_config: extended_config,
|
|
352
|
+
default_visible_properties: keys_set,
|
|
353
|
+
})
|
|
354
|
+
} else if (trajectory) {
|
|
355
|
+
plot_series = generate_plot_series(trajectory, data_extractor, {
|
|
356
|
+
property_config: extended_config,
|
|
357
|
+
default_visible_properties: keys_set,
|
|
358
|
+
})
|
|
359
|
+
} else {
|
|
360
|
+
plot_series = []
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
// Update visible_properties binding when user toggles series visibility in legend
|
|
365
|
+
$effect(() => {
|
|
366
|
+
if (!plot_series.length) return
|
|
367
|
+
|
|
368
|
+
// Extract property keys from visible series metadata
|
|
369
|
+
const visible_keys = plot_series.flatMap((srs) => {
|
|
370
|
+
if (!srs.visible) return []
|
|
371
|
+
const metadata = Array.isArray(srs.metadata) ? srs.metadata[0] : srs.metadata
|
|
372
|
+
const key = metadata?.property_key
|
|
373
|
+
return key ? [key as string] : []
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
// Only update if changed (use untrack to avoid circular dependency)
|
|
377
|
+
const current = untrack(() => visible_properties) || []
|
|
378
|
+
const has_changed = visible_keys.length !== current.length ||
|
|
379
|
+
!visible_keys.every((key, idx) => key === current[idx])
|
|
380
|
+
|
|
381
|
+
if (has_changed) {
|
|
382
|
+
syncing_visible_properties = true
|
|
383
|
+
visible_properties = visible_keys
|
|
384
|
+
queueMicrotask(() => (syncing_visible_properties = false))
|
|
385
|
+
}
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
// Handler for legend toggle - updates plot_series state
|
|
389
|
+
function handle_legend_toggle(series_idx: number) {
|
|
390
|
+
plot_series = toggle_series_visibility(plot_series, series_idx)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
let x_axis = $derived({
|
|
394
|
+
label: `Step`,
|
|
395
|
+
format: `.3~s`,
|
|
396
|
+
ticks: step_label_positions,
|
|
397
|
+
})
|
|
398
|
+
// Generate axis labels based on first visible series on each axis
|
|
399
|
+
let y_axis_labels = $derived(generate_axis_labels(plot_series))
|
|
400
|
+
let y_axis = $derived({
|
|
401
|
+
label: y_axis_labels.y1,
|
|
402
|
+
format: `.2~s`,
|
|
403
|
+
label_shift: { y: 10 },
|
|
404
|
+
})
|
|
405
|
+
let y2_axis = $derived({
|
|
406
|
+
label: y_axis_labels.y2,
|
|
407
|
+
format: `.2~s`,
|
|
408
|
+
label_shift: { y: 80 },
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
// hide plot if all plotted values are constant (no variation)
|
|
412
|
+
let show_plot = $derived(
|
|
413
|
+
display_mode !== `structure` && !should_hide_plot(trajectory, plot_series),
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
// Determine what to show based on display mode
|
|
417
|
+
let show_structure = $derived(![`scatter`, `histogram`].includes(display_mode))
|
|
418
|
+
let actual_show_plot = $derived(display_mode !== `structure` && show_plot)
|
|
419
|
+
|
|
420
|
+
// Check if there are any Y2 series to determine padding
|
|
421
|
+
let has_y2_series = $derived(
|
|
422
|
+
plot_series.some((srs) => srs.y_axis === `y2` && srs.visible),
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
// Step navigation functions
|
|
426
|
+
function next_step() {
|
|
427
|
+
if (current_step_idx < total_frames - 1) {
|
|
428
|
+
current_step_idx++
|
|
429
|
+
// Streaming frame loading handled by reactive effect
|
|
430
|
+
if (trajectory) {
|
|
431
|
+
on_step_change?.({
|
|
432
|
+
trajectory,
|
|
433
|
+
step_idx: current_step_idx,
|
|
434
|
+
frame_count: total_frames,
|
|
435
|
+
frame: current_frame || undefined,
|
|
436
|
+
})
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function prev_step() {
|
|
442
|
+
if (current_step_idx > 0) {
|
|
443
|
+
current_step_idx--
|
|
444
|
+
// Streaming frame loading handled by reactive effect
|
|
445
|
+
if (trajectory) {
|
|
446
|
+
on_step_change?.({
|
|
447
|
+
trajectory,
|
|
448
|
+
step_idx: current_step_idx,
|
|
449
|
+
frame_count: total_frames,
|
|
450
|
+
frame: current_frame || undefined,
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function go_to_step(idx: number) {
|
|
457
|
+
if (idx >= 0 && idx < total_frames) {
|
|
458
|
+
current_step_idx = idx
|
|
459
|
+
// Note: streaming frame loading is handled by reactive effect
|
|
460
|
+
// Handle callbacks for both traditional and streaming modes
|
|
461
|
+
if (trajectory) {
|
|
462
|
+
on_step_change?.({
|
|
463
|
+
trajectory,
|
|
464
|
+
step_idx: current_step_idx,
|
|
465
|
+
frame_count: total_frames,
|
|
466
|
+
frame: current_frame || undefined,
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Handle plot point clicks to jump to that step
|
|
473
|
+
function handle_plot_change(data: (Point & { series: DataSeries }) | null) {
|
|
474
|
+
if (data?.x !== undefined && typeof data.x === `number`) {
|
|
475
|
+
go_to_step(Math.round(data.x))
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Helper function to read file content
|
|
480
|
+
async function read_file_content(file: File): Promise<string | ArrayBuffer> {
|
|
481
|
+
return new Promise((resolve, reject) => {
|
|
482
|
+
const reader = new FileReader()
|
|
483
|
+
reader.addEventListener(`load`, () => resolve(reader.result as string | ArrayBuffer))
|
|
484
|
+
reader.addEventListener(`error`, () => reject(new Error(`Failed to read file`)))
|
|
485
|
+
|
|
486
|
+
// Read as text for text-based formats, binary for others
|
|
487
|
+
if (file.name.toLowerCase().match(/\.(xyz|json|extxyz|lammpstrj)$/)) {
|
|
488
|
+
reader.readAsText(file)
|
|
489
|
+
} else reader.readAsArrayBuffer(file)
|
|
490
|
+
})
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Play/pause functionality
|
|
494
|
+
function toggle_play() {
|
|
495
|
+
if (is_playing) pause_playback()
|
|
496
|
+
else start_playback()
|
|
497
|
+
}
|
|
498
|
+
function start_playback() {
|
|
499
|
+
if (total_frames <= 1) return
|
|
500
|
+
is_playing = true
|
|
501
|
+
if (trajectory) {
|
|
502
|
+
on_play?.({ trajectory, step_idx: current_step_idx, frame_count: total_frames })
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function pause_playback() {
|
|
506
|
+
is_playing = false
|
|
507
|
+
if (trajectory) {
|
|
508
|
+
on_pause?.({
|
|
509
|
+
trajectory: trajectory,
|
|
510
|
+
step_idx: current_step_idx,
|
|
511
|
+
frame_count: total_frames,
|
|
512
|
+
})
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
$effect(() => { // Effect to manage playback interval
|
|
516
|
+
// Only watch is_playing and frame_rate_ms, not play_interval itself
|
|
517
|
+
const playing = is_playing
|
|
518
|
+
const rate_ms = 1000 / fps
|
|
519
|
+
|
|
520
|
+
if (playing) {
|
|
521
|
+
// Clear existing interval if it exists - use untrack to avoid circular dependency
|
|
522
|
+
const current_interval = untrack(() => play_interval)
|
|
523
|
+
if (current_interval !== undefined) clearInterval(current_interval)
|
|
524
|
+
|
|
525
|
+
// Create new interval with current frame rate
|
|
526
|
+
play_interval = setInterval(() => {
|
|
527
|
+
if (current_step_idx >= total_frames - 1) {
|
|
528
|
+
if (trajectory) {
|
|
529
|
+
on_end?.({
|
|
530
|
+
trajectory,
|
|
531
|
+
step_idx: current_step_idx,
|
|
532
|
+
frame_count: total_frames,
|
|
533
|
+
frame: current_frame || undefined,
|
|
534
|
+
})
|
|
535
|
+
}
|
|
536
|
+
go_to_step(0) // Loop back to 1st step
|
|
537
|
+
if (trajectory) {
|
|
538
|
+
on_loop?.({ trajectory, frame_count: total_frames })
|
|
539
|
+
}
|
|
540
|
+
} else next_step()
|
|
541
|
+
}, rate_ms)
|
|
542
|
+
} else {
|
|
543
|
+
// Clear interval when not playing - use untrack to avoid circular dependency
|
|
544
|
+
const current_interval = untrack(() => play_interval)
|
|
545
|
+
if (current_interval !== undefined) {
|
|
546
|
+
clearInterval(current_interval)
|
|
547
|
+
play_interval = undefined
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
// Cleanup interval on component destroy
|
|
553
|
+
$effect(() => () => {
|
|
554
|
+
if (play_interval !== undefined) clearInterval(play_interval)
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
// Handle internal file format drops
|
|
558
|
+
async function handle_internal_file_drop(internal_data: string): Promise<boolean> {
|
|
559
|
+
try {
|
|
560
|
+
const file_info = JSON.parse(internal_data)
|
|
561
|
+
|
|
562
|
+
// Check if this is a binary file
|
|
563
|
+
if (file_info.is_binary) {
|
|
564
|
+
if (file_info.content instanceof ArrayBuffer) {
|
|
565
|
+
await load_trajectory_data(file_info.content, file_info.name)
|
|
566
|
+
} else if (file_info.content_url) {
|
|
567
|
+
const response = await fetch(file_info.content_url)
|
|
568
|
+
const array_buffer = await response.arrayBuffer()
|
|
569
|
+
await load_trajectory_data(array_buffer, file_info.name)
|
|
570
|
+
} else {
|
|
571
|
+
console.warn(
|
|
572
|
+
`Binary file without ArrayBuffer or blob URL:`,
|
|
573
|
+
file_info.name,
|
|
574
|
+
)
|
|
575
|
+
}
|
|
576
|
+
} else {
|
|
577
|
+
await load_trajectory_data(file_info.content, file_info.name)
|
|
578
|
+
}
|
|
579
|
+
return true
|
|
580
|
+
} catch (error) {
|
|
581
|
+
console.warn(`Failed to parse internal file data:`, error)
|
|
582
|
+
return false
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Handle file drop events with optimized large file support
|
|
587
|
+
async function handle_file_drop(event: DragEvent) {
|
|
588
|
+
event.preventDefault()
|
|
589
|
+
dragover = false
|
|
590
|
+
if (!allow_file_drop) return
|
|
591
|
+
|
|
592
|
+
loading = true
|
|
593
|
+
|
|
594
|
+
try {
|
|
595
|
+
// Check for our custom internal file format first
|
|
596
|
+
const internal_data = event.dataTransfer?.getData(
|
|
597
|
+
`application/x-matterviz-file`,
|
|
598
|
+
)
|
|
599
|
+
if (internal_data) {
|
|
600
|
+
const handled = await handle_internal_file_drop(internal_data)
|
|
601
|
+
if (handled) return
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Handle URL-based files (e.g. from FilePicker)
|
|
605
|
+
const handled = await handle_url_drop(event, async (content, filename) => {
|
|
606
|
+
current_filename = filename
|
|
607
|
+
file_size = content instanceof ArrayBuffer
|
|
608
|
+
? content.byteLength
|
|
609
|
+
: new Blob([content]).size
|
|
610
|
+
await load_trajectory_data(content, filename)
|
|
611
|
+
}).catch(() => false)
|
|
612
|
+
|
|
613
|
+
if (handled) {
|
|
614
|
+
return
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Handle file system drops with optimized large file support
|
|
618
|
+
const file = event.dataTransfer?.files[0]
|
|
619
|
+
if (file) {
|
|
620
|
+
file_size = file.size
|
|
621
|
+
current_file_path = file.webkitRelativePath || file.name
|
|
622
|
+
file_object = file
|
|
623
|
+
|
|
624
|
+
// Read file content directly
|
|
625
|
+
const content = await read_file_content(file)
|
|
626
|
+
await load_trajectory_data(content, file.name)
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Check for plain text data (fallback)
|
|
630
|
+
const text_data = event.dataTransfer?.getData(`text/plain`)
|
|
631
|
+
if (text_data) {
|
|
632
|
+
file_size = new Blob([text_data]).size // Calculate byte size of text data
|
|
633
|
+
await load_trajectory_data(text_data, `trajectory.json`)
|
|
634
|
+
return
|
|
635
|
+
}
|
|
636
|
+
} catch (error) {
|
|
637
|
+
console.error(`File drop failed:`, error)
|
|
638
|
+
error_msg = `Failed to load file: ${error}`
|
|
639
|
+
on_error?.({ error_msg, filename: current_filename, file_size })
|
|
640
|
+
} finally {
|
|
641
|
+
loading = false
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
$effect(() => { // Load trajectory from URL when data_url is provided
|
|
646
|
+
if (data_url && !trajectory) {
|
|
647
|
+
loading = true
|
|
648
|
+
error_msg = null
|
|
649
|
+
|
|
650
|
+
load_from_url(data_url, async (content, filename) => {
|
|
651
|
+
current_filename = filename
|
|
652
|
+
file_size = content instanceof ArrayBuffer
|
|
653
|
+
? content.byteLength
|
|
654
|
+
: new Blob([content]).size
|
|
655
|
+
await load_trajectory_data(content, filename)
|
|
656
|
+
})
|
|
657
|
+
.then(() => {
|
|
658
|
+
loading = false
|
|
659
|
+
})
|
|
660
|
+
.catch((err: Error) => {
|
|
661
|
+
console.error(`Failed to load trajectory from URL:`, err)
|
|
662
|
+
error_msg = `Failed to load trajectory: ${err.message}`
|
|
663
|
+
current_filename = undefined
|
|
664
|
+
file_size = undefined
|
|
665
|
+
loading = false
|
|
666
|
+
on_error?.({
|
|
667
|
+
error_msg,
|
|
668
|
+
filename: current_filename || undefined,
|
|
669
|
+
file_size: file_size || undefined,
|
|
670
|
+
})
|
|
671
|
+
})
|
|
672
|
+
}
|
|
673
|
+
})
|
|
674
|
+
|
|
675
|
+
// Watch for frame rate changes
|
|
676
|
+
$effect(() => {
|
|
677
|
+
on_frame_rate_change?.({ trajectory, fps: fps })
|
|
678
|
+
})
|
|
679
|
+
|
|
680
|
+
async function load_trajectory_data(data: string | ArrayBuffer, filename: string) {
|
|
681
|
+
loading = true
|
|
682
|
+
error_msg = null
|
|
683
|
+
parsing_progress = null
|
|
684
|
+
|
|
685
|
+
// Reset previous loading state
|
|
686
|
+
orig_data = null
|
|
687
|
+
|
|
688
|
+
try {
|
|
689
|
+
const data_size = data instanceof ArrayBuffer ? data.byteLength : data.length
|
|
690
|
+
|
|
691
|
+
// Determine loading strategy based on file size
|
|
692
|
+
const bin_file_threshold = loading_options.bin_file_threshold ??
|
|
693
|
+
MAX_BIN_FILE_SIZE
|
|
694
|
+
const text_file_threshold = loading_options.text_file_threshold ??
|
|
695
|
+
MAX_TEXT_FILE_SIZE
|
|
696
|
+
if (
|
|
697
|
+
(data instanceof ArrayBuffer && data_size > bin_file_threshold) ||
|
|
698
|
+
(typeof data === `string` && data_size > text_file_threshold)
|
|
699
|
+
) { // Large files: Use indexed loading
|
|
700
|
+
await load_with_indexing(data, filename)
|
|
701
|
+
} else {
|
|
702
|
+
// Small files: Use regular loading
|
|
703
|
+
const merged_options = { ...loading_options, atom_type_mapping }
|
|
704
|
+
trajectory = await parse_trajectory_async(data, filename, (progress) => {
|
|
705
|
+
parsing_progress = progress
|
|
706
|
+
}, merged_options)
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
current_step_idx = 0
|
|
710
|
+
current_filename = filename
|
|
711
|
+
|
|
712
|
+
const file_size_bytes = data instanceof ArrayBuffer
|
|
713
|
+
? data.byteLength
|
|
714
|
+
: new Blob([data]).size
|
|
715
|
+
on_file_load?.({ // emit file load event
|
|
716
|
+
trajectory,
|
|
717
|
+
frame_count: trajectory?.frames.length ?? 0,
|
|
718
|
+
total_atoms: trajectory?.frames[0]?.structure.sites.length ?? 0,
|
|
719
|
+
filename,
|
|
720
|
+
file_size: file_size_bytes,
|
|
721
|
+
})
|
|
722
|
+
} catch (err) {
|
|
723
|
+
const unsupported_message = get_unsupported_format_message(
|
|
724
|
+
filename,
|
|
725
|
+
typeof data === `string` ? data : ``,
|
|
726
|
+
)
|
|
727
|
+
error_msg = unsupported_message || `Failed to parse trajectory: ${err}`
|
|
728
|
+
current_filename = undefined
|
|
729
|
+
file_size = undefined
|
|
730
|
+
|
|
731
|
+
on_error?.({ // emit error event
|
|
732
|
+
error_msg,
|
|
733
|
+
filename: current_filename || undefined,
|
|
734
|
+
file_size: file_size || undefined,
|
|
735
|
+
})
|
|
736
|
+
} finally {
|
|
737
|
+
parsing_progress = null
|
|
738
|
+
loading = false
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Load using indexed parsing for large files
|
|
743
|
+
async function load_with_indexing(data: string | ArrayBuffer, filename: string) {
|
|
744
|
+
try { // Use indexed parsing for efficient large file handling
|
|
745
|
+
const merged_options = {
|
|
746
|
+
use_indexing: true,
|
|
747
|
+
...loading_options,
|
|
748
|
+
atom_type_mapping,
|
|
749
|
+
}
|
|
750
|
+
trajectory = await parse_trajectory_async(data, filename, (progress) => {
|
|
751
|
+
parsing_progress = progress
|
|
752
|
+
}, merged_options)
|
|
753
|
+
|
|
754
|
+
// Attach frame loader and original data directly to trajectory for unified access
|
|
755
|
+
orig_data = data
|
|
756
|
+
trajectory.frame_loader = create_frame_loader(filename)
|
|
757
|
+
} catch (error) {
|
|
758
|
+
console.error(`Indexed loading failed:`, error)
|
|
759
|
+
throw error
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Get current view mode label
|
|
764
|
+
let current_view_label = $derived.by(() => {
|
|
765
|
+
if (display_mode === `structure`) return `Structure Only`
|
|
766
|
+
if (display_mode === `scatter`) return `Scatter Only`
|
|
767
|
+
if (display_mode === `histogram`) return `Histogram Only`
|
|
768
|
+
if (display_mode === `structure+histogram`) return `Structure + Histogram`
|
|
769
|
+
if (display_mode === `structure+scatter`) return `Structure + Scatter`
|
|
770
|
+
throw new Error(`Unexpected display mode: ${display_mode}`)
|
|
771
|
+
})
|
|
772
|
+
|
|
773
|
+
let view_mode_dropdown_open = $state(false)
|
|
774
|
+
|
|
775
|
+
// Handle click outside to close dropdowns
|
|
776
|
+
function handle_click_outside(event: MouseEvent) {
|
|
777
|
+
const target = event.target
|
|
778
|
+
if (!(target instanceof Element)) return
|
|
779
|
+
if (view_mode_dropdown_open) {
|
|
780
|
+
const dropdown_wrapper = target.closest(`.view-mode-dropdown-wrapper`)
|
|
781
|
+
// Don't close if clicking on dropdown wrapper (contains both button and menu)
|
|
782
|
+
if (!dropdown_wrapper) view_mode_dropdown_open = false
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Handle keyboard shortcuts
|
|
787
|
+
function onkeydown(event: KeyboardEvent) {
|
|
788
|
+
if (!trajectory) return
|
|
789
|
+
|
|
790
|
+
// Don't handle shortcuts if user is typing in an input field (but allow if it's our step input and not focused)
|
|
791
|
+
const target = event.target instanceof HTMLElement ? event.target : null
|
|
792
|
+
const is_step_input = target?.classList.contains(`step-input`) ?? false
|
|
793
|
+
const is_input_focused =
|
|
794
|
+
target?.tagName === `INPUT` || target?.tagName === `TEXTAREA`
|
|
795
|
+
|
|
796
|
+
// Skip if typing in an input that's not our step input
|
|
797
|
+
if (is_input_focused && !is_step_input) return
|
|
798
|
+
|
|
799
|
+
// If typing in step input, only handle certain navigation keys
|
|
800
|
+
if (is_step_input && is_input_focused) {
|
|
801
|
+
// Allow normal typing, but handle special navigation keys
|
|
802
|
+
if ([`Escape`, `Enter`].includes(event.key)) target?.blur() // Remove focus from input
|
|
803
|
+
return
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
const is_cmd_or_ctrl = event.metaKey || event.ctrlKey
|
|
807
|
+
|
|
808
|
+
// Navigation shortcuts
|
|
809
|
+
if (event.key === ` `) toggle_play()
|
|
810
|
+
else if (event.key === `ArrowLeft`) {
|
|
811
|
+
if (is_cmd_or_ctrl) go_to_step(0)
|
|
812
|
+
else prev_step()
|
|
813
|
+
} else if (event.key === `ArrowRight`) {
|
|
814
|
+
if (is_cmd_or_ctrl) go_to_step(total_frames - 1)
|
|
815
|
+
else next_step()
|
|
816
|
+
} else if (event.key === `Home`) go_to_step(0)
|
|
817
|
+
else if (event.key === `End`) go_to_step(total_frames - 1)
|
|
818
|
+
else if (event.key === `j`) {
|
|
819
|
+
go_to_step(Math.max(0, current_step_idx - 10))
|
|
820
|
+
} else if (event.key === `l`) {
|
|
821
|
+
go_to_step(Math.min(total_frames - 1, current_step_idx + 10))
|
|
822
|
+
} else if (event.key === `PageUp`) {
|
|
823
|
+
go_to_step(Math.max(0, current_step_idx - 25))
|
|
824
|
+
} else if (event.key === `PageDown`) {
|
|
825
|
+
go_to_step(Math.min(total_frames - 1, current_step_idx + 25))
|
|
826
|
+
} // Interface shortcuts
|
|
827
|
+
else if (event.key === `f` && fullscreen_toggle) toggle_fullscreen(wrapper)
|
|
828
|
+
// 'i' key handled by the TrajectoryInfoPane's built-in toggle
|
|
829
|
+
// Playback speed shortcuts (only when playing)
|
|
830
|
+
else if ((event.key === `=` || event.key === `+`) && is_playing) {
|
|
831
|
+
fps = Math.min(fps_range[1], fps + 0.2)
|
|
832
|
+
on_frame_rate_change?.({ trajectory, fps: fps })
|
|
833
|
+
} else if (event.key === `-` && is_playing) {
|
|
834
|
+
fps = Math.max(fps_range[0], fps - 0.2)
|
|
835
|
+
on_frame_rate_change?.({ trajectory, fps: fps })
|
|
836
|
+
} // System shortcuts
|
|
837
|
+
else if (event.key === `Escape`) {
|
|
838
|
+
if (document.fullscreenElement) document.exitFullscreen()
|
|
839
|
+
else if (view_mode_dropdown_open) view_mode_dropdown_open = false
|
|
840
|
+
// Escape key for info pane handled by DraggablePane
|
|
841
|
+
} // Number keys 0-9 - jump to percentage of trajectory
|
|
842
|
+
else if (event.key >= `0` && event.key <= `9`) {
|
|
843
|
+
go_to_step(Math.floor((parseInt(event.key, 10) / 10) * (total_frames - 1)))
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// Separate state variables for each pane to match component prop types
|
|
848
|
+
let structure_info_open = $state(false)
|
|
849
|
+
let structure_controls_open = $state(false)
|
|
850
|
+
let scatter_controls = $state<ControlsConfig>({ open: false })
|
|
851
|
+
let trajectory_export_open = $state(false)
|
|
852
|
+
let fullscreen = $state(false)
|
|
853
|
+
</script>
|
|
854
|
+
|
|
855
|
+
<svelte:document
|
|
856
|
+
onfullscreenchange={() => {
|
|
857
|
+
fullscreen = !!document.fullscreenElement
|
|
858
|
+
on_fullscreen_change?.({ trajectory, fullscreen })
|
|
859
|
+
}}
|
|
860
|
+
/>
|
|
861
|
+
|
|
862
|
+
<div
|
|
863
|
+
class:dragover
|
|
864
|
+
class:active={is_playing || structure_info_open || structure_controls_open ||
|
|
865
|
+
scatter_controls.open || trajectory_export_open || info_pane_open}
|
|
866
|
+
bind:this={wrapper}
|
|
867
|
+
bind:clientWidth={element_size.width}
|
|
868
|
+
bind:clientHeight={element_size.height}
|
|
869
|
+
role="button"
|
|
870
|
+
tabindex="0"
|
|
871
|
+
aria-label="Drop trajectory file here to load"
|
|
872
|
+
ondrop={handle_file_drop}
|
|
873
|
+
ondragover={(event) => {
|
|
874
|
+
event.preventDefault()
|
|
875
|
+
if (!allow_file_drop) return
|
|
876
|
+
dragover = true
|
|
877
|
+
}}
|
|
878
|
+
ondragleave={(event) => {
|
|
879
|
+
event.preventDefault()
|
|
880
|
+
dragover = false
|
|
881
|
+
}}
|
|
882
|
+
onclick={handle_click_outside}
|
|
883
|
+
{onkeydown}
|
|
884
|
+
{...rest}
|
|
885
|
+
class="trajectory {actual_layout} {rest.class ?? ``}"
|
|
886
|
+
class:show-both-views={[`structure+scatter`, `structure+histogram`].includes(display_mode) &&
|
|
887
|
+
actual_show_plot && show_structure}
|
|
888
|
+
>
|
|
889
|
+
{#if loading}
|
|
890
|
+
{@const text = parsing_progress
|
|
891
|
+
? `${parsing_progress.stage} (${parsing_progress.current}%)`
|
|
892
|
+
: `Loading trajectory...`}
|
|
893
|
+
<Spinner
|
|
894
|
+
{text}
|
|
895
|
+
style="flex: 1; display: flex; align-items: center; justify-content: center"
|
|
896
|
+
{...spinner_props}
|
|
897
|
+
/>
|
|
898
|
+
{:else if error_msg}
|
|
899
|
+
<TrajectoryError
|
|
900
|
+
{error_msg}
|
|
901
|
+
on_dismiss={() => (error_msg = null)}
|
|
902
|
+
{error_snippet}
|
|
903
|
+
/>
|
|
904
|
+
{:else if trajectory}
|
|
905
|
+
<!-- Trajectory Controls -->
|
|
906
|
+
{#if controls_config.mode !== `never`}
|
|
907
|
+
<div
|
|
908
|
+
class="trajectory-controls {controls_config.class}"
|
|
909
|
+
style={controls_config.style}
|
|
910
|
+
>
|
|
911
|
+
{#if trajectory_controls}
|
|
912
|
+
{@render trajectory_controls({
|
|
913
|
+
trajectory,
|
|
914
|
+
current_step_idx,
|
|
915
|
+
total_frames: total_frames,
|
|
916
|
+
on_step_change: go_to_step,
|
|
917
|
+
})}
|
|
918
|
+
{:else}
|
|
919
|
+
{#if current_filename && controls_config.visible(`filename`)}
|
|
920
|
+
<button
|
|
921
|
+
class="filename"
|
|
922
|
+
title="Click to copy filename <code>{current_filename}</code>"
|
|
923
|
+
{@attach tooltip({ allow_html: true })}
|
|
924
|
+
onclick={() => {
|
|
925
|
+
if (current_filename) {
|
|
926
|
+
navigator.clipboard.writeText(current_filename)
|
|
927
|
+
filename_copied = true
|
|
928
|
+
setTimeout(() => filename_copied = false, 1000)
|
|
929
|
+
}
|
|
930
|
+
}}
|
|
931
|
+
>
|
|
932
|
+
{current_filename}
|
|
933
|
+
{#if filename_copied}
|
|
934
|
+
<Icon
|
|
935
|
+
icon="Check"
|
|
936
|
+
style="color: var(--success-color); position: absolute; right: 3pt; top: 50%; transform: translateY(-50%); font-size: 16px; animation: fade-in 0.1s; background: var(--surface-bg-hover); border-radius: 50%"
|
|
937
|
+
/>
|
|
938
|
+
{/if}
|
|
939
|
+
</button>
|
|
940
|
+
{/if}
|
|
941
|
+
|
|
942
|
+
<!-- Navigation controls -->
|
|
943
|
+
{#if controls_config.visible(`nav`)}
|
|
944
|
+
<div class="nav-section">
|
|
945
|
+
<button
|
|
946
|
+
onclick={prev_step}
|
|
947
|
+
disabled={current_step_idx === 0 || is_playing}
|
|
948
|
+
title="Previous step"
|
|
949
|
+
>
|
|
950
|
+
⏮
|
|
951
|
+
</button>
|
|
952
|
+
<button
|
|
953
|
+
onclick={toggle_play}
|
|
954
|
+
disabled={total_frames <= 1}
|
|
955
|
+
title={is_playing ? `Pause playback` : `Play trajectory`}
|
|
956
|
+
class="play-button"
|
|
957
|
+
class:playing={is_playing}
|
|
958
|
+
>
|
|
959
|
+
{is_playing ? `⏸` : `▶`}
|
|
960
|
+
</button>
|
|
961
|
+
<button
|
|
962
|
+
onclick={next_step}
|
|
963
|
+
disabled={current_step_idx === total_frames - 1 || is_playing}
|
|
964
|
+
title="Next step"
|
|
965
|
+
>
|
|
966
|
+
⏭
|
|
967
|
+
</button>
|
|
968
|
+
</div>
|
|
969
|
+
{/if}
|
|
970
|
+
|
|
971
|
+
<!-- Frame slider and counter -->
|
|
972
|
+
{#if controls_config.visible(`step`)}
|
|
973
|
+
<div class="step-section">
|
|
974
|
+
<input
|
|
975
|
+
type="number"
|
|
976
|
+
min="0"
|
|
977
|
+
max={total_frames - 1}
|
|
978
|
+
bind:value={current_step_idx}
|
|
979
|
+
class="step-input"
|
|
980
|
+
title="Enter step number to jump to"
|
|
981
|
+
aria-label="Step input"
|
|
982
|
+
{@attach tooltip()}
|
|
983
|
+
/>
|
|
984
|
+
<span aria-label="total frames">/ {format_num(total_frames, `.3~s`)}</span>
|
|
985
|
+
<div class="slider-container">
|
|
986
|
+
<input
|
|
987
|
+
type="range"
|
|
988
|
+
min="0"
|
|
989
|
+
max={total_frames - 1}
|
|
990
|
+
bind:value={current_step_idx}
|
|
991
|
+
class="step-slider"
|
|
992
|
+
title="Drag to navigate steps"
|
|
993
|
+
/>
|
|
994
|
+
{#if step_label_positions.length > 0}
|
|
995
|
+
<div class="step-labels">
|
|
996
|
+
{#each step_label_positions as step_idx (step_idx)}
|
|
997
|
+
{@const position_percent = total_frames > 1
|
|
998
|
+
? (step_idx / (total_frames - 1)) * 100
|
|
999
|
+
: 0}
|
|
1000
|
+
{@const adjusted_position = 1.5 + (position_percent * (100 - 2)) / 100}
|
|
1001
|
+
<div class="step-tick" style:left="{adjusted_position}%"></div>
|
|
1002
|
+
<div class="step-label" style:left="{adjusted_position}%">
|
|
1003
|
+
{format_num(step_idx, `.3~s`)}
|
|
1004
|
+
</div>
|
|
1005
|
+
{/each}
|
|
1006
|
+
</div>
|
|
1007
|
+
{/if}
|
|
1008
|
+
</div>
|
|
1009
|
+
</div>
|
|
1010
|
+
{/if}
|
|
1011
|
+
|
|
1012
|
+
<!-- Frame rate control - only shown when playing -->
|
|
1013
|
+
{#if is_playing && controls_config.visible(`fps`)}
|
|
1014
|
+
<label
|
|
1015
|
+
class="fps-section"
|
|
1016
|
+
style="font-size: 0.9em; display: flex; align-items: center; gap: 5pt; margin-inline: 6pt"
|
|
1017
|
+
>
|
|
1018
|
+
FPS
|
|
1019
|
+
<input
|
|
1020
|
+
type="range"
|
|
1021
|
+
min={fps_range[0]}
|
|
1022
|
+
max={fps_range[1]}
|
|
1023
|
+
bind:value={fps}
|
|
1024
|
+
title="Frame rate: {format_num(fps, `.2~s`)} fps"
|
|
1025
|
+
style="width: clamp(60px, 8cqw, 90px); accent-color: var(--accent-color)"
|
|
1026
|
+
/>
|
|
1027
|
+
<input
|
|
1028
|
+
type="number"
|
|
1029
|
+
min={fps_range[0]}
|
|
1030
|
+
max={fps_range[1]}
|
|
1031
|
+
bind:value={fps}
|
|
1032
|
+
title="Enter precise FPS value"
|
|
1033
|
+
style="text-align: center; border: var(--tooltip-border)"
|
|
1034
|
+
/>
|
|
1035
|
+
</label>
|
|
1036
|
+
{/if}
|
|
1037
|
+
|
|
1038
|
+
<!-- Frame info section -->
|
|
1039
|
+
<div class="info-section">
|
|
1040
|
+
{#if trajectory && controls_config.visible(`info-pane`)}
|
|
1041
|
+
<TrajectoryInfoPane
|
|
1042
|
+
{trajectory}
|
|
1043
|
+
{current_step_idx}
|
|
1044
|
+
{current_filename}
|
|
1045
|
+
{current_file_path}
|
|
1046
|
+
{file_size}
|
|
1047
|
+
{file_object}
|
|
1048
|
+
bind:pane_open={info_pane_open}
|
|
1049
|
+
pane_props={{ style: `max-height: calc(${element_size.height}px - 50px)` }}
|
|
1050
|
+
/>
|
|
1051
|
+
{/if}
|
|
1052
|
+
<!-- Trajectory Export Pane -->
|
|
1053
|
+
{#if controls_config.visible(`export-pane`)}
|
|
1054
|
+
<TrajectoryExportPane
|
|
1055
|
+
bind:export_pane_open={trajectory_export_open}
|
|
1056
|
+
{trajectory}
|
|
1057
|
+
{wrapper}
|
|
1058
|
+
filename={current_filename || `trajectory`}
|
|
1059
|
+
on_step_change={go_to_step}
|
|
1060
|
+
pane_props={{ style: `max-height: calc(${element_size.height}px - 50px)` }}
|
|
1061
|
+
/>
|
|
1062
|
+
{/if}
|
|
1063
|
+
<!-- Display mode dropdown -->
|
|
1064
|
+
{#if plot_series.length > 0 &&
|
|
1065
|
+
controls_config.visible(`view-mode`)}
|
|
1066
|
+
<div class="view-mode-dropdown-wrapper">
|
|
1067
|
+
<button
|
|
1068
|
+
onclick={() => (view_mode_dropdown_open = !view_mode_dropdown_open)}
|
|
1069
|
+
title={current_view_label}
|
|
1070
|
+
class="view-mode-button"
|
|
1071
|
+
class:active={view_mode_dropdown_open}
|
|
1072
|
+
style="background-color: transparent; padding: 0"
|
|
1073
|
+
>
|
|
1074
|
+
<Icon
|
|
1075
|
+
icon={({
|
|
1076
|
+
structure: `Atom`,
|
|
1077
|
+
'structure+scatter': `TwoColumns`,
|
|
1078
|
+
'structure+histogram': `TwoColumns`,
|
|
1079
|
+
scatter: `ScatterPlot`,
|
|
1080
|
+
histogram: `Histogram`,
|
|
1081
|
+
} as const)[display_mode]}
|
|
1082
|
+
/>
|
|
1083
|
+
<Icon icon={view_mode_dropdown_open ? `ArrowUp` : `ArrowDown`} />
|
|
1084
|
+
</button>
|
|
1085
|
+
{#if view_mode_dropdown_open}
|
|
1086
|
+
<div class="view-mode-dropdown">
|
|
1087
|
+
{#each [
|
|
1088
|
+
{ mode: `structure`, icon: `Atom`, label: `Structure-only` },
|
|
1089
|
+
{
|
|
1090
|
+
mode: `structure+scatter`,
|
|
1091
|
+
icon: `TwoColumns`,
|
|
1092
|
+
label: `Structure + Scatter`,
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
mode: `structure+histogram`,
|
|
1096
|
+
icon: `TwoColumns`,
|
|
1097
|
+
label: `Structure + Histogram`,
|
|
1098
|
+
},
|
|
1099
|
+
{ mode: `scatter`, icon: `ScatterPlot`, label: `Scatter-only` },
|
|
1100
|
+
{
|
|
1101
|
+
mode: `histogram`,
|
|
1102
|
+
icon: `Histogram`,
|
|
1103
|
+
label: `Histogram-only`,
|
|
1104
|
+
},
|
|
1105
|
+
] as const as
|
|
1106
|
+
option
|
|
1107
|
+
(option.mode)
|
|
1108
|
+
}
|
|
1109
|
+
<button
|
|
1110
|
+
class="view-mode-option"
|
|
1111
|
+
class:selected={display_mode === option.mode}
|
|
1112
|
+
onclick={() => {
|
|
1113
|
+
display_mode = option.mode
|
|
1114
|
+
on_display_mode_change?.({ trajectory, mode: option.mode })
|
|
1115
|
+
view_mode_dropdown_open = false
|
|
1116
|
+
}}
|
|
1117
|
+
>
|
|
1118
|
+
<Icon icon={option.icon} />
|
|
1119
|
+
<span>{option.label}</span>
|
|
1120
|
+
</button>
|
|
1121
|
+
{/each}
|
|
1122
|
+
</div>
|
|
1123
|
+
{/if}
|
|
1124
|
+
</div>
|
|
1125
|
+
{/if}
|
|
1126
|
+
<!-- Fullscreen button - rightmost position -->
|
|
1127
|
+
{#if fullscreen_toggle &&
|
|
1128
|
+
controls_config.visible(`fullscreen`)}
|
|
1129
|
+
<button
|
|
1130
|
+
type="button"
|
|
1131
|
+
onclick={() => fullscreen_toggle && toggle_fullscreen(wrapper)}
|
|
1132
|
+
title="{fullscreen ? `Exit` : `Enter`} fullscreen"
|
|
1133
|
+
aria-label="{fullscreen ? `Exit` : `Enter`} fullscreen"
|
|
1134
|
+
aria-pressed={fullscreen}
|
|
1135
|
+
class="fullscreen-button"
|
|
1136
|
+
>
|
|
1137
|
+
{#if typeof fullscreen_toggle === `function`}
|
|
1138
|
+
{@render fullscreen_toggle({ fullscreen })}
|
|
1139
|
+
{:else}
|
|
1140
|
+
<Icon icon="{fullscreen ? `Exit` : ``}Fullscreen" />
|
|
1141
|
+
{/if}
|
|
1142
|
+
</button>
|
|
1143
|
+
{/if}
|
|
1144
|
+
</div>
|
|
1145
|
+
{/if}
|
|
1146
|
+
</div>
|
|
1147
|
+
{/if}
|
|
1148
|
+
|
|
1149
|
+
<div
|
|
1150
|
+
class="content-area"
|
|
1151
|
+
class:hide-plot={!actual_show_plot}
|
|
1152
|
+
class:hide-structure={!show_structure}
|
|
1153
|
+
class:show-both={[`structure+scatter`, `structure+histogram`].includes(display_mode)}
|
|
1154
|
+
class:show-structure-only={display_mode === `structure`}
|
|
1155
|
+
class:show-plot-only={[`scatter`, `histogram`].includes(display_mode)}
|
|
1156
|
+
>
|
|
1157
|
+
{#if show_structure}
|
|
1158
|
+
<Structure
|
|
1159
|
+
structure={current_structure}
|
|
1160
|
+
allow_file_drop={false}
|
|
1161
|
+
style="height: 100%; min-height: 0; z-index: 3; border-radius: 0"
|
|
1162
|
+
{...{
|
|
1163
|
+
show_image_atoms: false, // Default to false to avoid atoms popping in/out at cell edges
|
|
1164
|
+
...structure_props,
|
|
1165
|
+
}}
|
|
1166
|
+
bind:controls_open={structure_controls_open}
|
|
1167
|
+
bind:info_pane_open={structure_info_open}
|
|
1168
|
+
bind:hidden_elements
|
|
1169
|
+
/>
|
|
1170
|
+
{/if}
|
|
1171
|
+
|
|
1172
|
+
{#if actual_show_plot}
|
|
1173
|
+
{#if display_mode === `scatter` || display_mode === `structure+scatter`}
|
|
1174
|
+
<ScatterPlot
|
|
1175
|
+
series={plot_series}
|
|
1176
|
+
{x_axis}
|
|
1177
|
+
{y_axis}
|
|
1178
|
+
{y2_axis}
|
|
1179
|
+
controls={scatter_controls}
|
|
1180
|
+
current_x_value={current_step_idx}
|
|
1181
|
+
change={plot_skimming ? handle_plot_change : undefined}
|
|
1182
|
+
padding={{ t: 20, b: 60, l: 52, r: has_y2_series ? 100 : 20 }}
|
|
1183
|
+
range_padding={0}
|
|
1184
|
+
style="height: 100%"
|
|
1185
|
+
{...scatter_props}
|
|
1186
|
+
legend={{
|
|
1187
|
+
...scatter_props.legend ?? {},
|
|
1188
|
+
on_toggle: (series_idx: number) => {
|
|
1189
|
+
handle_legend_toggle(series_idx)
|
|
1190
|
+
scatter_props.legend?.on_toggle?.(series_idx)
|
|
1191
|
+
},
|
|
1192
|
+
}}
|
|
1193
|
+
class="plot {scatter_props.class ?? ``}"
|
|
1194
|
+
>
|
|
1195
|
+
{#snippet tooltip({
|
|
1196
|
+
x,
|
|
1197
|
+
y,
|
|
1198
|
+
metadata,
|
|
1199
|
+
label,
|
|
1200
|
+
}: ScatterHandlerProps)}
|
|
1201
|
+
{@const formatted_y = typeof y === `number` ? format_num(y) : y}
|
|
1202
|
+
Step: {Math.round(x)}<br />
|
|
1203
|
+
{@html sanitize_html(metadata?.series_label || label || `Value`)}: {formatted_y}
|
|
1204
|
+
{/snippet}
|
|
1205
|
+
</ScatterPlot>
|
|
1206
|
+
{:else if display_mode === `histogram` || display_mode === `structure+histogram`}
|
|
1207
|
+
<Histogram
|
|
1208
|
+
{...histogram_props}
|
|
1209
|
+
series={plot_series}
|
|
1210
|
+
x_axis={{
|
|
1211
|
+
label: String(histogram_props.x_axis?.label ?? y_axis_labels.y1),
|
|
1212
|
+
format: `.3~s`,
|
|
1213
|
+
}}
|
|
1214
|
+
y_axis={{ label: histogram_props.y_axis?.label ?? `Count`, format: `.3~s` }}
|
|
1215
|
+
mode={histogram_props.mode ?? `overlay`}
|
|
1216
|
+
show_legend={histogram_props.show_legend ?? plot_series.length > 1}
|
|
1217
|
+
legend={histogram_props.legend}
|
|
1218
|
+
on_series_toggle={(series_idx: number) => {
|
|
1219
|
+
handle_legend_toggle(series_idx)
|
|
1220
|
+
histogram_props.on_series_toggle?.(series_idx)
|
|
1221
|
+
}}
|
|
1222
|
+
style="height: 100%"
|
|
1223
|
+
class="plot {histogram_props.class ?? ``}"
|
|
1224
|
+
--ctrl-btn-top="6ex"
|
|
1225
|
+
>
|
|
1226
|
+
{#snippet tooltip({
|
|
1227
|
+
value,
|
|
1228
|
+
count,
|
|
1229
|
+
property,
|
|
1230
|
+
}: {
|
|
1231
|
+
value: number
|
|
1232
|
+
count: number
|
|
1233
|
+
property?: string
|
|
1234
|
+
})}
|
|
1235
|
+
{#if property}<div><strong>{property}</strong></div>{/if}
|
|
1236
|
+
<div>Value: {format_num(value)}</div>
|
|
1237
|
+
<div>Count: {count}</div>
|
|
1238
|
+
{/snippet}
|
|
1239
|
+
</Histogram>
|
|
1240
|
+
{/if}
|
|
1241
|
+
{/if}
|
|
1242
|
+
</div>
|
|
1243
|
+
{:else}
|
|
1244
|
+
<EmptyState class="trajectory-empty-state">
|
|
1245
|
+
<h3 id="load-trajectory">Load Trajectory</h3>
|
|
1246
|
+
<p>
|
|
1247
|
+
Drop a trajectory file here (.xyz, .extxyz, .json, .json.gz, XDATCAR, .traj, .h5)
|
|
1248
|
+
or provide trajectory data via props
|
|
1249
|
+
</p>
|
|
1250
|
+
<strong style="display: block; margin-block: 1em 1ex">Supported formats:</strong>
|
|
1251
|
+
<ul>
|
|
1252
|
+
<li>Multi-frame XYZ trajectory files (.xyz, .extxyz)</li>
|
|
1253
|
+
<li>ASE trajectory files (.traj)</li>
|
|
1254
|
+
<li>Pymatgen trajectory JSON</li>
|
|
1255
|
+
<li>Array of structures with metadata</li>
|
|
1256
|
+
<li>VASP XDATCAR files</li>
|
|
1257
|
+
<li>HDF5 trajectory files (.h5, .hdf5)</li>
|
|
1258
|
+
<li>Compressed files (.gz)</li>
|
|
1259
|
+
</ul>
|
|
1260
|
+
<p>
|
|
1261
|
+
💡 Force vectors will be automatically displayed when present in trajectory data
|
|
1262
|
+
</p>
|
|
1263
|
+
</EmptyState>
|
|
1264
|
+
{/if}
|
|
1265
|
+
</div>
|
|
1266
|
+
|
|
1267
|
+
<style>
|
|
1268
|
+
.trajectory {
|
|
1269
|
+
--min-height: 500px;
|
|
1270
|
+
display: flex;
|
|
1271
|
+
flex-direction: column;
|
|
1272
|
+
height: var(--traj-height, 100%);
|
|
1273
|
+
position: relative;
|
|
1274
|
+
min-height: var(--traj-min-height, var(--min-height));
|
|
1275
|
+
border-radius: var(--traj-border-radius, var(--border-radius, 3pt));
|
|
1276
|
+
box-sizing: border-box;
|
|
1277
|
+
contain: layout;
|
|
1278
|
+
z-index: var(--traj-z-index, 1);
|
|
1279
|
+
container-type: size; /* enable cqh for panes if explicit height is set */
|
|
1280
|
+
:global(.plot) {
|
|
1281
|
+
background: var(--surface-bg);
|
|
1282
|
+
}
|
|
1283
|
+
&.active {
|
|
1284
|
+
z-index: 2; /* needed so info/control panes from an active viewer overlay those of the next (if there is one) */
|
|
1285
|
+
.trajectory-controls {
|
|
1286
|
+
z-index: 5; /* needed so info/control panes from an active viewer its own plot when active, not sure why needed */
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
&:fullscreen {
|
|
1290
|
+
height: 100vh !important;
|
|
1291
|
+
width: 100vw !important;
|
|
1292
|
+
border-radius: 0 !important;
|
|
1293
|
+
background: var(--surface-bg);
|
|
1294
|
+
overflow: hidden;
|
|
1295
|
+
}
|
|
1296
|
+
&.horizontal .content-area {
|
|
1297
|
+
grid-template-columns: 1fr 1fr;
|
|
1298
|
+
grid-template-rows: 1fr;
|
|
1299
|
+
}
|
|
1300
|
+
&.vertical .content-area {
|
|
1301
|
+
grid-template-columns: 1fr;
|
|
1302
|
+
grid-template-rows: 1fr 1fr;
|
|
1303
|
+
}
|
|
1304
|
+
/* Display mode specific layouts */
|
|
1305
|
+
&:is(.horizontal, .vertical) .content-area:is(.show-structure-only, .show-plot-only) {
|
|
1306
|
+
grid-template-columns: 1fr !important;
|
|
1307
|
+
grid-template-rows: 1fr !important;
|
|
1308
|
+
}
|
|
1309
|
+
&.dragover {
|
|
1310
|
+
background-color: var(--traj-dragover-bg, var(--dragover-bg));
|
|
1311
|
+
border: var(--traj-dragover-border, var(--dragover-border));
|
|
1312
|
+
}
|
|
1313
|
+
/* Mode: hover - controls visible on component hover */
|
|
1314
|
+
&:hover .trajectory-controls.hover-visible,
|
|
1315
|
+
&:focus-within .trajectory-controls.hover-visible {
|
|
1316
|
+
opacity: 1;
|
|
1317
|
+
pointer-events: auto;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
/* Content area - grid container for equal sizing */
|
|
1321
|
+
.content-area {
|
|
1322
|
+
display: grid;
|
|
1323
|
+
flex: 1;
|
|
1324
|
+
min-height: 0; /* important for tall structure viewers not to overflow */
|
|
1325
|
+
/* When plot or structure is hidden, the other takes full space */
|
|
1326
|
+
&:is(.hide-plot, .hide-structure) {
|
|
1327
|
+
grid-template-columns: 1fr !important;
|
|
1328
|
+
grid-template-rows: 1fr !important;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
.trajectory-controls {
|
|
1332
|
+
display: flex;
|
|
1333
|
+
align-items: center;
|
|
1334
|
+
gap: clamp(2pt, 1cqw, 1ex);
|
|
1335
|
+
padding: clamp(2pt, 0.5cqw, 1ex) clamp(4pt, 1cqw, 1.2ex);
|
|
1336
|
+
background: var(--surface-bg-hover);
|
|
1337
|
+
backdrop-filter: blur(4px);
|
|
1338
|
+
position: relative;
|
|
1339
|
+
border-radius: var(--border-radius, 3pt) var(--border-radius, 3pt) 0 0;
|
|
1340
|
+
opacity: 0;
|
|
1341
|
+
pointer-events: none;
|
|
1342
|
+
transition: opacity 0.2s ease;
|
|
1343
|
+
/* Mode: always - controls always visible */
|
|
1344
|
+
&.always-visible {
|
|
1345
|
+
opacity: 1;
|
|
1346
|
+
pointer-events: auto;
|
|
1347
|
+
}
|
|
1348
|
+
/* Mode: never - stays hidden (default state, no additional CSS needed) */
|
|
1349
|
+
&:focus-within {
|
|
1350
|
+
z-index: var(--traj-controls-z-index, 999999999);
|
|
1351
|
+
}
|
|
1352
|
+
button {
|
|
1353
|
+
background: var(--btn-bg);
|
|
1354
|
+
font-size: clamp(0.8rem, 2cqw, 1rem);
|
|
1355
|
+
&:hover:not(:disabled) {
|
|
1356
|
+
background: var(--btn-bg-hover);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
input[type='number'] {
|
|
1360
|
+
&::-webkit-outer-spin-button,
|
|
1361
|
+
&::-webkit-inner-spin-button {
|
|
1362
|
+
-webkit-appearance: none;
|
|
1363
|
+
margin: 0;
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
.nav-section {
|
|
1368
|
+
display: flex;
|
|
1369
|
+
align-items: center;
|
|
1370
|
+
gap: clamp(1pt, 0.5cqw, 5pt);
|
|
1371
|
+
}
|
|
1372
|
+
.step-section {
|
|
1373
|
+
display: flex;
|
|
1374
|
+
align-items: center;
|
|
1375
|
+
gap: clamp(0.25rem, 1.5cqw, 0.5rem);
|
|
1376
|
+
flex: 1;
|
|
1377
|
+
min-width: 0;
|
|
1378
|
+
}
|
|
1379
|
+
.step-input {
|
|
1380
|
+
border: 1px solid rgba(99, 179, 237, 0.3);
|
|
1381
|
+
text-align: center;
|
|
1382
|
+
margin: 0 -5px 0 0;
|
|
1383
|
+
padding: 2px;
|
|
1384
|
+
}
|
|
1385
|
+
.slider-container {
|
|
1386
|
+
position: relative;
|
|
1387
|
+
flex: 1;
|
|
1388
|
+
min-width: var(--trajectory-slider-min-width, 100px);
|
|
1389
|
+
}
|
|
1390
|
+
.step-slider {
|
|
1391
|
+
width: 100%;
|
|
1392
|
+
accent-color: var(--accent-color);
|
|
1393
|
+
}
|
|
1394
|
+
.step-labels {
|
|
1395
|
+
position: absolute;
|
|
1396
|
+
left: 0;
|
|
1397
|
+
right: 0;
|
|
1398
|
+
}
|
|
1399
|
+
.step-tick {
|
|
1400
|
+
position: absolute;
|
|
1401
|
+
transform: translateX(-50%);
|
|
1402
|
+
width: var(--trajectory-step-tick-width, 1px);
|
|
1403
|
+
height: var(--trajectory-step-tick-height, 4px);
|
|
1404
|
+
background: var(--text-color-muted);
|
|
1405
|
+
top: -9pt;
|
|
1406
|
+
}
|
|
1407
|
+
.step-label {
|
|
1408
|
+
position: absolute;
|
|
1409
|
+
transform: translateX(-50%);
|
|
1410
|
+
font-size: clamp(0.5em, 1.2cqw, 0.65em);
|
|
1411
|
+
color: var(--text-color-muted);
|
|
1412
|
+
white-space: nowrap;
|
|
1413
|
+
text-align: center;
|
|
1414
|
+
top: -1.7ex;
|
|
1415
|
+
}
|
|
1416
|
+
button.filename {
|
|
1417
|
+
align-items: center;
|
|
1418
|
+
white-space: nowrap;
|
|
1419
|
+
padding: var(--trajectory-filename-padding, 3pt 4pt);
|
|
1420
|
+
border-radius: var(--trajectory-filename-border-radius, var(--border-radius, 3pt));
|
|
1421
|
+
max-width: clamp(150px, 20cqw, 250px);
|
|
1422
|
+
overflow: hidden;
|
|
1423
|
+
text-overflow: ellipsis;
|
|
1424
|
+
display: inline-block;
|
|
1425
|
+
position: relative;
|
|
1426
|
+
font-family: monospace;
|
|
1427
|
+
font-size: 0.9em;
|
|
1428
|
+
background: var(--code-bg, rgba(0, 0, 0, 0.1));
|
|
1429
|
+
}
|
|
1430
|
+
@keyframes fade-in {
|
|
1431
|
+
from {
|
|
1432
|
+
opacity: 0;
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
.fullscreen-button {
|
|
1436
|
+
background: transparent !important;
|
|
1437
|
+
padding: 0;
|
|
1438
|
+
&:hover:not(:disabled) {
|
|
1439
|
+
background: var(--border-color);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
.info-section {
|
|
1443
|
+
display: flex;
|
|
1444
|
+
align-items: center;
|
|
1445
|
+
gap: clamp(3pt, 0.6cqw, 1ex);
|
|
1446
|
+
position: relative;
|
|
1447
|
+
}
|
|
1448
|
+
.info-section :global(:is(.trajectory-info-toggle, .trajectory-export-toggle)) {
|
|
1449
|
+
font-size: clamp(1rem, 2.2cqw, 1.1rem);
|
|
1450
|
+
}
|
|
1451
|
+
.play-button {
|
|
1452
|
+
min-width: clamp(32px, 4cqw, 36px);
|
|
1453
|
+
&:hover:not(:disabled) {
|
|
1454
|
+
background: var(--traj-play-btn-bg-hover, var(--btn-bg-hover, rgba(0, 0, 0, 0.2)));
|
|
1455
|
+
}
|
|
1456
|
+
&.playing {
|
|
1457
|
+
background: var(--traj-pause-btn-bg, var(--btn-bg, rgba(0, 0, 0, 0.1)));
|
|
1458
|
+
&:hover:not(:disabled) {
|
|
1459
|
+
background: var(
|
|
1460
|
+
--traj-pause-btn-bg-hover,
|
|
1461
|
+
var(--btn-bg-hover, rgba(0, 0, 0, 0.1))
|
|
1462
|
+
);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
:global(.trajectory-empty-state) {
|
|
1467
|
+
padding: 2rem;
|
|
1468
|
+
border-radius: var(--border-radius, 3pt);
|
|
1469
|
+
background: var(--dropzone-bg);
|
|
1470
|
+
:where(p, ul) {
|
|
1471
|
+
color: var(--text-color-muted);
|
|
1472
|
+
}
|
|
1473
|
+
:where(ul, li, strong) {
|
|
1474
|
+
max-width: var(--trajectory-empty-state-max-width, 500px);
|
|
1475
|
+
margin-inline: auto;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
button {
|
|
1479
|
+
&:hover:not(:disabled) {
|
|
1480
|
+
background: var(--border-color);
|
|
1481
|
+
}
|
|
1482
|
+
&:disabled {
|
|
1483
|
+
background: var(--btn-disabled-bg);
|
|
1484
|
+
color: var(--text-color-muted);
|
|
1485
|
+
cursor: not-allowed;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
/* Responsive design */
|
|
1489
|
+
@media (orientation: portrait) {
|
|
1490
|
+
.trajectory {
|
|
1491
|
+
/* Fallback class for browsers without :has() support */
|
|
1492
|
+
&.show-both-views {
|
|
1493
|
+
min-height: calc(var(--min-height) * 2);
|
|
1494
|
+
}
|
|
1495
|
+
/* Modern browsers: use :has() for same effect */
|
|
1496
|
+
@supports selector(:has(.content-area)) {
|
|
1497
|
+
&:has(.content-area.show-both:not(.hide-plot):not(.hide-structure)) {
|
|
1498
|
+
min-height: calc(var(--min-height) * 2);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
.content-area.show-both:not(.hide-plot):not(.hide-structure) {
|
|
1502
|
+
grid-template-columns: 1fr !important;
|
|
1503
|
+
grid-template-rows: 1fr 1fr !important;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
.view-mode-dropdown-wrapper {
|
|
1508
|
+
display: flex;
|
|
1509
|
+
position: relative;
|
|
1510
|
+
}
|
|
1511
|
+
.view-mode-dropdown {
|
|
1512
|
+
position: absolute;
|
|
1513
|
+
top: 115%;
|
|
1514
|
+
right: 0;
|
|
1515
|
+
background: var(--surface-bg);
|
|
1516
|
+
border-radius: 4px;
|
|
1517
|
+
box-shadow: 0 8px 16px -4px rgba(0, 0, 0, 0.3), 0 4px 8px -2px rgba(0, 0, 0, 0.1);
|
|
1518
|
+
}
|
|
1519
|
+
.view-mode-option {
|
|
1520
|
+
display: flex;
|
|
1521
|
+
align-items: center;
|
|
1522
|
+
gap: 1ex;
|
|
1523
|
+
width: 100%;
|
|
1524
|
+
padding: var(--trajectory-view-mode-option-padding, 5pt);
|
|
1525
|
+
box-sizing: border-box;
|
|
1526
|
+
background: transparent;
|
|
1527
|
+
border-radius: 0;
|
|
1528
|
+
text-align: left;
|
|
1529
|
+
transition: background-color 0.15s ease;
|
|
1530
|
+
&:first-child {
|
|
1531
|
+
border-top-left-radius: 3px;
|
|
1532
|
+
border-top-right-radius: 3px;
|
|
1533
|
+
}
|
|
1534
|
+
&.selected {
|
|
1535
|
+
color: var(--accent-color);
|
|
1536
|
+
}
|
|
1537
|
+
span {
|
|
1538
|
+
font-weight: 500;
|
|
1539
|
+
white-space: nowrap;
|
|
1540
|
+
overflow: hidden;
|
|
1541
|
+
text-overflow: ellipsis;
|
|
1542
|
+
flex: 1;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
</style>
|