matterviz 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -4
- package/dist/FilePicker.svelte +48 -60
- package/dist/Icon.svelte +7 -4
- package/dist/MillerIndexInput.svelte +2 -2
- package/dist/api/optimade.js +10 -7
- package/dist/app.css +68 -0
- package/dist/brillouin/BrillouinZone.svelte +90 -91
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -7
- package/dist/brillouin/BrillouinZoneControls.svelte +3 -6
- package/dist/brillouin/BrillouinZoneExportPane.svelte +18 -14
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +6 -10
- package/dist/brillouin/BrillouinZoneScene.svelte +46 -68
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/compute.js +10 -16
- package/dist/brillouin/geometry.js +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +48 -50
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +61 -169
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +559 -755
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +1 -1
- package/dist/chempot-diagram/async-compute.svelte.js +13 -14
- package/dist/chempot-diagram/color.d.ts +21 -1
- package/dist/chempot-diagram/color.js +70 -1
- package/dist/chempot-diagram/compute.d.ts +7 -0
- package/dist/chempot-diagram/compute.js +85 -26
- package/dist/chempot-diagram/controls-state.svelte.js +1 -1
- package/dist/chempot-diagram/export.js +1 -6
- package/dist/chempot-diagram/temperature.js +9 -10
- package/dist/colors/index.d.ts +0 -4
- package/dist/colors/index.js +19 -20
- package/dist/composition/BarChart.svelte +30 -26
- package/dist/composition/BubbleChart.svelte +17 -17
- package/dist/composition/Composition.svelte +10 -19
- package/dist/composition/Formula.svelte +20 -27
- package/dist/composition/FormulaFilter.svelte +115 -184
- package/dist/composition/PieChart.svelte +55 -41
- package/dist/composition/format.js +7 -9
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/index.js +14 -0
- package/dist/composition/parse.d.ts +2 -2
- package/dist/composition/parse.js +61 -115
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +17 -26
- package/dist/convex-hull/ConvexHull.svelte +12 -15
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +93 -94
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +127 -186
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +131 -180
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +36 -40
- package/dist/convex-hull/ConvexHullControls.svelte +46 -48
- package/dist/convex-hull/ConvexHullStats.svelte +193 -195
- package/dist/convex-hull/ConvexHullTooltip.svelte +5 -12
- package/dist/convex-hull/GasPressureControls.svelte +5 -12
- package/dist/convex-hull/StructurePopup.svelte +18 -22
- package/dist/convex-hull/StructurePopup.svelte.d.ts +2 -0
- package/dist/convex-hull/TemperatureSlider.svelte +4 -10
- package/dist/convex-hull/canvas-interactions.svelte.js +2 -1
- package/dist/convex-hull/gas-thermodynamics.js +21 -53
- package/dist/convex-hull/helpers.d.ts +8 -10
- package/dist/convex-hull/helpers.js +37 -43
- package/dist/convex-hull/hull-state.svelte.d.ts +1 -1
- package/dist/convex-hull/thermodynamics.js +37 -44
- package/dist/coordination/CoordinationBarPlot.svelte +49 -53
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +1 -1
- package/dist/coordination/calc-coordination.d.ts +1 -1
- package/dist/coordination/calc-coordination.js +28 -25
- package/dist/element/BohrAtom.svelte +5 -9
- package/dist/element/ElementHeading.svelte +4 -1
- package/dist/element/ElementPhoto.svelte +11 -9
- package/dist/element/ElementStats.svelte +12 -10
- package/dist/element/ElementTile.svelte +44 -67
- package/dist/element/Nucleus.svelte +4 -2
- package/dist/element/data.d.ts +3 -2
- package/dist/element/data.js +5 -1
- package/dist/element/helpers.d.ts +4 -0
- package/dist/element/helpers.js +18 -0
- package/dist/element/index.d.ts +2 -5
- package/dist/element/index.js +4 -19
- package/dist/feedback/DragOverlay.svelte +5 -5
- package/dist/feedback/DragOverlay.svelte.d.ts +2 -2
- package/dist/feedback/StatusMessage.svelte +7 -4
- package/dist/fermi-surface/FermiSlice.svelte +21 -18
- package/dist/fermi-surface/FermiSurface.svelte +35 -44
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +7 -13
- package/dist/fermi-surface/FermiSurfaceControls.svelte +6 -20
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +64 -136
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +9 -6
- package/dist/fermi-surface/compute.js +25 -58
- package/dist/fermi-surface/parse.js +54 -88
- package/dist/file-viewer/JsonBrowser.svelte +1043 -0
- package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
- package/dist/file-viewer/PlotPanel.svelte +350 -0
- package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
- package/dist/file-viewer/detect.d.ts +11 -0
- package/dist/file-viewer/detect.js +381 -0
- package/dist/file-viewer/eligibility.d.ts +4 -0
- package/dist/file-viewer/eligibility.js +53 -0
- package/dist/file-viewer/host-protocol.d.ts +50 -0
- package/dist/file-viewer/host-transfer.d.ts +25 -0
- package/dist/file-viewer/host-transfer.js +42 -0
- package/dist/file-viewer/index.d.ts +5 -0
- package/dist/file-viewer/index.js +5 -0
- package/dist/file-viewer/main.d.ts +44 -0
- package/dist/file-viewer/main.js +535 -0
- package/dist/file-viewer/parse.d.ts +9 -0
- package/dist/file-viewer/parse.js +170 -0
- package/dist/file-viewer/plot-utils.d.ts +24 -0
- package/dist/file-viewer/plot-utils.js +191 -0
- package/dist/file-viewer/types.d.ts +4 -0
- package/dist/file-viewer/types.js +5 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +153 -219
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +9 -7
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/index.d.ts +5 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/io/ExportPane.svelte +11 -7
- package/dist/io/decompress.d.ts +4 -1
- package/dist/io/decompress.js +24 -36
- package/dist/io/export.d.ts +11 -4
- package/dist/io/export.js +75 -19
- package/dist/io/fetch.d.ts +0 -3
- package/dist/io/fetch.js +0 -11
- package/dist/io/file-drop.js +60 -35
- package/dist/io/index.d.ts +0 -1
- package/dist/io/index.js +2 -9
- package/dist/io/is-binary.d.ts +9 -0
- package/dist/io/is-binary.js +45 -1
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +40 -40
- package/dist/isosurface/Isosurface.svelte +700 -215
- package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
- package/dist/isosurface/IsosurfaceControls.svelte +590 -116
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
- package/dist/isosurface/VolumeSlice.svelte +224 -0
- package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
- package/dist/isosurface/coloring.d.ts +20 -0
- package/dist/isosurface/coloring.js +118 -0
- package/dist/isosurface/geometry-worker-types.d.ts +38 -0
- package/dist/isosurface/geometry.worker.d.ts +1 -0
- package/dist/isosurface/geometry.worker.js +59 -0
- package/dist/isosurface/grid.d.ts +10 -0
- package/dist/isosurface/grid.js +31 -0
- package/dist/isosurface/index.d.ts +4 -0
- package/dist/isosurface/index.js +4 -0
- package/dist/isosurface/parse-vaspwave.d.ts +3 -0
- package/dist/isosurface/parse-vaspwave.js +138 -0
- package/dist/isosurface/parse.js +6 -6
- package/dist/isosurface/profile.d.ts +12 -0
- package/dist/isosurface/profile.js +19 -0
- package/dist/isosurface/sampling.d.ts +34 -0
- package/dist/isosurface/sampling.js +408 -0
- package/dist/isosurface/slice-rendering.d.ts +13 -0
- package/dist/isosurface/slice-rendering.js +79 -0
- package/dist/isosurface/slice.d.ts +22 -2
- package/dist/isosurface/slice.js +200 -116
- package/dist/isosurface/types.d.ts +24 -1
- package/dist/isosurface/types.js +120 -8
- package/dist/json-path.d.ts +4 -0
- package/dist/json-path.js +89 -0
- package/dist/labels.d.ts +6 -2
- package/dist/labels.js +44 -14
- package/dist/layout/FullscreenButton.svelte +2 -1
- package/dist/layout/FullscreenToggle.svelte +10 -4
- package/dist/layout/InfoCard.svelte +8 -21
- package/dist/layout/InfoTag.svelte +1 -3
- package/dist/layout/NumberRangeInput.svelte +46 -0
- package/dist/layout/NumberRangeInput.svelte.d.ts +12 -0
- package/dist/layout/PropertyFilter.svelte +2 -6
- package/dist/layout/SettingsSection.svelte +57 -62
- package/dist/layout/SettingsSection.svelte.d.ts +6 -7
- package/dist/layout/SubpageGrid.svelte +3 -1
- package/dist/layout/ViewerChrome.svelte +16 -11
- package/dist/layout/ViewerChrome.svelte.d.ts +2 -1
- package/dist/layout/fullscreen.js +3 -5
- package/dist/layout/fullscreen.svelte.js +1 -2
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +22 -59
- package/dist/layout/json-tree/JsonTree.svelte +101 -172
- package/dist/layout/json-tree/JsonValue.svelte +9 -32
- package/dist/layout/json-tree/utils.d.ts +0 -3
- package/dist/layout/json-tree/utils.js +50 -188
- package/dist/marching-cubes.d.ts +8 -1
- package/dist/marching-cubes.js +115 -48
- package/dist/math.d.ts +5 -2
- package/dist/math.js +48 -38
- package/dist/overlays/ContextMenu.svelte +19 -34
- package/dist/overlays/CopyButton.svelte +11 -5
- package/dist/overlays/DragControlTab.svelte +6 -1
- package/dist/overlays/DraggablePane.svelte +110 -74
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -1
- package/dist/overlays/GlassChip.svelte +32 -0
- package/dist/overlays/GlassChip.svelte.d.ts +8 -0
- package/dist/overlays/InfoPaneCards.svelte +11 -23
- package/dist/overlays/index.d.ts +7 -0
- package/dist/overlays/index.js +26 -0
- package/dist/overlays/portal.d.ts +2 -0
- package/dist/overlays/portal.js +14 -0
- package/dist/periodic-table/PeriodicTable.svelte +113 -145
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +5 -3
- package/dist/periodic-table/PeriodicTableControls.svelte +37 -115
- package/dist/periodic-table/TableInset.svelte +9 -4
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +68 -105
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -8
- package/dist/phase-diagram/PhaseDiagramControls.svelte +70 -94
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +12 -12
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +54 -58
- package/dist/phase-diagram/TdbInfoPanel.svelte +21 -15
- package/dist/phase-diagram/build-diagram.js +4 -9
- package/dist/phase-diagram/diagram-input.d.ts +1 -2
- package/dist/phase-diagram/parse.js +15 -15
- package/dist/phase-diagram/svg-to-diagram.js +28 -27
- package/dist/phase-diagram/utils.js +2 -3
- package/dist/plot/bar/BarPlot.svelte +461 -426
- package/dist/plot/bar/BarPlot.svelte.d.ts +2 -0
- package/dist/plot/bar/BarPlotControls.svelte +1 -3
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +4 -6
- package/dist/plot/bar/SpacegroupBarPlot.svelte +46 -77
- package/dist/plot/bar/data.d.ts +5 -4
- package/dist/plot/bar/data.js +2 -1
- package/dist/plot/box/BoxPlot.svelte +322 -226
- package/dist/plot/box/BoxPlot.svelte.d.ts +2 -0
- package/dist/plot/box/Violin.svelte.d.ts +1 -0
- package/dist/plot/box/box-plot.js +1 -1
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +2 -2
- package/dist/plot/core/axis-utils.d.ts +12 -7
- package/dist/plot/core/axis-utils.js +48 -48
- package/dist/plot/core/components/AxisLabel.svelte +82 -20
- package/dist/plot/core/components/AxisLabel.svelte.d.ts +1 -0
- package/dist/plot/core/components/ColorBar.svelte +101 -106
- package/dist/plot/core/components/ColorScaleSelect.svelte +1 -1
- package/dist/plot/core/components/FillArea.svelte +10 -17
- package/dist/plot/core/components/HierarchyControls.svelte +249 -0
- package/dist/plot/{sunburst/SunburstControls.svelte.d.ts → core/components/HierarchyControls.svelte.d.ts} +12 -8
- package/dist/plot/core/components/InteractiveAxisLabel.svelte +1 -1
- package/dist/plot/core/components/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/core/components/Line.svelte +18 -9
- package/dist/plot/core/components/Line.svelte.d.ts +2 -0
- package/dist/plot/core/components/PlotAxis.svelte +40 -17
- package/dist/plot/core/components/PlotControls.svelte +65 -41
- package/dist/plot/core/components/PlotLegend.svelte +31 -35
- package/dist/plot/core/components/PlotMarginals.svelte +616 -0
- package/dist/plot/core/components/PlotMarginals.svelte.d.ts +15 -0
- package/dist/plot/core/components/PlotTooltip.svelte +1 -1
- package/dist/plot/core/components/PortalSelect.svelte +4 -8
- package/dist/plot/core/components/ReferenceLine.svelte +27 -24
- package/dist/plot/core/components/ReferenceLine3D.svelte +54 -57
- package/dist/plot/core/components/ReferencePlane.svelte +7 -8
- package/dist/plot/core/components/ZeroLines.svelte +4 -8
- package/dist/plot/core/components/ZoomRect.svelte +1 -2
- package/dist/plot/core/components/index.d.ts +1 -0
- package/dist/plot/core/components/index.js +1 -0
- package/dist/plot/core/data-cleaning-signal.d.ts +46 -0
- package/dist/plot/core/data-cleaning-signal.js +467 -0
- package/dist/plot/core/data-cleaning.d.ts +2 -42
- package/dist/plot/core/data-cleaning.js +27 -474
- package/dist/plot/core/data-transform.d.ts +1 -2
- package/dist/plot/core/data-transform.js +9 -15
- package/dist/plot/core/fill-utils.d.ts +3 -1
- package/dist/plot/core/fill-utils.js +28 -6
- package/dist/plot/core/index.d.ts +1 -0
- package/dist/plot/core/index.js +1 -0
- package/dist/plot/core/interactions.js +0 -2
- package/dist/plot/core/layout.d.ts +15 -6
- package/dist/plot/core/layout.js +57 -38
- package/dist/plot/core/marginals.d.ts +170 -0
- package/dist/plot/core/marginals.js +436 -0
- package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
- package/dist/plot/core/pan-zoom.svelte.js +34 -17
- package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -21
- package/dist/plot/core/reference-line.js +1 -1
- package/dist/plot/core/scales.d.ts +23 -0
- package/dist/plot/core/scales.js +39 -13
- package/dist/plot/core/svg.js +0 -1
- package/dist/plot/core/types/fills.d.ts +101 -0
- package/dist/plot/core/types/fills.js +15 -0
- package/dist/plot/core/types/plot-3d.d.ts +87 -0
- package/dist/plot/core/types/plot-3d.js +4 -0
- package/dist/plot/core/types/reference-lines.d.ts +140 -0
- package/dist/plot/core/types/reference-lines.js +9 -0
- package/dist/plot/core/types.d.ts +29 -324
- package/dist/plot/core/types.js +23 -20
- package/dist/plot/core/utils/hierarchy-chart.d.ts +52 -0
- package/dist/plot/core/utils/hierarchy-chart.js +191 -0
- package/dist/plot/core/utils/hierarchy-labels.d.ts +20 -0
- package/dist/plot/core/utils/hierarchy-labels.js +100 -0
- package/dist/plot/core/utils/label-placement.js +2 -2
- package/dist/plot/histogram/Histogram.svelte +314 -340
- package/dist/plot/histogram/Histogram.svelte.d.ts +7 -7
- package/dist/plot/histogram/HistogramControls.svelte +30 -28
- package/dist/plot/histogram/histogram.d.ts +31 -0
- package/dist/plot/histogram/histogram.js +70 -0
- package/dist/plot/histogram/index.d.ts +1 -0
- package/dist/plot/histogram/index.js +1 -0
- package/dist/plot/index.d.ts +1 -0
- package/dist/plot/index.js +1 -0
- package/dist/plot/sankey/Sankey.svelte +78 -69
- package/dist/plot/sankey/Sankey.svelte.d.ts +2 -2
- package/dist/plot/sankey/SankeyControls.svelte +22 -16
- package/dist/plot/sankey/sankey.js +13 -9
- package/dist/plot/scatter/BinnedScatterPlot.svelte +311 -141
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +7 -0
- package/dist/plot/scatter/ElementScatter.svelte +4 -1
- package/dist/plot/scatter/ScatterPlot.svelte +517 -410
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +2 -0
- package/dist/plot/scatter/ScatterPlotControls.svelte +18 -19
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/ScatterPoint.svelte +16 -9
- package/dist/plot/scatter/adaptive-density.d.ts +1 -1
- package/dist/plot/scatter/adaptive-density.js +36 -20
- package/dist/plot/scatter/binned-scatter-types.d.ts +3 -2
- package/dist/plot/scatter/binned-scatter-types.js +6 -1
- package/dist/plot/scatter/scatter-data.d.ts +1 -1
- package/dist/plot/scatter/scatter-data.js +8 -7
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +25 -34
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +8 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +113 -116
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/scatter-3d/Surface3D.svelte +4 -13
- package/dist/plot/sunburst/Sunburst.svelte +269 -347
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +2 -2
- package/dist/plot/sunburst/index.d.ts +1 -1
- package/dist/plot/sunburst/index.js +2 -1
- package/dist/plot/sunburst/render.d.ts +2 -2
- package/dist/plot/sunburst/render.js +47 -22
- package/dist/plot/sunburst/sunburst.d.ts +5 -1
- package/dist/plot/sunburst/sunburst.js +10 -3
- package/dist/plot/treemap/Treemap.svelte +1022 -0
- package/dist/plot/treemap/Treemap.svelte.d.ts +90 -0
- package/dist/plot/treemap/index.d.ts +4 -0
- package/dist/plot/treemap/index.js +4 -0
- package/dist/plot/treemap/labels.d.ts +38 -0
- package/dist/plot/treemap/labels.js +80 -0
- package/dist/plot/treemap/treemap.d.ts +28 -0
- package/dist/plot/treemap/treemap.js +102 -0
- package/dist/rdf/RdfPlot.svelte +37 -59
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/calc-rdf.js +63 -52
- package/dist/rdf/index.d.ts +0 -1
- package/dist/sanitize.js +85 -27
- package/dist/scene/SceneCamera.svelte +1 -1
- package/dist/scene/SceneCamera.svelte.d.ts +1 -1
- package/dist/scene/bind-renderer.svelte.js +14 -6
- package/dist/scene/index.d.ts +1 -2
- package/dist/scene/index.js +1 -1
- package/dist/scene/{props.js → props.svelte.js} +15 -1
- package/dist/settings.d.ts +19 -9
- package/dist/settings.js +229 -525
- package/dist/spectral/Bands.svelte +207 -221
- package/dist/spectral/BandsAndDos.svelte +11 -9
- package/dist/spectral/BrillouinBandsDos.svelte +19 -42
- package/dist/spectral/Dos.svelte +92 -93
- package/dist/spectral/helpers.d.ts +3 -3
- package/dist/spectral/helpers.js +65 -140
- package/dist/state.svelte.js +5 -18
- package/dist/structure/Arrow.svelte +5 -18
- package/dist/structure/ArrowInstances.svelte +160 -0
- package/dist/structure/ArrowInstances.svelte.d.ts +16 -0
- package/dist/structure/AtomLegend.svelte +120 -85
- package/dist/structure/AtomLegend.svelte.d.ts +2 -3
- package/dist/structure/Bond.svelte +31 -23
- package/dist/structure/CanvasTooltip.svelte +15 -3
- package/dist/structure/CellSelect.svelte +45 -35
- package/dist/structure/Cylinder.svelte +24 -40
- package/dist/structure/InstancedAtoms.svelte +114 -0
- package/dist/structure/InstancedAtoms.svelte.d.ts +15 -0
- package/dist/structure/Lattice.svelte +85 -149
- package/dist/structure/SiteLabels.svelte +122 -0
- package/dist/structure/SiteLabels.svelte.d.ts +18 -0
- package/dist/structure/Structure.svelte +636 -504
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureCarousel.svelte +637 -0
- package/dist/structure/StructureCarousel.svelte.d.ts +19 -0
- package/dist/structure/StructureControls.svelte +165 -425
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureExportPane.svelte +17 -21
- package/dist/structure/StructureInfoPane.svelte +128 -133
- package/dist/structure/StructureInfoPane.svelte.d.ts +1 -1
- package/dist/structure/StructureScene.svelte +535 -578
- package/dist/structure/StructureScene.svelte.d.ts +6 -2
- package/dist/structure/StructureViewport.svelte +451 -0
- package/dist/structure/StructureViewport.svelte.d.ts +65 -0
- package/dist/structure/atom-label-placement.d.ts +16 -12
- package/dist/structure/atom-label-placement.js +70 -37
- package/dist/structure/atom-properties.d.ts +2 -0
- package/dist/structure/atom-properties.js +105 -38
- package/dist/structure/bond-order-perception.js +3 -8
- package/dist/structure/bonding.d.ts +9 -3
- package/dist/structure/bonding.js +95 -46
- package/dist/structure/edit-history.d.ts +6 -0
- package/dist/structure/edit-history.js +27 -0
- package/dist/structure/export.d.ts +1 -0
- package/dist/structure/export.js +89 -105
- package/dist/structure/format-detect.d.ts +1 -0
- package/dist/structure/format-detect.js +20 -0
- package/dist/structure/geometry.d.ts +9 -0
- package/dist/structure/geometry.js +27 -0
- package/dist/structure/index.d.ts +16 -1
- package/dist/structure/index.js +15 -10
- package/dist/structure/measure.d.ts +1 -1
- package/dist/structure/measure.js +6 -12
- package/dist/structure/parse.d.ts +2 -1
- package/dist/structure/parse.js +272 -313
- package/dist/structure/partial-occupancy.js +10 -5
- package/dist/structure/pbc.js +85 -107
- package/dist/structure/polyhedra.d.ts +0 -1
- package/dist/structure/polyhedra.js +7 -21
- package/dist/structure/prop-groups.d.ts +85 -0
- package/dist/structure/prop-groups.js +18 -0
- package/dist/structure/supercell.d.ts +1 -2
- package/dist/structure/supercell.js +7 -13
- package/dist/symmetry/SymmetryElements.svelte +11 -15
- package/dist/symmetry/SymmetryStats.svelte +55 -71
- package/dist/symmetry/WyckoffTable.svelte +10 -28
- package/dist/symmetry/cell-transform.js +6 -14
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +13 -10
- package/dist/symmetry/spacegroups.js +3 -2
- package/dist/table/HeatmapTable.svelte +1142 -447
- package/dist/table/HeatmapTable.svelte.d.ts +12 -2
- package/dist/table/ToggleMenu.svelte +168 -53
- package/dist/table/ToggleMenu.svelte.d.ts +1 -1
- package/dist/table/index.d.ts +21 -6
- package/dist/table/index.js +34 -21
- package/dist/theme/ThemeControl.svelte +16 -8
- package/dist/theme/embedded.d.ts +18 -0
- package/dist/theme/embedded.js +206 -0
- package/dist/theme/index.d.ts +5 -5
- package/dist/theme/index.js +5 -12
- package/dist/theme/themes.mjs +44 -66
- package/dist/tooltip/KCoords.svelte +4 -1
- package/dist/tooltip/TooltipContent.svelte +3 -6
- package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
- package/dist/tooltip/index.d.ts +8 -1
- package/dist/trajectory/Trajectory.svelte +613 -386
- package/dist/trajectory/Trajectory.svelte.d.ts +1 -1
- package/dist/trajectory/TrajectoryError.svelte +12 -74
- package/dist/trajectory/TrajectoryExportPane.svelte +14 -32
- package/dist/trajectory/TrajectoryInfoPane.svelte +127 -164
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
- package/dist/trajectory/extract.js +61 -49
- package/dist/trajectory/format-detect.d.ts +2 -0
- package/dist/trajectory/format-detect.js +17 -13
- package/dist/trajectory/frame-reader.d.ts +2 -0
- package/dist/trajectory/frame-reader.js +35 -32
- package/dist/trajectory/helpers.d.ts +2 -0
- package/dist/trajectory/helpers.js +34 -56
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +5 -8
- package/dist/trajectory/parse/ase.js +1 -1
- package/dist/trajectory/parse/h5-utils.d.ts +13 -0
- package/dist/trajectory/parse/h5-utils.js +109 -0
- package/dist/trajectory/parse/hdf5.d.ts +1 -1
- package/dist/trajectory/parse/hdf5.js +116 -106
- package/dist/trajectory/parse/index.d.ts +6 -6
- package/dist/trajectory/parse/index.js +25 -33
- package/dist/trajectory/parse/lammps.js +8 -12
- package/dist/trajectory/parse/vasp.js +10 -7
- package/dist/trajectory/parse/vaspout-electronic.d.ts +13 -0
- package/dist/trajectory/parse/vaspout-electronic.js +207 -0
- package/dist/trajectory/parse/vaspout-h5.d.ts +4 -0
- package/dist/trajectory/parse/vaspout-h5.js +281 -0
- package/dist/trajectory/parse/xyz.js +59 -9
- package/dist/trajectory/plotting.d.ts +8 -9
- package/dist/trajectory/plotting.js +113 -64
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/xrd/XrdPlot.svelte +79 -118
- package/dist/xrd/broadening.js +2 -1
- package/dist/xrd/calc-xrd.js +24 -62
- package/dist/xrd/parse.d.ts +0 -1
- package/dist/xrd/parse.js +69 -95
- package/package.json +94 -34
- package/readme.md +6 -5
- package/dist/api/mp.d.ts +0 -6
- package/dist/api/mp.js +0 -22
- package/dist/plot/sunburst/SunburstControls.svelte +0 -200
- package/dist/scene/types.d.ts +0 -26
- package/dist/tooltip/types.d.ts +0 -8
- package/dist/trajectory/constants.d.ts +0 -6
- package/dist/trajectory/constants.js +0 -11
- /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
- /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
|
@@ -3,7 +3,7 @@ import { type ElementSymbol } from '../element';
|
|
|
3
3
|
import Spinner from '../feedback/Spinner.svelte';
|
|
4
4
|
import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types';
|
|
5
5
|
import { type FullscreenToggleProp } from '../layout';
|
|
6
|
-
import type { AnyStructure, BondEditMode, BondOrder, MeasureMode, StructureBond } from './';
|
|
6
|
+
import type { AnyStructure, BondEditMode, BondOrder, MeasureMode, StructureBond, StructureView } from './';
|
|
7
7
|
import type { CellType, SymmetrySettings } from '../symmetry';
|
|
8
8
|
import type { MoyoDataset } from '@spglib/moyo-wasm';
|
|
9
9
|
import type { ComponentProps, Snippet } from 'svelte';
|
|
@@ -34,6 +34,8 @@ type $$ComponentProps = {
|
|
|
34
34
|
bond_edit_mode?: BondEditMode;
|
|
35
35
|
bond_edit_order?: BondOrder;
|
|
36
36
|
info_pane_open?: boolean;
|
|
37
|
+
multi_view?: boolean;
|
|
38
|
+
views?: StructureView[];
|
|
37
39
|
fullscreen_toggle?: FullscreenToggleProp;
|
|
38
40
|
bottom_left?: Snippet<[{
|
|
39
41
|
structure?: AnyStructure;
|
|
@@ -74,6 +76,6 @@ type $$ComponentProps = {
|
|
|
74
76
|
on_camera_reset?: EventHandler;
|
|
75
77
|
on_bonds_change?: (bonds: StructureBond[] | undefined) => void;
|
|
76
78
|
} & Omit<ComponentProps<typeof StructureControls>, `children` | `onclose`> & Omit<HTMLAttributes<HTMLDivElement>, `children`>;
|
|
77
|
-
declare const Structure: import("svelte").Component<$$ComponentProps, {}, "
|
|
79
|
+
declare const Structure: import("svelte").Component<$$ComponentProps, {}, "height" | "width" | "dragover" | "color_scheme" | "fullscreen" | "wrapper" | "hovered" | "controls_open" | "structure" | "active_volume_idx" | "background_color" | "background_opacity" | "show_image_atoms" | "sym_data" | "lattice_props" | "measure_mode" | "selected_sites" | "measured_sites" | "bond_edit_mode" | "bond_edit_order" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "atom_color_config" | "volumetric_data" | "isosurface_settings" | "scene_props" | "hovered_site_idx" | "bonds" | "element_mapping" | "supercell_scaling" | "cell_type" | "loading" | "png_dpi" | "highlighted_sites" | "info_pane_open" | "multi_view" | "enable_measure_mode" | "error_msg" | "performance_mode" | "displayed_structure" | "symmetry_settings">;
|
|
78
80
|
type Structure = ReturnType<typeof Structure>;
|
|
79
81
|
export default Structure;
|
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ShowControlsProp } from '../controls'
|
|
3
|
+
import type { StructureCarouselItem } from './'
|
|
4
|
+
import GlassChip from '../overlays/GlassChip.svelte'
|
|
5
|
+
import { portal } from '../overlays/portal'
|
|
6
|
+
import { SvelteSet } from 'svelte/reactivity'
|
|
7
|
+
import Structure from './Structure.svelte'
|
|
8
|
+
|
|
9
|
+
type Layout = `horizontal` | `vertical`
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
items: StructureCarouselItem[]
|
|
13
|
+
layout?: Layout
|
|
14
|
+
height?: number
|
|
15
|
+
min_card_width?: number
|
|
16
|
+
max_rendered_items?: number
|
|
17
|
+
resizable?: boolean
|
|
18
|
+
show_controls?: ShowControlsProp
|
|
19
|
+
empty_message?: string
|
|
20
|
+
on_prefetch_more?: () => void
|
|
21
|
+
// Min delay between on_prefetch_more calls while the item count is
|
|
22
|
+
// unchanged (i.e. while a previous prefetch is still in flight).
|
|
23
|
+
prefetch_cooldown_ms?: number
|
|
24
|
+
// Host element to render the pager (‹ 1–3 / 64 ›) into, e.g. an embedding
|
|
25
|
+
// panel's title bar. When unset the pager floats over the carousel bottom.
|
|
26
|
+
pager_target?: HTMLElement | null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
items,
|
|
31
|
+
layout = `horizontal`,
|
|
32
|
+
height = 360,
|
|
33
|
+
min_card_width = 190,
|
|
34
|
+
max_rendered_items = 8,
|
|
35
|
+
resizable = false,
|
|
36
|
+
show_controls,
|
|
37
|
+
empty_message = `No structures`,
|
|
38
|
+
on_prefetch_more,
|
|
39
|
+
prefetch_cooldown_ms = 1000,
|
|
40
|
+
pager_target = undefined,
|
|
41
|
+
}: Props = $props()
|
|
42
|
+
|
|
43
|
+
let track: HTMLElement | undefined = $state()
|
|
44
|
+
let carousel: HTMLElement | undefined = $state()
|
|
45
|
+
let carousel_width = $state(0)
|
|
46
|
+
let carousel_height = $state(0)
|
|
47
|
+
let resized_height: number | null = $state(null)
|
|
48
|
+
let resized_width: number | null = $state(null)
|
|
49
|
+
let scroll_pos = $state(0) // along the scroll axis (left horizontally, top vertically)
|
|
50
|
+
let last_prefetch_ms = Number.NEGATIVE_INFINITY
|
|
51
|
+
let last_prefetch_item_count = -1
|
|
52
|
+
|
|
53
|
+
type ResizeDrag = {
|
|
54
|
+
axis: `height` | `width`
|
|
55
|
+
start_position: number
|
|
56
|
+
start_size: number
|
|
57
|
+
}
|
|
58
|
+
let resize_drag: ResizeDrag | undefined = $state()
|
|
59
|
+
|
|
60
|
+
const gap = 8
|
|
61
|
+
const min_resize_size = 150
|
|
62
|
+
// wheel delta for deltaMode=DOM_DELTA_LINE, in px per line (Firefox)
|
|
63
|
+
const wheel_line_height_px = 16
|
|
64
|
+
// px per arrow-key press when resizing via keyboard
|
|
65
|
+
const keyboard_resize_step_px = 16
|
|
66
|
+
const effective_height = $derived(
|
|
67
|
+
layout === `horizontal` && resizable ? (resized_height ?? height) : height,
|
|
68
|
+
)
|
|
69
|
+
const effective_width = $derived(
|
|
70
|
+
layout === `vertical` && resizable
|
|
71
|
+
? (resized_width ?? (carousel_width > 0 ? carousel_width : min_card_width))
|
|
72
|
+
: min_card_width,
|
|
73
|
+
)
|
|
74
|
+
const card_width = $derived(layout === `horizontal` ? effective_height : effective_width)
|
|
75
|
+
const max_rendered = $derived(Math.max(1, Math.floor(max_rendered_items)))
|
|
76
|
+
const visible_item_count = $derived(Math.min(items.length, max_rendered))
|
|
77
|
+
// stride follows the scroll axis: card inline-size horizontally, block-size vertically
|
|
78
|
+
const item_stride = $derived((layout === `horizontal` ? card_width : effective_height) + gap)
|
|
79
|
+
const total_scroll_extent = $derived(
|
|
80
|
+
items.length === 0 ? 0 : items.length * item_stride - gap,
|
|
81
|
+
)
|
|
82
|
+
const track_width = $derived(
|
|
83
|
+
Math.max(1, visible_item_count) * card_width + Math.max(0, visible_item_count - 1) * gap,
|
|
84
|
+
)
|
|
85
|
+
const first_visible_idx = $derived(Math.max(0, Math.floor(scroll_pos / item_stride)))
|
|
86
|
+
// Cards per viewport page, measured along the scroll axis: inline-size for
|
|
87
|
+
// horizontal layout, block-size for vertical (mixing axes here previously
|
|
88
|
+
// made vertical prefetch thresholds depend on the carousel's WIDTH)
|
|
89
|
+
const measured_page_size = $derived.by(() => {
|
|
90
|
+
const viewport_size = layout === `horizontal` ? carousel_width : carousel_height
|
|
91
|
+
return viewport_size > 0 ? Math.floor((viewport_size + gap) / item_stride) : 1
|
|
92
|
+
})
|
|
93
|
+
const page_size = $derived(Math.max(1, Math.min(visible_item_count, measured_page_size)))
|
|
94
|
+
const max_page_start = $derived(Math.max(0, items.length - page_size))
|
|
95
|
+
const page_start = $derived(Math.min(max_page_start, first_visible_idx))
|
|
96
|
+
const page_end = $derived(Math.min(items.length, page_start + page_size))
|
|
97
|
+
// How many card ELEMENTS exist (canvas mount timing is live_ids' job below).
|
|
98
|
+
// Horizontal: the visible page plus one card per edge — an unaligned scroll
|
|
99
|
+
// position shows partial cards at BOTH edges, and measured_page_size floors,
|
|
100
|
+
// so up to page_size + 2 cards can intersect the viewport. Vertical tracks
|
|
101
|
+
// size their viewport to max_rendered cards (see max-block-size CSS), so
|
|
102
|
+
// there the page itself is the budget.
|
|
103
|
+
const rendered_count = $derived(
|
|
104
|
+
layout === `horizontal`
|
|
105
|
+
? Math.min(items.length, page_size + 2, max_rendered)
|
|
106
|
+
: Math.min(items.length, max_rendered),
|
|
107
|
+
)
|
|
108
|
+
const window_start = $derived(
|
|
109
|
+
Math.min(Math.max(0, items.length - rendered_count), first_visible_idx),
|
|
110
|
+
)
|
|
111
|
+
const rendered_items = $derived(
|
|
112
|
+
items.slice(window_start, window_start + rendered_count).map((item, offset) => ({
|
|
113
|
+
item,
|
|
114
|
+
idx: window_start + offset,
|
|
115
|
+
})),
|
|
116
|
+
)
|
|
117
|
+
const carousel_style = $derived(
|
|
118
|
+
[
|
|
119
|
+
`--structure-carousel-columns: ${max_rendered}`,
|
|
120
|
+
`--structure-carousel-card-width: ${card_width}px`,
|
|
121
|
+
`--structure-carousel-height: ${effective_height}px`,
|
|
122
|
+
`--structure-carousel-gap: ${gap}px`,
|
|
123
|
+
`--structure-carousel-track-width: ${track_width}px`,
|
|
124
|
+
layout === `horizontal`
|
|
125
|
+
? `inline-size: min(100%, var(--structure-carousel-track-width))`
|
|
126
|
+
: ``,
|
|
127
|
+
layout === `vertical` && resized_width ? `inline-size: ${resized_width}px` : ``,
|
|
128
|
+
resizable ? `max-inline-size: 100%` : ``,
|
|
129
|
+
resizable ? `min-block-size: ${min_resize_size}px` : ``,
|
|
130
|
+
]
|
|
131
|
+
.filter(Boolean)
|
|
132
|
+
.join(`; `),
|
|
133
|
+
)
|
|
134
|
+
const track_style = $derived(
|
|
135
|
+
layout === `horizontal`
|
|
136
|
+
? `overflow-x: auto; overflow-y: hidden; block-size: ${effective_height}px`
|
|
137
|
+
: `overflow-x: hidden; overflow-y: auto;`,
|
|
138
|
+
)
|
|
139
|
+
// Horizontal spacers/cards take their height from the track's CONTENT box
|
|
140
|
+
// (spacer min-block-size 100%, cards inset-block: 0) instead of a fixed
|
|
141
|
+
// px height: a classic (non-overlay) horizontal scrollbar shrinks that
|
|
142
|
+
// content box, and fixed-height cards would get their bottom edge — where
|
|
143
|
+
// the atom legend sits — clipped by exactly the scrollbar's height.
|
|
144
|
+
const spacer_style = $derived(
|
|
145
|
+
layout === `horizontal`
|
|
146
|
+
? `inline-size: ${total_scroll_extent}px`
|
|
147
|
+
: `block-size: ${total_scroll_extent}px; inline-size: ${card_width}px`,
|
|
148
|
+
)
|
|
149
|
+
const card_style = (idx: number): string => {
|
|
150
|
+
const [x_shift, y_shift] =
|
|
151
|
+
layout === `horizontal` ? [idx * item_stride, 0] : [0, idx * item_stride]
|
|
152
|
+
const cross_size =
|
|
153
|
+
layout === `horizontal` ? `inset-block: 0` : `block-size: ${effective_height}px`
|
|
154
|
+
return `inline-size: ${card_width}px; ${cross_size}; transform: translate3d(${x_shift}px, ${y_shift}px, 0);`
|
|
155
|
+
}
|
|
156
|
+
const structure_scene_props = { gizmo: false }
|
|
157
|
+
|
|
158
|
+
const prefetch = (): void => {
|
|
159
|
+
const now = performance.now()
|
|
160
|
+
if (
|
|
161
|
+
!on_prefetch_more ||
|
|
162
|
+
(items.length === last_prefetch_item_count &&
|
|
163
|
+
now - last_prefetch_ms < prefetch_cooldown_ms)
|
|
164
|
+
) {
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
last_prefetch_ms = now
|
|
168
|
+
last_prefetch_item_count = items.length
|
|
169
|
+
on_prefetch_more()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Cards entering the render window mid-scroll render instantly as label
|
|
173
|
+
// shells and get their WebGL canvas (tracked in live_ids) later: mounting a
|
|
174
|
+
// Threlte scene (context creation + shader compile) takes long enough that a
|
|
175
|
+
// burst of simultaneous mounts stalls fast flings — the main source of
|
|
176
|
+
// scroll jank. While scrolling, at most one card is promoted to live per
|
|
177
|
+
// promote_interval_ms so structures still fill in mid-scroll without
|
|
178
|
+
// stacking several mounts into one frame; once scrolling settles, all
|
|
179
|
+
// remaining shells mount. Cards leaving the window always lose live status
|
|
180
|
+
// (window eviction destroys their canvas regardless) so re-entering cards go
|
|
181
|
+
// through the same throttle instead of burst-remounting from stale ids.
|
|
182
|
+
const scroll_settle_ms = 150
|
|
183
|
+
const promote_interval_ms = 200
|
|
184
|
+
let is_scrolling = $state(false)
|
|
185
|
+
let settle_timer: ReturnType<typeof setTimeout> | undefined
|
|
186
|
+
let last_promote_ms = Number.NEGATIVE_INFINITY
|
|
187
|
+
const live_ids = new SvelteSet<string>()
|
|
188
|
+
$effect(() => {
|
|
189
|
+
const window_ids = new Set(rendered_items.map(({ item }) => item.id))
|
|
190
|
+
for (const id of live_ids) if (!window_ids.has(id)) live_ids.delete(id)
|
|
191
|
+
if (!is_scrolling) {
|
|
192
|
+
for (const id of window_ids) live_ids.add(id)
|
|
193
|
+
} else {
|
|
194
|
+
const now = performance.now()
|
|
195
|
+
const entering = rendered_items.find(({ item }) => !live_ids.has(item.id))
|
|
196
|
+
if (!entering || now - last_promote_ms < promote_interval_ms) return
|
|
197
|
+
last_promote_ms = now
|
|
198
|
+
live_ids.add(entering.item.id)
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
const on_scroll = (): void => {
|
|
203
|
+
if (!track) return
|
|
204
|
+
is_scrolling = true
|
|
205
|
+
clearTimeout(settle_timer)
|
|
206
|
+
settle_timer = setTimeout(() => (is_scrolling = false), scroll_settle_ms)
|
|
207
|
+
scroll_pos = layout === `horizontal` ? track.scrollLeft : track.scrollTop
|
|
208
|
+
// first_visible_idx re-derives from the scroll offset just written above
|
|
209
|
+
const remaining_items = Math.max(0, items.length - first_visible_idx - page_size)
|
|
210
|
+
// Prefetch when within two pages (or one render window) of the end.
|
|
211
|
+
if (remaining_items <= Math.max(max_rendered, page_size * 2)) prefetch()
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const on_wheel = (event: WheelEvent): void => {
|
|
215
|
+
if (!track || layout !== `horizontal` || event.ctrlKey || items.length <= page_size) return
|
|
216
|
+
const dominant_delta =
|
|
217
|
+
Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY
|
|
218
|
+
if (dominant_delta === 0) return
|
|
219
|
+
const delta_scale =
|
|
220
|
+
event.deltaMode === WheelEvent.DOM_DELTA_LINE
|
|
221
|
+
? wheel_line_height_px
|
|
222
|
+
: event.deltaMode === WheelEvent.DOM_DELTA_PAGE
|
|
223
|
+
? track.clientWidth
|
|
224
|
+
: 1
|
|
225
|
+
const delta = dominant_delta * delta_scale
|
|
226
|
+
// unclamped above when max is 0 (track not yet measured); browser clamps anyway
|
|
227
|
+
const max_scroll_left = Math.max(0, track.scrollWidth - track.clientWidth) || Infinity
|
|
228
|
+
const next_scroll_left = Math.min(max_scroll_left, Math.max(0, track.scrollLeft + delta))
|
|
229
|
+
// already at the first/last card: leave the event alone so parent scroll
|
|
230
|
+
// containers can handle it instead of swallowing a no-op
|
|
231
|
+
if (next_scroll_left === track.scrollLeft) return
|
|
232
|
+
event.preventDefault()
|
|
233
|
+
event.stopPropagation()
|
|
234
|
+
track.scrollLeft = next_scroll_left
|
|
235
|
+
on_scroll()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const scroll_page = (direction: -1 | 1): void => {
|
|
239
|
+
if (!track) return
|
|
240
|
+
const target_start = Math.min(
|
|
241
|
+
max_page_start,
|
|
242
|
+
Math.max(0, first_visible_idx + direction * page_size),
|
|
243
|
+
)
|
|
244
|
+
track.scrollLeft = target_start * item_stride
|
|
245
|
+
on_scroll()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Keyboard scrolling for the focused track: main-axis arrows move one card,
|
|
249
|
+
// PageUp/PageDown one viewport page, Home/End jump to the ends. Only keys
|
|
250
|
+
// targeting the track itself are handled — card content binds its own arrows
|
|
251
|
+
// (e.g. the info pane's site table) and must not be hijacked. Boundary no-ops
|
|
252
|
+
// fall through to the page, matching the wheel handler.
|
|
253
|
+
const on_track_keydown = (event: KeyboardEvent): void => {
|
|
254
|
+
if (!track || event.target !== track) return
|
|
255
|
+
const horizontal = layout === `horizontal`
|
|
256
|
+
const [back_key, fwd_key] = horizontal
|
|
257
|
+
? [`ArrowLeft`, `ArrowRight`]
|
|
258
|
+
: [`ArrowUp`, `ArrowDown`]
|
|
259
|
+
const max_scroll = horizontal
|
|
260
|
+
? Math.max(0, track.scrollWidth - track.clientWidth)
|
|
261
|
+
: Math.max(0, track.scrollHeight - track.clientHeight)
|
|
262
|
+
const current = horizontal ? track.scrollLeft : track.scrollTop
|
|
263
|
+
const deltas: Record<string, number> = {
|
|
264
|
+
[back_key]: -item_stride,
|
|
265
|
+
[fwd_key]: item_stride,
|
|
266
|
+
PageUp: -page_size * item_stride,
|
|
267
|
+
PageDown: page_size * item_stride,
|
|
268
|
+
Home: -current,
|
|
269
|
+
End: max_scroll - current,
|
|
270
|
+
}
|
|
271
|
+
const delta = deltas[event.key]
|
|
272
|
+
if (delta === undefined) return
|
|
273
|
+
const next_scroll = Math.min(max_scroll, Math.max(0, current + delta))
|
|
274
|
+
if (next_scroll === current) return // boundary: let the page handle it
|
|
275
|
+
event.preventDefault()
|
|
276
|
+
if (horizontal) track.scrollLeft = next_scroll
|
|
277
|
+
else track.scrollTop = next_scroll
|
|
278
|
+
on_scroll()
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const stop_resize = (): void => {
|
|
282
|
+
resize_drag = undefined
|
|
283
|
+
window.removeEventListener(`pointermove`, on_resize_move)
|
|
284
|
+
window.removeEventListener(`pointerup`, stop_resize)
|
|
285
|
+
window.removeEventListener(`pointercancel`, stop_resize)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Shared by pointer drags and keyboard resizes: clamps to the minimum size
|
|
289
|
+
// and (for width) to the parent container.
|
|
290
|
+
const set_resized_size = (axis: `height` | `width`, next_size: number): void => {
|
|
291
|
+
if (axis === `height`) {
|
|
292
|
+
resized_height = Math.max(min_resize_size, next_size)
|
|
293
|
+
} else {
|
|
294
|
+
const clamped = Math.max(min_card_width, next_size)
|
|
295
|
+
const parent_width = carousel?.parentElement?.clientWidth ?? Number.POSITIVE_INFINITY
|
|
296
|
+
resized_width = Math.min(clamped, parent_width > 0 ? parent_width : clamped)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const on_resize_move = (event: PointerEvent): void => {
|
|
301
|
+
if (!resize_drag) return
|
|
302
|
+
const position = resize_drag.axis === `height` ? event.clientY : event.clientX
|
|
303
|
+
set_resized_size(
|
|
304
|
+
resize_drag.axis,
|
|
305
|
+
resize_drag.start_size + position - resize_drag.start_position,
|
|
306
|
+
)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const resize_by = (delta: number): void => {
|
|
310
|
+
if (layout === `horizontal`) set_resized_size(`height`, effective_height + delta)
|
|
311
|
+
else set_resized_size(`width`, card_width + delta)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const on_resize_keydown = (event: KeyboardEvent): void => {
|
|
315
|
+
const [grow, shrink] =
|
|
316
|
+
layout === `horizontal` ? [`ArrowDown`, `ArrowUp`] : [`ArrowRight`, `ArrowLeft`]
|
|
317
|
+
if (event.key !== grow && event.key !== shrink) return
|
|
318
|
+
event.preventDefault()
|
|
319
|
+
resize_by(event.key === grow ? keyboard_resize_step_px : -keyboard_resize_step_px)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const start_resize = (event: PointerEvent): void => {
|
|
323
|
+
if (!resizable) return
|
|
324
|
+
event.preventDefault()
|
|
325
|
+
event.stopPropagation()
|
|
326
|
+
resize_drag =
|
|
327
|
+
layout === `horizontal`
|
|
328
|
+
? { axis: `height`, start_position: event.clientY, start_size: effective_height }
|
|
329
|
+
: { axis: `width`, start_position: event.clientX, start_size: card_width }
|
|
330
|
+
;(event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId)
|
|
331
|
+
window.addEventListener(`pointermove`, on_resize_move)
|
|
332
|
+
window.addEventListener(`pointerup`, stop_resize)
|
|
333
|
+
window.addEventListener(`pointercancel`, stop_resize)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Capture before the nested Structure canvas sees the wheel. Orbit controls
|
|
337
|
+
// otherwise consume the event, and Svelte's normal bubble listener cannot
|
|
338
|
+
// reliably turn a mouse wheel into horizontal carousel movement.
|
|
339
|
+
$effect(() => {
|
|
340
|
+
const node = track
|
|
341
|
+
if (!node || layout !== `horizontal`) return
|
|
342
|
+
node.addEventListener(`wheel`, on_wheel, { capture: true, passive: false })
|
|
343
|
+
return () => node.removeEventListener(`wheel`, on_wheel, true)
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
$effect(() => () => {
|
|
347
|
+
stop_resize()
|
|
348
|
+
clearTimeout(settle_timer)
|
|
349
|
+
})
|
|
350
|
+
</script>
|
|
351
|
+
|
|
352
|
+
<section
|
|
353
|
+
bind:this={carousel}
|
|
354
|
+
class={[`structure-carousel`, layout, resizable && `resizable`, resize_drag && `resizing`]}
|
|
355
|
+
style={carousel_style}
|
|
356
|
+
bind:clientWidth={carousel_width}
|
|
357
|
+
bind:clientHeight={carousel_height}
|
|
358
|
+
>
|
|
359
|
+
{#if items.length === 0}
|
|
360
|
+
<p class="empty-carousel">{empty_message}</p>
|
|
361
|
+
{:else}
|
|
362
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex, a11y_no_noninteractive_element_interactions
|
|
363
|
+
(focusable scroll region is a valid ARIA carousel pattern: arrows/PageUp/
|
|
364
|
+
PageDown/Home/End scroll it; see on_track_keydown) -->
|
|
365
|
+
<div
|
|
366
|
+
bind:this={track}
|
|
367
|
+
class="structure-carousel-track"
|
|
368
|
+
role="group"
|
|
369
|
+
aria-roledescription="carousel"
|
|
370
|
+
aria-label="Structure carousel"
|
|
371
|
+
tabindex="0"
|
|
372
|
+
onscroll={on_scroll}
|
|
373
|
+
onkeydown={on_track_keydown}
|
|
374
|
+
style={track_style}
|
|
375
|
+
>
|
|
376
|
+
<div class="structure-carousel-spacer" style={spacer_style}>
|
|
377
|
+
{#each rendered_items as { item, idx } (item.id)}
|
|
378
|
+
<article class="structure-card" style={card_style(idx)}>
|
|
379
|
+
<GlassChip class="card-info">
|
|
380
|
+
<strong title={item.label}>{item.label}</strong>
|
|
381
|
+
{#if item.subtitle}
|
|
382
|
+
<span>{item.subtitle}</span>
|
|
383
|
+
{/if}
|
|
384
|
+
</GlassChip>
|
|
385
|
+
{#if live_ids.has(item.id) || !is_scrolling}
|
|
386
|
+
<!-- Fill-the-card overrides for Structure's standalone defaults
|
|
387
|
+
(height 500px, min-width 300px — both larger than a card). -->
|
|
388
|
+
<Structure
|
|
389
|
+
structure={item.structure}
|
|
390
|
+
show_controls={show_controls ?? `never`}
|
|
391
|
+
scene_props={structure_scene_props}
|
|
392
|
+
allow_file_drop={false}
|
|
393
|
+
performance_mode="speed"
|
|
394
|
+
style="--struct-min-width: 0; --struct-height: 100%"
|
|
395
|
+
/>
|
|
396
|
+
{/if}
|
|
397
|
+
</article>
|
|
398
|
+
{/each}
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
{#if layout === `horizontal` && items.length > page_size}
|
|
402
|
+
<nav
|
|
403
|
+
aria-label="Structure pages"
|
|
404
|
+
class="structure-carousel-pager"
|
|
405
|
+
class:portaled={Boolean(pager_target)}
|
|
406
|
+
{@attach portal(pager_target)}
|
|
407
|
+
>
|
|
408
|
+
<button
|
|
409
|
+
aria-label="Previous structures"
|
|
410
|
+
disabled={page_start === 0}
|
|
411
|
+
onclick={() => scroll_page(-1)}
|
|
412
|
+
type="button">‹</button
|
|
413
|
+
>
|
|
414
|
+
<span aria-live="polite">{page_start + 1}–{page_end} / {items.length}</span>
|
|
415
|
+
<button
|
|
416
|
+
aria-label="Next structures"
|
|
417
|
+
disabled={page_end >= items.length}
|
|
418
|
+
onclick={() => scroll_page(1)}
|
|
419
|
+
type="button">›</button
|
|
420
|
+
>
|
|
421
|
+
</nav>
|
|
422
|
+
{/if}
|
|
423
|
+
{/if}
|
|
424
|
+
{#if resizable}
|
|
425
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions (focusable separator is a valid ARIA pattern: arrow keys resize, pointer drags) -->
|
|
426
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
427
|
+
<div
|
|
428
|
+
aria-label={layout === `horizontal` ? `Resize carousel height` : `Resize carousel width`}
|
|
429
|
+
aria-orientation={layout === `horizontal` ? `horizontal` : `vertical`}
|
|
430
|
+
aria-valuemin={layout === `horizontal` ? min_resize_size : min_card_width}
|
|
431
|
+
aria-valuemax={Math.round(
|
|
432
|
+
layout === `horizontal`
|
|
433
|
+
? Math.max(effective_height, carousel_height)
|
|
434
|
+
: Math.max(card_width, carousel_width),
|
|
435
|
+
)}
|
|
436
|
+
aria-valuenow={Math.round(layout === `horizontal` ? effective_height : card_width)}
|
|
437
|
+
class={`structure-carousel-resize-handle ${layout}`}
|
|
438
|
+
onkeydown={on_resize_keydown}
|
|
439
|
+
onpointerdown={start_resize}
|
|
440
|
+
role="separator"
|
|
441
|
+
tabindex="0"
|
|
442
|
+
title={layout === `horizontal`
|
|
443
|
+
? `Drag to resize carousel height`
|
|
444
|
+
: `Drag to resize carousel width`}
|
|
445
|
+
></div>
|
|
446
|
+
{/if}
|
|
447
|
+
</section>
|
|
448
|
+
|
|
449
|
+
<style>
|
|
450
|
+
.structure-carousel {
|
|
451
|
+
position: relative;
|
|
452
|
+
min-inline-size: 0;
|
|
453
|
+
overflow: hidden;
|
|
454
|
+
}
|
|
455
|
+
.structure-carousel.horizontal {
|
|
456
|
+
block-size: var(--structure-carousel-height);
|
|
457
|
+
}
|
|
458
|
+
/* reserve a lane for the resize handle below (horizontal) / beside
|
|
459
|
+
(vertical) the cards so the grip never overlaps the structure canvases */
|
|
460
|
+
.structure-carousel.horizontal.resizable {
|
|
461
|
+
block-size: calc(var(--structure-carousel-height) + 8px);
|
|
462
|
+
}
|
|
463
|
+
.structure-carousel.vertical.resizable {
|
|
464
|
+
padding-inline-end: 10px;
|
|
465
|
+
}
|
|
466
|
+
.structure-carousel-track {
|
|
467
|
+
position: relative;
|
|
468
|
+
min-inline-size: 0;
|
|
469
|
+
scrollbar-width: thin;
|
|
470
|
+
overscroll-behavior: contain;
|
|
471
|
+
}
|
|
472
|
+
/* inset ring so it isn't clipped by the carousel's overflow: hidden */
|
|
473
|
+
.structure-carousel-track:focus-visible {
|
|
474
|
+
outline: 2px solid var(--accent-color, Highlight);
|
|
475
|
+
outline-offset: -2px;
|
|
476
|
+
}
|
|
477
|
+
.horizontal .structure-carousel-track {
|
|
478
|
+
inline-size: min(100%, var(--structure-carousel-track-width));
|
|
479
|
+
}
|
|
480
|
+
.vertical .structure-carousel-track {
|
|
481
|
+
max-block-size: calc(var(--structure-carousel-height) * var(--structure-carousel-columns));
|
|
482
|
+
}
|
|
483
|
+
.structure-carousel-spacer {
|
|
484
|
+
position: relative;
|
|
485
|
+
min-block-size: 100%;
|
|
486
|
+
}
|
|
487
|
+
.structure-card {
|
|
488
|
+
position: absolute;
|
|
489
|
+
inset-block-start: 0;
|
|
490
|
+
inset-inline-start: 0;
|
|
491
|
+
min-inline-size: 0;
|
|
492
|
+
overflow: hidden;
|
|
493
|
+
border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
|
|
494
|
+
border-radius: 6px;
|
|
495
|
+
background: var(--structure-carousel-card-bg, light-dark(#e9edf2, #343941));
|
|
496
|
+
contain: layout paint style;
|
|
497
|
+
}
|
|
498
|
+
/* element color chips stay visible at all times; the legend's extra chrome
|
|
499
|
+
is already hover-gated elsewhere (mode chevron via Structure's
|
|
500
|
+
viewer_active, cell-select via .structure:hover, chip × toggles via
|
|
501
|
+
.legend-item:hover) */
|
|
502
|
+
.structure-card :global(.atom-legend) {
|
|
503
|
+
z-index: 4;
|
|
504
|
+
max-inline-size: calc(100% - 8px);
|
|
505
|
+
justify-content: flex-end;
|
|
506
|
+
overflow: visible;
|
|
507
|
+
}
|
|
508
|
+
.structure-card :global(.element-legend sub) {
|
|
509
|
+
display: none;
|
|
510
|
+
}
|
|
511
|
+
/* frosted label/subtitle chip, same look as StructurePopup's stats block */
|
|
512
|
+
.structure-card :global(.card-info) {
|
|
513
|
+
--glass-chip-top: 4px;
|
|
514
|
+
--glass-chip-left: 4px;
|
|
515
|
+
--glass-chip-max-width: calc(100% - 8px);
|
|
516
|
+
--glass-chip-font-size: clamp(9px, calc(var(--structure-carousel-height) * 0.062), 12px);
|
|
517
|
+
line-height: 1.25;
|
|
518
|
+
pointer-events: none;
|
|
519
|
+
}
|
|
520
|
+
.structure-card :global(.card-info strong),
|
|
521
|
+
.structure-card :global(.card-info span) {
|
|
522
|
+
display: block;
|
|
523
|
+
overflow: hidden;
|
|
524
|
+
text-overflow: ellipsis;
|
|
525
|
+
white-space: nowrap;
|
|
526
|
+
}
|
|
527
|
+
.structure-card :global(.card-info span) {
|
|
528
|
+
color: light-dark(#5b6572, #b8c0cc);
|
|
529
|
+
font-size: 0.92em;
|
|
530
|
+
}
|
|
531
|
+
.structure-carousel-pager {
|
|
532
|
+
position: absolute;
|
|
533
|
+
z-index: 6;
|
|
534
|
+
/* own compositing layer, or WKWebView paints the canvas over this (see app.css) */
|
|
535
|
+
will-change: transform;
|
|
536
|
+
inset-block-end: 12px;
|
|
537
|
+
inset-inline-start: 50%;
|
|
538
|
+
display: flex;
|
|
539
|
+
align-items: center;
|
|
540
|
+
gap: 4px;
|
|
541
|
+
padding: 3px 5px;
|
|
542
|
+
border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
|
|
543
|
+
border-radius: 999px;
|
|
544
|
+
background: color-mix(in srgb, light-dark(#f4f6f9, #1f232b) 88%, transparent);
|
|
545
|
+
box-shadow: 0 3px 12px color-mix(in srgb, black 20%, transparent);
|
|
546
|
+
color: light-dark(#404854, #d5dbe4);
|
|
547
|
+
font-size: 10px;
|
|
548
|
+
font-variant-numeric: tabular-nums;
|
|
549
|
+
transform: translateX(-50%);
|
|
550
|
+
}
|
|
551
|
+
/* hosted in a panel title bar instead of floating over the cards */
|
|
552
|
+
.structure-carousel-pager.portaled {
|
|
553
|
+
position: static;
|
|
554
|
+
gap: 1px;
|
|
555
|
+
padding: 0 2px;
|
|
556
|
+
background: transparent;
|
|
557
|
+
box-shadow: none;
|
|
558
|
+
transform: none;
|
|
559
|
+
}
|
|
560
|
+
.structure-carousel-pager.portaled button {
|
|
561
|
+
inline-size: 18px;
|
|
562
|
+
block-size: 18px;
|
|
563
|
+
}
|
|
564
|
+
.structure-carousel-pager button {
|
|
565
|
+
display: grid;
|
|
566
|
+
place-items: center;
|
|
567
|
+
inline-size: 22px;
|
|
568
|
+
block-size: 22px;
|
|
569
|
+
padding: 0 0 2px;
|
|
570
|
+
border: 0;
|
|
571
|
+
border-radius: 50%;
|
|
572
|
+
background: transparent;
|
|
573
|
+
color: inherit;
|
|
574
|
+
cursor: pointer;
|
|
575
|
+
font: inherit;
|
|
576
|
+
font-size: 16px;
|
|
577
|
+
line-height: 1;
|
|
578
|
+
}
|
|
579
|
+
.structure-carousel-pager button:hover:not(:disabled) {
|
|
580
|
+
color: var(--active-color, #6ea8ff);
|
|
581
|
+
}
|
|
582
|
+
.structure-carousel-pager button:disabled {
|
|
583
|
+
opacity: 0.3;
|
|
584
|
+
cursor: default;
|
|
585
|
+
}
|
|
586
|
+
.structure-carousel-resize-handle {
|
|
587
|
+
position: absolute;
|
|
588
|
+
z-index: 5;
|
|
589
|
+
background: transparent;
|
|
590
|
+
touch-action: none;
|
|
591
|
+
}
|
|
592
|
+
.structure-carousel-resize-handle::before {
|
|
593
|
+
position: absolute;
|
|
594
|
+
border-radius: 999px;
|
|
595
|
+
background: color-mix(in srgb, currentColor 32%, transparent);
|
|
596
|
+
content: '';
|
|
597
|
+
/* grip only shows while the carousel is hovered, focused, or resizing */
|
|
598
|
+
opacity: 0;
|
|
599
|
+
transition: opacity 0.15s ease;
|
|
600
|
+
}
|
|
601
|
+
.structure-carousel:hover .structure-carousel-resize-handle::before,
|
|
602
|
+
.structure-carousel-resize-handle:focus-visible::before,
|
|
603
|
+
.structure-carousel.resizing .structure-carousel-resize-handle::before {
|
|
604
|
+
opacity: 1;
|
|
605
|
+
}
|
|
606
|
+
.structure-carousel-resize-handle:hover::before,
|
|
607
|
+
.structure-carousel.resizing .structure-carousel-resize-handle::before {
|
|
608
|
+
background: color-mix(in srgb, var(--active-color, #6ea8ff) 75%, white 10%);
|
|
609
|
+
}
|
|
610
|
+
.structure-carousel-resize-handle.horizontal {
|
|
611
|
+
inset-block-end: 0;
|
|
612
|
+
inset-inline: 0;
|
|
613
|
+
block-size: 8px;
|
|
614
|
+
cursor: ns-resize;
|
|
615
|
+
}
|
|
616
|
+
.structure-carousel-resize-handle.horizontal::before {
|
|
617
|
+
inset-block-end: 2px;
|
|
618
|
+
inset-inline: 42%;
|
|
619
|
+
block-size: 2px;
|
|
620
|
+
}
|
|
621
|
+
.structure-carousel-resize-handle.vertical {
|
|
622
|
+
inset-block: 0;
|
|
623
|
+
inset-inline-end: 0;
|
|
624
|
+
inline-size: 10px;
|
|
625
|
+
cursor: ew-resize;
|
|
626
|
+
}
|
|
627
|
+
.structure-carousel-resize-handle.vertical::before {
|
|
628
|
+
inset-block: 42%;
|
|
629
|
+
inset-inline-end: 3px;
|
|
630
|
+
inline-size: 2px;
|
|
631
|
+
}
|
|
632
|
+
.empty-carousel {
|
|
633
|
+
margin: 0;
|
|
634
|
+
padding: 16px;
|
|
635
|
+
color: light-dark(#6b7482, #aeb6c2);
|
|
636
|
+
}
|
|
637
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ShowControlsProp } from '../controls';
|
|
2
|
+
import type { StructureCarouselItem } from './';
|
|
3
|
+
type Layout = `horizontal` | `vertical`;
|
|
4
|
+
interface Props {
|
|
5
|
+
items: StructureCarouselItem[];
|
|
6
|
+
layout?: Layout;
|
|
7
|
+
height?: number;
|
|
8
|
+
min_card_width?: number;
|
|
9
|
+
max_rendered_items?: number;
|
|
10
|
+
resizable?: boolean;
|
|
11
|
+
show_controls?: ShowControlsProp;
|
|
12
|
+
empty_message?: string;
|
|
13
|
+
on_prefetch_more?: () => void;
|
|
14
|
+
prefetch_cooldown_ms?: number;
|
|
15
|
+
pager_target?: HTMLElement | null;
|
|
16
|
+
}
|
|
17
|
+
declare const StructureCarousel: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type StructureCarousel = ReturnType<typeof StructureCarousel>;
|
|
19
|
+
export default StructureCarousel;
|