matterviz 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brillouin/BrillouinZone.svelte +68 -145
- package/dist/brillouin/BrillouinZone.svelte.d.ts +5 -14
- package/dist/brillouin/BrillouinZoneExportPane.svelte +43 -96
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +9 -32
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +2 -3
- package/dist/brillouin/BrillouinZoneScene.svelte +49 -203
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +3 -23
- package/dist/brillouin/ReciprocalVectors.svelte +39 -0
- package/dist/brillouin/ReciprocalVectors.svelte.d.ts +9 -0
- package/dist/brillouin/compute.d.ts +2 -0
- package/dist/brillouin/compute.js +80 -77
- package/dist/brillouin/geometry.d.ts +8 -0
- package/dist/brillouin/geometry.js +57 -0
- package/dist/brillouin/index.d.ts +2 -0
- package/dist/brillouin/index.js +2 -0
- package/dist/brillouin/types.d.ts +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +100 -191
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +4 -1
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +176 -464
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +7 -1
- package/dist/chempot-diagram/color.d.ts +3 -6
- package/dist/chempot-diagram/color.js +5 -5
- package/dist/chempot-diagram/compute.d.ts +3 -3
- package/dist/chempot-diagram/compute.js +3 -1
- package/dist/chempot-diagram/controls-state.svelte.d.ts +10 -0
- package/dist/chempot-diagram/controls-state.svelte.js +42 -0
- package/dist/chempot-diagram/export.d.ts +47 -0
- package/dist/chempot-diagram/export.js +133 -0
- package/dist/chempot-diagram/index.d.ts +1 -0
- package/dist/chempot-diagram/index.js +1 -0
- package/dist/chempot-diagram/pointer.d.ts +0 -10
- package/dist/chempot-diagram/pointer.js +4 -4
- package/dist/chempot-diagram/types.d.ts +3 -3
- package/dist/colors/index.js +2 -2
- package/dist/composition/FormulaFilter.svelte +6 -5
- package/dist/composition/PieChart.svelte +5 -5
- package/dist/composition/chem-sys.js +3 -2
- package/dist/composition/format.js +3 -2
- package/dist/composition/parse.d.ts +0 -1
- package/dist/composition/parse.js +17 -19
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +0 -1
- package/dist/convex-hull/ConvexHull.svelte +8 -10
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -4
- package/dist/convex-hull/ConvexHull2D.svelte +94 -175
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +176 -680
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +180 -680
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullChrome.svelte +268 -0
- package/dist/convex-hull/ConvexHullChrome.svelte.d.ts +30 -0
- package/dist/convex-hull/ConvexHullControls.svelte +88 -7
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +7 -6
- package/dist/convex-hull/ConvexHullInfoPane.svelte +18 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +6 -5
- package/dist/convex-hull/ConvexHullStats.svelte +29 -168
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +3 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +11 -2
- package/dist/convex-hull/ConvexHullTooltip.svelte.d.ts +2 -1
- package/dist/convex-hull/barycentric-coords.d.ts +2 -4
- package/dist/convex-hull/barycentric-coords.js +6 -33
- package/dist/convex-hull/canvas-interactions.svelte.d.ts +79 -0
- package/dist/convex-hull/canvas-interactions.svelte.js +278 -0
- package/dist/convex-hull/helpers.d.ts +39 -7
- package/dist/convex-hull/helpers.js +154 -69
- package/dist/convex-hull/hull-state.svelte.d.ts +44 -0
- package/dist/convex-hull/hull-state.svelte.js +124 -0
- package/dist/convex-hull/index.d.ts +9 -7
- package/dist/convex-hull/index.js +7 -2
- package/dist/convex-hull/thermodynamics.js +91 -920
- package/dist/convex-hull/types.d.ts +12 -4
- package/dist/convex-hull/types.js +12 -0
- package/dist/coordination/CoordinationBarPlot.svelte +4 -11
- package/dist/element/BohrAtom.svelte +2 -1
- package/dist/element/ElementTile.svelte.d.ts +1 -1
- package/dist/element/index.d.ts +4 -0
- package/dist/element/index.js +18 -0
- package/dist/feedback/DragOverlay.svelte +3 -1
- package/dist/feedback/DragOverlay.svelte.d.ts +1 -0
- package/dist/feedback/StatusMessage.svelte +13 -3
- package/dist/fermi-surface/FermiSurface.svelte +67 -146
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +5 -14
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +72 -224
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +3 -23
- package/dist/fermi-surface/compute.js +11 -10
- package/dist/fermi-surface/export.js +4 -15
- package/dist/fermi-surface/index.d.ts +0 -1
- package/dist/fermi-surface/index.js +0 -1
- package/dist/fermi-surface/parse.d.ts +1 -1
- package/dist/fermi-surface/parse.js +64 -75
- package/dist/fermi-surface/types.d.ts +2 -2
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +55 -40
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +4 -3
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +3 -2
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +5 -5
- package/dist/heatmap-matrix/index.d.ts +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/io/ExportPane.svelte +166 -0
- package/dist/io/ExportPane.svelte.d.ts +17 -0
- package/dist/io/decompress.js +1 -2
- package/dist/io/export.d.ts +5 -1
- package/dist/io/export.js +32 -28
- package/dist/io/fetch.d.ts +2 -1
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +13 -0
- package/dist/io/index.d.ts +2 -0
- package/dist/io/index.js +10 -0
- package/dist/io/types.d.ts +13 -0
- package/dist/isosurface/parse.js +46 -44
- package/dist/labels.js +1 -1
- package/dist/layout/FullscreenButton.svelte +33 -0
- package/dist/layout/FullscreenButton.svelte.d.ts +10 -0
- package/dist/layout/FullscreenToggle.svelte +8 -14
- package/dist/layout/ViewerChrome.svelte +116 -0
- package/dist/layout/ViewerChrome.svelte.d.ts +17 -0
- package/dist/layout/fullscreen.d.ts +4 -0
- package/dist/layout/fullscreen.svelte.d.ts +8 -0
- package/dist/layout/fullscreen.svelte.js +37 -0
- package/dist/layout/index.d.ts +3 -0
- package/dist/layout/index.js +3 -0
- package/dist/math.d.ts +7 -3
- package/dist/math.js +18 -21
- package/dist/overlays/index.d.ts +4 -0
- package/dist/periodic-table/PeriodicTable.svelte +9 -8
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +3 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +4 -3
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +2 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +2 -3
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +47 -132
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +3 -4
- package/dist/phase-diagram/colors.js +1 -1
- package/dist/phase-diagram/parse.d.ts +2 -1
- package/dist/plot/bar/BarPlot.svelte +79 -316
- package/dist/plot/bar/BarPlot.svelte.d.ts +7 -15
- package/dist/plot/bar/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/bar/SpacegroupBarPlot.svelte +2 -1
- package/dist/plot/box/BoxPlot.svelte +76 -246
- package/dist/plot/box/BoxPlot.svelte.d.ts +4 -3
- package/dist/plot/box/BoxPlotControls.svelte.d.ts +1 -1
- package/dist/plot/box/Violin.svelte.d.ts +1 -1
- package/dist/plot/box/box-plot.d.ts +3 -2
- package/dist/plot/box/box-plot.js +5 -2
- package/dist/plot/box/kde.d.ts +2 -1
- package/dist/plot/box/kde.js +4 -4
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +4 -1
- package/dist/plot/core/components/ColorBar.svelte +5 -5
- package/dist/plot/core/components/ColorBar.svelte.d.ts +5 -4
- package/dist/plot/core/components/Line.svelte +3 -2
- package/dist/plot/core/components/Line.svelte.d.ts +3 -2
- package/dist/plot/core/components/PlotAxis.svelte +2 -1
- package/dist/plot/core/components/PlotAxis.svelte.d.ts +2 -1
- package/dist/plot/core/components/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/core/components/ReferenceLine3D.svelte +2 -2
- package/dist/plot/core/components/ReferenceLine3D.svelte.d.ts +4 -4
- package/dist/plot/core/components/ReferencePlane.svelte +2 -2
- package/dist/plot/core/components/ReferencePlane.svelte.d.ts +4 -4
- package/dist/plot/core/data-cleaning.js +18 -18
- package/dist/plot/core/fill-utils.d.ts +4 -3
- package/dist/plot/core/fill-utils.js +6 -3
- package/dist/plot/core/interactions.d.ts +5 -1
- package/dist/plot/core/interactions.js +14 -0
- package/dist/plot/core/pan-zoom.svelte.d.ts +35 -0
- package/dist/plot/core/pan-zoom.svelte.js +221 -0
- package/dist/plot/core/placed-tween.svelte.d.ts +21 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -0
- package/dist/plot/core/reference-line.d.ts +10 -10
- package/dist/plot/core/reference-line.js +6 -6
- package/dist/plot/core/scales.d.ts +17 -25
- package/dist/plot/core/scales.js +10 -8
- package/dist/plot/core/svg.d.ts +2 -1
- package/dist/plot/core/types.d.ts +18 -7
- package/dist/plot/core/utils/label-placement.d.ts +1 -1
- package/dist/plot/core/utils/label-placement.js +3 -3
- package/dist/plot/core/utils.d.ts +2 -1
- package/dist/plot/histogram/Histogram.svelte +77 -314
- package/dist/plot/histogram/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/sankey/Sankey.svelte +2 -5
- package/dist/plot/sankey/Sankey.svelte.d.ts +1 -1
- package/dist/plot/sankey/sankey.js +3 -1
- package/dist/plot/scatter/BinnedScatterPlot.svelte +3 -5
- package/dist/plot/scatter/BinnedScatterPlot.svelte.d.ts +4 -4
- package/dist/plot/scatter/ScatterPlot.svelte +160 -450
- package/dist/plot/scatter/ScatterPlot.svelte.d.ts +7 -15
- package/dist/plot/scatter/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/scatter/binned-scatter-types.d.ts +4 -11
- package/dist/plot/scatter/index.d.ts +1 -1
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte +15 -26
- package/dist/plot/scatter-3d/ScatterPlot3D.svelte.d.ts +6 -14
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte +9 -10
- package/dist/plot/scatter-3d/ScatterPlot3DControls.svelte.d.ts +5 -5
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte +122 -121
- package/dist/plot/scatter-3d/ScatterPlot3DScene.svelte.d.ts +5 -14
- package/dist/plot/scatter-3d/Surface3D.svelte +6 -5
- package/dist/plot/scatter-3d/Surface3D.svelte.d.ts +4 -3
- package/dist/plot/sunburst/Sunburst.svelte +16 -20
- package/dist/plot/sunburst/Sunburst.svelte.d.ts +4 -3
- package/dist/plot/sunburst/SunburstControls.svelte.d.ts +1 -1
- package/dist/plot/sunburst/sunburst.js +4 -1
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/sanitize.js +13 -2
- package/dist/scene/SceneCamera.svelte +62 -0
- package/dist/scene/SceneCamera.svelte.d.ts +19 -0
- package/dist/scene/bind-renderer.svelte.d.ts +2 -0
- package/dist/scene/bind-renderer.svelte.js +14 -0
- package/dist/scene/index.d.ts +4 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/props.js +52 -0
- package/dist/scene/types.d.ts +26 -0
- package/dist/scene/types.js +1 -0
- package/dist/settings.d.ts +14 -2
- package/dist/settings.js +59 -1
- package/dist/spectral/Bands.svelte +8 -7
- package/dist/spectral/Bands.svelte.d.ts +3 -2
- package/dist/spectral/BandsAndDos.svelte +22 -24
- package/dist/spectral/BrillouinBandsDos.svelte +3 -3
- package/dist/spectral/Dos.svelte +5 -4
- package/dist/spectral/Dos.svelte.d.ts +2 -1
- package/dist/spectral/helpers.d.ts +6 -6
- package/dist/spectral/helpers.js +43 -37
- package/dist/state.svelte.d.ts +0 -7
- package/dist/state.svelte.js +0 -6
- package/dist/structure/Arrow.svelte +2 -4
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CanvasTooltip.svelte +1 -0
- package/dist/structure/CellSelect.svelte +11 -3
- package/dist/structure/CellSelect.svelte.d.ts +2 -1
- package/dist/structure/Lattice.svelte +2 -2
- package/dist/structure/Structure.svelte +291 -355
- package/dist/structure/Structure.svelte.d.ts +5 -15
- package/dist/structure/StructureControls.svelte +217 -2
- package/dist/structure/StructureControls.svelte.d.ts +5 -3
- package/dist/structure/StructureExportPane.svelte +54 -156
- package/dist/structure/StructureExportPane.svelte.d.ts +4 -5
- package/dist/structure/StructureInfoPane.svelte +5 -3
- package/dist/structure/StructureInfoPane.svelte.d.ts +5 -5
- package/dist/structure/StructureScene.svelte +365 -198
- package/dist/structure/StructureScene.svelte.d.ts +22 -20
- package/dist/structure/{label-placement.d.ts → atom-label-placement.d.ts} +3 -3
- package/dist/structure/{label-placement.js → atom-label-placement.js} +12 -2
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +11 -16
- package/dist/structure/bond-order-perception.js +2 -4
- package/dist/structure/bonding.d.ts +3 -0
- package/dist/structure/bonding.js +91 -48
- package/dist/structure/export.d.ts +24 -4
- package/dist/structure/export.js +64 -122
- package/dist/structure/index.d.ts +2 -0
- package/dist/structure/index.js +2 -0
- package/dist/structure/parse.d.ts +3 -2
- package/dist/structure/parse.js +333 -370
- package/dist/structure/partial-occupancy.d.ts +0 -1
- package/dist/structure/partial-occupancy.js +1 -1
- package/dist/structure/pbc.d.ts +1 -1
- package/dist/structure/pbc.js +186 -13
- package/dist/structure/polyhedra.d.ts +41 -0
- package/dist/structure/polyhedra.js +602 -0
- package/dist/structure/site.d.ts +4 -0
- package/dist/structure/site.js +1 -0
- package/dist/structure/supercell.js +3 -2
- package/dist/structure/validation.js +5 -6
- package/dist/symmetry/SymmetryElementControls.svelte +69 -0
- package/dist/symmetry/SymmetryElementControls.svelte.d.ts +9 -0
- package/dist/symmetry/SymmetryElements.svelte +354 -0
- package/dist/symmetry/SymmetryElements.svelte.d.ts +24 -0
- package/dist/symmetry/SymmetryStats.svelte +111 -6
- package/dist/symmetry/WyckoffTable.svelte +68 -7
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -0
- package/dist/symmetry/cell-transform.js +7 -14
- package/dist/symmetry/index.d.ts +14 -4
- package/dist/symmetry/index.js +301 -80
- package/dist/symmetry/spacegroups.d.ts +5 -1
- package/dist/symmetry/spacegroups.js +15 -1
- package/dist/symmetry/symmetry-elements.d.ts +33 -0
- package/dist/symmetry/symmetry-elements.js +521 -0
- package/dist/symmetry/wyckoff-db.d.ts +9 -0
- package/dist/symmetry/wyckoff-db.js +87 -0
- package/dist/table/HeatmapTable.svelte +4 -15
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/trajectory/Trajectory.svelte +58 -61
- package/dist/trajectory/Trajectory.svelte.d.ts +10 -22
- package/dist/trajectory/TrajectoryExportPane.svelte +15 -24
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +4 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +3 -2
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -2
- package/dist/trajectory/constants.js +6 -2
- package/dist/trajectory/extract.js +17 -37
- package/dist/trajectory/format-detect.d.ts +0 -1
- package/dist/trajectory/format-detect.js +3 -9
- package/dist/trajectory/frame-reader.d.ts +0 -1
- package/dist/trajectory/frame-reader.js +62 -128
- package/dist/trajectory/helpers.d.ts +10 -2
- package/dist/trajectory/helpers.js +56 -36
- package/dist/trajectory/parse/ase.d.ts +9 -1
- package/dist/trajectory/parse/ase.js +47 -32
- package/dist/trajectory/parse/diagnostics.d.ts +3 -0
- package/dist/trajectory/parse/diagnostics.js +14 -0
- package/dist/trajectory/parse/index.d.ts +1 -1
- package/dist/trajectory/parse/index.js +54 -102
- package/dist/trajectory/parse/lammps.d.ts +0 -2
- package/dist/trajectory/parse/lammps.js +8 -6
- package/dist/trajectory/parse/pymatgen.d.ts +2 -0
- package/dist/trajectory/parse/pymatgen.js +74 -0
- package/dist/trajectory/parse/vasp.js +4 -3
- package/dist/trajectory/parse/xyz.d.ts +9 -21
- package/dist/trajectory/parse/xyz.js +28 -33
- package/dist/trajectory/plotting.d.ts +0 -1
- package/dist/trajectory/plotting.js +3 -100
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +1 -1
- package/dist/xrd/XrdPlot.svelte +14 -29
- package/dist/xrd/broadening.d.ts +2 -1
- package/dist/xrd/calc-xrd.js +6 -11
- package/dist/xrd/index.d.ts +2 -2
- package/package.json +29 -16
- package/dist/element/data.json +0 -11864
- package/dist/fermi-surface/marching-cubes.d.ts +0 -2
- package/dist/fermi-surface/marching-cubes.js +0 -2
- package/dist/plot/core/hover-lock.svelte.d.ts +0 -14
- package/dist/plot/core/hover-lock.svelte.js +0 -45
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Vec2 } from '../../../math';
|
|
1
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
3
|
import type { AxisOption, ColorBarDataLoaderFn, ColorScaleOption, Orientation, ScaleType } from '../types';
|
|
3
4
|
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
@@ -9,19 +10,19 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
9
10
|
wrapper_style?: string;
|
|
10
11
|
tick_labels?: (string | number)[] | number;
|
|
11
12
|
tick_format?: string;
|
|
12
|
-
range?:
|
|
13
|
+
range?: Vec2;
|
|
13
14
|
tick_side?: `primary` | `secondary` | `inside`;
|
|
14
15
|
orientation?: Orientation;
|
|
15
16
|
snap_ticks?: boolean;
|
|
16
17
|
steps?: number;
|
|
17
|
-
nice_range?:
|
|
18
|
+
nice_range?: Vec2;
|
|
18
19
|
scale_type?: ScaleType;
|
|
19
20
|
color_scale_fn?: (value: number) => string;
|
|
20
|
-
color_scale_domain?:
|
|
21
|
+
color_scale_domain?: Vec2;
|
|
21
22
|
property_options?: AxisOption[];
|
|
22
23
|
selected_property_key?: string;
|
|
23
24
|
data_loader?: ColorBarDataLoaderFn;
|
|
24
|
-
on_property_change?: (key: string, range:
|
|
25
|
+
on_property_change?: (key: string, range: Vec2) => void;
|
|
25
26
|
color_scale_options?: ColorScaleOption[];
|
|
26
27
|
selected_color_scale_key?: string;
|
|
27
28
|
on_color_scale_change?: (key: string) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { Vec2 } from '../../../math'
|
|
2
3
|
import { DEFAULTS } from '../../../settings'
|
|
3
4
|
import { extent, min } from 'd3-array'
|
|
4
5
|
import { interpolatePath } from 'd3-interpolate-path'
|
|
@@ -19,8 +20,8 @@
|
|
|
19
20
|
line_dash = DEFAULTS.scatter.line.dash,
|
|
20
21
|
...rest
|
|
21
22
|
}: Omit<SVGAttributes<SVGPathElement>, `origin` | `points`> & {
|
|
22
|
-
points: readonly [
|
|
23
|
-
origin:
|
|
23
|
+
points: readonly Vec2[]
|
|
24
|
+
origin: Vec2
|
|
24
25
|
line_color?: string
|
|
25
26
|
line_width?: number
|
|
26
27
|
area_color?: string
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { Vec2 } from '../../../math';
|
|
1
2
|
import type { SVGAttributes } from 'svelte/elements';
|
|
2
3
|
import { type TweenOptions } from 'svelte/motion';
|
|
3
4
|
type $$ComponentProps = Omit<SVGAttributes<SVGPathElement>, `origin` | `points`> & {
|
|
4
|
-
points: readonly [
|
|
5
|
-
origin:
|
|
5
|
+
points: readonly Vec2[];
|
|
6
|
+
origin: Vec2;
|
|
6
7
|
line_color?: string;
|
|
7
8
|
line_width?: number;
|
|
8
9
|
area_color?: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { format_value } from '../../../labels'
|
|
3
|
+
import type { Vec2 } from '../../../math'
|
|
3
4
|
import AxisLabel from './AxisLabel.svelte'
|
|
4
5
|
import type { Sides } from '../layout'
|
|
5
6
|
import type { AxisConfig } from '../types'
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
show_baseline?: boolean // axis spine line (ScatterPlot omits it)
|
|
41
42
|
tick_label?: (tick: number) => string | null | undefined // custom/categorical label
|
|
42
43
|
tick_color?: (tick: number) => string | undefined // per-tick label color (else axis.color)
|
|
43
|
-
domain?:
|
|
44
|
+
domain?: Vec2 // when set, cull off-plot ticks and hide out-of-domain labels
|
|
44
45
|
unit_on_first_tick?: boolean // append axis.unit after the first tick label (ScatterPlot)
|
|
45
46
|
label_x?: number
|
|
46
47
|
label_y?: number
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Vec2 } from '../../../math';
|
|
1
2
|
import type { Sides } from '../layout';
|
|
2
3
|
import type { AxisConfig } from '../types';
|
|
3
4
|
type Side = `x` | `x2` | `y` | `y2`;
|
|
@@ -13,7 +14,7 @@ type $$ComponentProps = {
|
|
|
13
14
|
show_baseline?: boolean;
|
|
14
15
|
tick_label?: (tick: number) => string | null | undefined;
|
|
15
16
|
tick_color?: (tick: number) => string | undefined;
|
|
16
|
-
domain?:
|
|
17
|
+
domain?: Vec2;
|
|
17
18
|
unit_on_first_tick?: boolean;
|
|
18
19
|
label_x?: number;
|
|
19
20
|
label_y?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { PlotControlsProps } from '../types';
|
|
2
|
-
declare const PlotControls: import("svelte").Component<PlotControlsProps, {}, "display" | "show_controls" | "
|
|
2
|
+
declare const PlotControls: import("svelte").Component<PlotControlsProps, {}, "display" | "show_controls" | "x2_axis" | "y_axis" | "y2_axis" | "controls_open" | "x_axis">;
|
|
3
3
|
type PlotControls = ReturnType<typeof PlotControls>;
|
|
4
4
|
export default PlotControls;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
// ReferenceLine3D: 3D reference lines for axis-parallel, segments, and extended lines
|
|
3
3
|
// Uses Line2 for proper variable-width lines (WebGL ignores linewidth on basic lines)
|
|
4
|
-
import type { Point3D, Vec3 } from '../../../math'
|
|
4
|
+
import type { Point3D, Vec2, Vec3 } from '../../../math'
|
|
5
5
|
import { T, useThrelte } from '@threlte/core'
|
|
6
6
|
import * as THREE from 'three'
|
|
7
7
|
import { Line2 } from 'three/examples/jsm/lines/Line2.js'
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
let { ref_line, scene_size = [10, 10, 5], ranges }: {
|
|
14
14
|
ref_line: RefLine3D
|
|
15
15
|
scene_size?: Vec3
|
|
16
|
-
ranges: { x:
|
|
16
|
+
ranges: { x: Vec2; y: Vec2; z: Vec2 }
|
|
17
17
|
} = $props()
|
|
18
18
|
|
|
19
19
|
const { size } = useThrelte()
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { Vec3 } from '../../../math';
|
|
1
|
+
import type { Vec2, Vec3 } from '../../../math';
|
|
2
2
|
import type { RefLine3D } from '../types';
|
|
3
3
|
type $$ComponentProps = {
|
|
4
4
|
ref_line: RefLine3D;
|
|
5
5
|
scene_size?: Vec3;
|
|
6
6
|
ranges: {
|
|
7
|
-
x:
|
|
8
|
-
y:
|
|
9
|
-
z:
|
|
7
|
+
x: Vec2;
|
|
8
|
+
y: Vec2;
|
|
9
|
+
z: Vec2;
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
12
|
declare const ReferenceLine3D: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
// ReferencePlane: 3D reference planes (axis-aligned, normal-defined, or point-defined)
|
|
3
|
-
import type { Vec3 } from '../../../math'
|
|
3
|
+
import type { Vec2, Vec3 } from '../../../math'
|
|
4
4
|
import { cross_3d, normalize_vec } from '../../../math'
|
|
5
5
|
import { T } from '@threlte/core'
|
|
6
6
|
import * as THREE from 'three'
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
let { ref_plane, scene_size = [10, 10, 5], ranges }: {
|
|
11
11
|
ref_plane: RefPlane
|
|
12
12
|
scene_size?: Vec3
|
|
13
|
-
ranges: { x:
|
|
13
|
+
ranges: { x: Vec2; y: Vec2; z: Vec2 }
|
|
14
14
|
} = $props()
|
|
15
15
|
|
|
16
16
|
let [scene_x, scene_y, scene_z] = $derived(scene_size)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { Vec3 } from '../../../math';
|
|
1
|
+
import type { Vec2, Vec3 } from '../../../math';
|
|
2
2
|
import type { RefPlane } from '../types';
|
|
3
3
|
type $$ComponentProps = {
|
|
4
4
|
ref_plane: RefPlane;
|
|
5
5
|
scene_size?: Vec3;
|
|
6
6
|
ranges: {
|
|
7
|
-
x:
|
|
8
|
-
y:
|
|
9
|
-
z:
|
|
7
|
+
x: Vec2;
|
|
8
|
+
y: Vec2;
|
|
9
|
+
z: Vec2;
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
12
|
declare const ReferencePlane: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -274,7 +274,7 @@ export function smooth_savitzky_golay(values, window, polynomial_order = DEFAULT
|
|
|
274
274
|
const half = Math.floor(actual_window / 2);
|
|
275
275
|
const result = Array(values.length);
|
|
276
276
|
// Cache coefficient sum to avoid O(n × window) redundant reductions in loop
|
|
277
|
-
const coeffs_sum = coeffs.reduce((
|
|
277
|
+
const coeffs_sum = coeffs.reduce((sum, coeff) => sum + coeff, 0);
|
|
278
278
|
for (let idx = 0; idx < values.length; idx++) {
|
|
279
279
|
let [sum, weight_sum] = [0, 0];
|
|
280
280
|
for (let jdx = 0; jdx < actual_window; jdx++) {
|
|
@@ -437,8 +437,8 @@ export function handle_invalid_values(values, mode) {
|
|
|
437
437
|
}
|
|
438
438
|
if (left_idx >= 0 && right_idx < cleaned.length) {
|
|
439
439
|
// Linear interpolation
|
|
440
|
-
const
|
|
441
|
-
cleaned[idx] = cleaned[left_idx] +
|
|
440
|
+
const frac = (idx - left_idx) / (right_idx - left_idx);
|
|
441
|
+
cleaned[idx] = cleaned[left_idx] + frac * (cleaned[right_idx] - cleaned[left_idx]);
|
|
442
442
|
}
|
|
443
443
|
else if (left_idx >= 0) {
|
|
444
444
|
cleaned[idx] = cleaned[left_idx];
|
|
@@ -797,34 +797,34 @@ function transpose(matrix) {
|
|
|
797
797
|
}
|
|
798
798
|
return result;
|
|
799
799
|
}
|
|
800
|
-
function multiply_matrices(
|
|
801
|
-
const rows_a =
|
|
802
|
-
const cols_a =
|
|
803
|
-
const cols_b =
|
|
800
|
+
function multiply_matrices(matrix_a, matrix_b) {
|
|
801
|
+
const rows_a = matrix_a.length;
|
|
802
|
+
const cols_a = matrix_a[0]?.length ?? 0;
|
|
803
|
+
const cols_b = matrix_b[0]?.length ?? 0;
|
|
804
804
|
const result = Array.from({ length: rows_a }, () => Array(cols_b).fill(0));
|
|
805
805
|
for (let row = 0; row < rows_a; row++) {
|
|
806
806
|
for (let col = 0; col < cols_b; col++) {
|
|
807
|
-
for (let
|
|
808
|
-
result[row][col] +=
|
|
807
|
+
for (let idx_k = 0; idx_k < cols_a; idx_k++) {
|
|
808
|
+
result[row][col] += matrix_a[row][idx_k] * matrix_b[idx_k][col];
|
|
809
809
|
}
|
|
810
810
|
}
|
|
811
811
|
}
|
|
812
812
|
return result;
|
|
813
813
|
}
|
|
814
814
|
function invert_matrix(matrix) {
|
|
815
|
-
const
|
|
816
|
-
if (
|
|
815
|
+
const size = matrix.length;
|
|
816
|
+
if (size === 0 || matrix[0].length !== size)
|
|
817
817
|
return null;
|
|
818
818
|
// Create augmented matrix [A | I]
|
|
819
819
|
const aug = matrix.map((row, idx) => [
|
|
820
820
|
...row,
|
|
821
|
-
...Array.from({ length:
|
|
821
|
+
...Array.from({ length: size }, (_, jdx) => (idx === jdx ? 1 : 0)),
|
|
822
822
|
]);
|
|
823
823
|
// Gaussian elimination with partial pivoting
|
|
824
|
-
for (let col = 0; col <
|
|
824
|
+
for (let col = 0; col < size; col++) {
|
|
825
825
|
// Find pivot
|
|
826
826
|
let max_row = col;
|
|
827
|
-
for (let row = col + 1; row <
|
|
827
|
+
for (let row = col + 1; row < size; row++) {
|
|
828
828
|
if (Math.abs(aug[row][col]) > Math.abs(aug[max_row][col])) {
|
|
829
829
|
max_row = row;
|
|
830
830
|
}
|
|
@@ -836,18 +836,18 @@ function invert_matrix(matrix) {
|
|
|
836
836
|
[aug[col], aug[max_row]] = [aug[max_row], aug[col]];
|
|
837
837
|
// Eliminate column
|
|
838
838
|
const pivot = aug[col][col];
|
|
839
|
-
for (let jdx = 0; jdx < 2 *
|
|
839
|
+
for (let jdx = 0; jdx < 2 * size; jdx++) {
|
|
840
840
|
aug[col][jdx] /= pivot;
|
|
841
841
|
}
|
|
842
|
-
for (let row = 0; row <
|
|
842
|
+
for (let row = 0; row < size; row++) {
|
|
843
843
|
if (row !== col) {
|
|
844
844
|
const factor = aug[row][col];
|
|
845
|
-
for (let jdx = 0; jdx < 2 *
|
|
845
|
+
for (let jdx = 0; jdx < 2 * size; jdx++) {
|
|
846
846
|
aug[row][jdx] -= factor * aug[col][jdx];
|
|
847
847
|
}
|
|
848
848
|
}
|
|
849
849
|
}
|
|
850
850
|
}
|
|
851
851
|
// Extract inverse
|
|
852
|
-
return aug.map((row) => row.slice(
|
|
852
|
+
return aug.map((row) => row.slice(size));
|
|
853
853
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Vec2 } from '../../math';
|
|
1
2
|
import type { DataSeries, ErrorBand, FillBoundary, FillCurveType, FillGradient, FillRegion } from './types';
|
|
2
3
|
export declare const LOG_EPSILON = 1e-10;
|
|
3
4
|
export interface Pt {
|
|
@@ -21,9 +22,9 @@ export declare function resolve_series_ref(ref: {
|
|
|
21
22
|
}, series: readonly DataSeries[]): DataSeries | null;
|
|
22
23
|
export declare function monotone_interpolate(xs: readonly number[], ys: readonly number[], x: number, tangents?: readonly number[]): number;
|
|
23
24
|
interface DomainContext {
|
|
24
|
-
x_domain:
|
|
25
|
-
y_domain:
|
|
26
|
-
y2_domain?:
|
|
25
|
+
x_domain: Vec2;
|
|
26
|
+
y_domain: Vec2;
|
|
27
|
+
y2_domain?: Vec2;
|
|
27
28
|
}
|
|
28
29
|
export declare function resolve_boundary_points(boundary: FillBoundary, series: readonly DataSeries[], domains: DomainContext, companion?: Pt[] | null): ResolvedBoundary | null;
|
|
29
30
|
export declare function compute_fill_segments(region: FillRegion, series: readonly DataSeries[], domains: DomainContext): FillSegment[];
|
|
@@ -91,9 +91,12 @@ export function monotone_interpolate(xs, ys, x, tangents) {
|
|
|
91
91
|
const p1 = ys[lo] + dx * tang[lo];
|
|
92
92
|
const p2 = ys[lo + 1] - dx * tang[lo + 1];
|
|
93
93
|
const p3 = ys[lo + 1];
|
|
94
|
-
const
|
|
95
|
-
const mu = 1 -
|
|
96
|
-
return mu * mu * mu * p0 +
|
|
94
|
+
const frac = (x - x0) / span;
|
|
95
|
+
const mu = 1 - frac;
|
|
96
|
+
return (mu * mu * mu * p0 +
|
|
97
|
+
3 * mu * mu * frac * p1 +
|
|
98
|
+
3 * mu * frac * frac * p2 +
|
|
99
|
+
frac * frac * frac * p3);
|
|
97
100
|
}
|
|
98
101
|
// Curve types whose interior follows a (near-)monotone cubic; evaluated via monotone_interpolate.
|
|
99
102
|
// Others (linear/step) evaluate piecewise (exact for them at clip points).
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { type Point2D, type Vec2 } from '../../math';
|
|
2
|
-
import type { AxisRanges, ScaleType, Y2SyncConfig, Y2SyncMode } from './types';
|
|
2
|
+
import type { AxisRanges, InitialRanges, ScaleType, Y2SyncConfig, Y2SyncMode } from './types';
|
|
3
3
|
export declare function get_relative_coords(evt: MouseEvent, element?: EventTarget | null): Point2D | null;
|
|
4
4
|
export declare function closest_data_idx(event: Event, attr: string, root?: Element | null): number | null;
|
|
5
5
|
export declare function normalize_y2_sync(sync: Y2SyncConfig | Y2SyncMode | undefined): Y2SyncConfig;
|
|
6
6
|
export declare function sync_y2_range(y1_range: Vec2, y2_base_range: Vec2, sync: Y2SyncConfig): Vec2;
|
|
7
|
+
export declare const snapshot_ranges: ({ x, x2, y, y2 }: AxisRanges) => InitialRanges;
|
|
7
8
|
export declare function pan_range_by_pixels(range: Vec2, pixel_delta: number, pixel_span: number, scale_type?: ScaleType): Vec2;
|
|
8
9
|
export declare function zoom_range_by_factor(range: Vec2, factor: number, scale_type?: ScaleType): Vec2;
|
|
9
10
|
export declare const to_epoch_num: (val: number | Date) => number;
|
|
10
11
|
export declare function remove_drag_listeners(move_handlers: ((evt: MouseEvent) => void)[], up_handlers: ((evt: MouseEvent) => void)[]): void;
|
|
11
12
|
export declare const sorted_range: (a: number, b: number) => Vec2;
|
|
13
|
+
export declare function invert_rect_range(scale: {
|
|
14
|
+
invert: (px: number) => number | Date;
|
|
15
|
+
}, a_px: number, b_px: number): Vec2 | null;
|
|
12
16
|
export declare const vec2_equal: (a: Vec2, b: Vec2) => boolean;
|
|
13
17
|
export declare const axis_ranges_equal: (a: AxisRanges, b: AxisRanges) => boolean;
|
|
14
18
|
type AxisRangeOverride = {
|
|
@@ -91,6 +91,13 @@ function axis_transform(scale_type) {
|
|
|
91
91
|
}
|
|
92
92
|
return { to: (val) => val, from: (val) => val };
|
|
93
93
|
}
|
|
94
|
+
// Snapshot the four axis ranges as fresh tuples at pan/zoom/touch interaction start
|
|
95
|
+
export const snapshot_ranges = ({ x, x2, y, y2 }) => ({
|
|
96
|
+
initial_x_range: [...x],
|
|
97
|
+
initial_x2_range: [...x2],
|
|
98
|
+
initial_y_range: [...y],
|
|
99
|
+
initial_y2_range: [...y2],
|
|
100
|
+
});
|
|
94
101
|
// Pan a range by a pixel delta, uniformly in screen space: linear axes shift by a
|
|
95
102
|
// constant amount, log axes by a constant factor (which also can't cross zero).
|
|
96
103
|
// `pixel_span` is the plot's pixel extent along the axis.
|
|
@@ -133,6 +140,13 @@ export function remove_drag_listeners(move_handlers, up_handlers) {
|
|
|
133
140
|
// Sorted [min, max] from two scalar bounds (rect-zoom inverts drag start/end,
|
|
134
141
|
// which arrive in either order depending on drag direction)
|
|
135
142
|
export const sorted_range = (a, b) => [Math.min(a, b), Math.max(a, b)];
|
|
143
|
+
// Invert a drag-rect edge pair through a scale to a sorted finite data range
|
|
144
|
+
// (time scales invert to Dates, coerced to epoch numbers). Returns null when
|
|
145
|
+
// either bound is non-finite or the range is degenerate (zero span).
|
|
146
|
+
export function invert_rect_range(scale, a_px, b_px) {
|
|
147
|
+
const range = sorted_range(to_epoch_num(scale.invert(a_px)), to_epoch_num(scale.invert(b_px)));
|
|
148
|
+
return range.every(Number.isFinite) && range[0] !== range[1] ? range : null;
|
|
149
|
+
}
|
|
136
150
|
// Strict per-bound equality of two [min, max] ranges
|
|
137
151
|
export const vec2_equal = (a, b) => a[0] === b[0] && a[1] === b[1];
|
|
138
152
|
// True when all four axis ranges match. The range-sync effects use this to skip
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Point2D, Vec2 } from '../../math';
|
|
2
|
+
import type { AxisRanges, PanConfig, ScaleType } from './types';
|
|
3
|
+
type Axis = `x` | `x2` | `y` | `y2`;
|
|
4
|
+
export interface PanZoomOptions {
|
|
5
|
+
ranges: () => AxisRanges;
|
|
6
|
+
scale_type: (axis: Axis) => ScaleType | undefined;
|
|
7
|
+
plot_dims: () => {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
11
|
+
pan: () => PanConfig | undefined;
|
|
12
|
+
set_range: (axis: Axis, range: Vec2) => void;
|
|
13
|
+
svg: () => SVGElement | null;
|
|
14
|
+
on_rect_zoom: (start: Point2D, current: Point2D) => void;
|
|
15
|
+
on_reset: () => void;
|
|
16
|
+
on_drag_move?: (coords: Point2D, inside_svg: boolean) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function create_pan_zoom(opts: PanZoomOptions): {
|
|
19
|
+
readonly drag_start: Point2D | null;
|
|
20
|
+
readonly drag_current: Point2D | null;
|
|
21
|
+
readonly is_pan_dragging: boolean;
|
|
22
|
+
readonly cursor: string;
|
|
23
|
+
set_focused: (focused: boolean) => void;
|
|
24
|
+
on_mouse_down: (evt: MouseEvent) => void;
|
|
25
|
+
on_wheel: (evt: WheelEvent) => void;
|
|
26
|
+
on_touch_start: (evt: TouchEvent) => void;
|
|
27
|
+
on_touch_move: (evt: TouchEvent) => void;
|
|
28
|
+
on_touch_end: () => void;
|
|
29
|
+
on_key_down: (evt: KeyboardEvent) => void;
|
|
30
|
+
on_window_key_down: (evt: KeyboardEvent) => void;
|
|
31
|
+
on_window_key_up: (evt: KeyboardEvent) => void;
|
|
32
|
+
reset_view: () => void;
|
|
33
|
+
destroy: () => void;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// Shared pan/zoom/touch/drag-rect interaction controller for the 2D plot components
|
|
2
|
+
// (BarPlot, BoxPlot, Histogram, ScatterPlot). Owns the interaction state machine;
|
|
3
|
+
// per-component policy (which axis props to write on rect-zoom, reset semantics)
|
|
4
|
+
// stays in the component via the on_rect_zoom/on_reset/set_range callbacks.
|
|
5
|
+
import { MIN_TOUCH_DISTANCE_PIXELS, pan_range_by_pixels, PINCH_ZOOM_THRESHOLD, remove_drag_listeners, snapshot_ranges, zoom_range_by_factor, } from './interactions';
|
|
6
|
+
const AXES = [`x`, `x2`, `y`, `y2`];
|
|
7
|
+
export function create_pan_zoom(opts) {
|
|
8
|
+
// Rect-zoom drag state
|
|
9
|
+
let drag_state = $state({ start: null, current: null, bounds: null });
|
|
10
|
+
// Pan state
|
|
11
|
+
let is_focused = $state(false);
|
|
12
|
+
let shift_held = $state(false);
|
|
13
|
+
let pan_drag_state = $state(null);
|
|
14
|
+
let touch_state = $state(null);
|
|
15
|
+
const cancel_rect_drag = () => {
|
|
16
|
+
drag_state = { start: null, current: null, bounds: null };
|
|
17
|
+
if (typeof window !== `undefined`) {
|
|
18
|
+
window.removeEventListener(`mousemove`, on_window_mouse_move);
|
|
19
|
+
window.removeEventListener(`mouseup`, on_window_mouse_up);
|
|
20
|
+
document.body.style.cursor = ``;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const on_window_mouse_move = (evt) => {
|
|
24
|
+
if (!drag_state.start || !drag_state.bounds)
|
|
25
|
+
return;
|
|
26
|
+
const coords = {
|
|
27
|
+
x: evt.clientX - drag_state.bounds.left,
|
|
28
|
+
y: evt.clientY - drag_state.bounds.top,
|
|
29
|
+
};
|
|
30
|
+
drag_state.current = coords;
|
|
31
|
+
const inside_svg = coords.x >= 0 &&
|
|
32
|
+
coords.x <= drag_state.bounds.width &&
|
|
33
|
+
coords.y >= 0 &&
|
|
34
|
+
coords.y <= drag_state.bounds.height;
|
|
35
|
+
opts.on_drag_move?.(coords, inside_svg);
|
|
36
|
+
};
|
|
37
|
+
const on_window_mouse_up = () => {
|
|
38
|
+
if (drag_state.start && drag_state.current) {
|
|
39
|
+
// Ignore minuscule drag rects (e.g. accidental clicks)
|
|
40
|
+
const dx = Math.abs(drag_state.start.x - drag_state.current.x);
|
|
41
|
+
const dy = Math.abs(drag_state.start.y - drag_state.current.y);
|
|
42
|
+
if (dx > 5 && dy > 5)
|
|
43
|
+
opts.on_rect_zoom(drag_state.start, drag_state.current);
|
|
44
|
+
}
|
|
45
|
+
cancel_rect_drag();
|
|
46
|
+
};
|
|
47
|
+
// Pan/zoom all four axes from an interaction-start snapshot, each in its own
|
|
48
|
+
// scale's transform space (log axes pan by a constant factor, linear by a shift)
|
|
49
|
+
const pan_all_axes = (init, dx_px, dy_px) => {
|
|
50
|
+
const dims = opts.plot_dims();
|
|
51
|
+
for (const axis of AXES) {
|
|
52
|
+
const horizontal = axis === `x` || axis === `x2`;
|
|
53
|
+
opts.set_range(axis, pan_range_by_pixels(init[`initial_${axis}_range`], horizontal ? dx_px : dy_px, horizontal ? dims.width : dims.height, opts.scale_type(axis)));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const zoom_all_axes = (init, factor) => {
|
|
57
|
+
for (const axis of AXES) {
|
|
58
|
+
opts.set_range(axis, zoom_range_by_factor(init[`initial_${axis}_range`], factor, opts.scale_type(axis)));
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
// Pan drag handler (drag direction inverted on x for natural pan feel)
|
|
62
|
+
const on_pan_move = (evt) => {
|
|
63
|
+
if (!pan_drag_state)
|
|
64
|
+
return;
|
|
65
|
+
const sensitivity = opts.pan()?.drag_sensitivity ?? 1;
|
|
66
|
+
pan_all_axes(pan_drag_state, -(evt.clientX - pan_drag_state.start.x) * sensitivity, (evt.clientY - pan_drag_state.start.y) * sensitivity);
|
|
67
|
+
};
|
|
68
|
+
const on_pan_end = () => {
|
|
69
|
+
pan_drag_state = null;
|
|
70
|
+
document.body.style.cursor = ``;
|
|
71
|
+
window.removeEventListener(`mousemove`, on_pan_move);
|
|
72
|
+
window.removeEventListener(`mouseup`, on_pan_end);
|
|
73
|
+
};
|
|
74
|
+
const on_mouse_down = (evt) => {
|
|
75
|
+
const svg = opts.svg();
|
|
76
|
+
if (!svg)
|
|
77
|
+
return;
|
|
78
|
+
// Shift+drag pans (when enabled); plain drag draws the zoom rect
|
|
79
|
+
const pan_enabled = opts.pan()?.enabled !== false;
|
|
80
|
+
if (pan_enabled && evt.shiftKey) {
|
|
81
|
+
evt.preventDefault();
|
|
82
|
+
pan_drag_state = {
|
|
83
|
+
start: { x: evt.clientX, y: evt.clientY },
|
|
84
|
+
...snapshot_ranges(opts.ranges()),
|
|
85
|
+
};
|
|
86
|
+
document.body.style.cursor = `grabbing`;
|
|
87
|
+
window.addEventListener(`mousemove`, on_pan_move);
|
|
88
|
+
window.addEventListener(`mouseup`, on_pan_end);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Cache bounds at drag start so window mousemove can compute relative coords
|
|
92
|
+
const bounds = svg.getBoundingClientRect();
|
|
93
|
+
const coords = { x: evt.clientX - bounds.left, y: evt.clientY - bounds.top };
|
|
94
|
+
drag_state = { start: coords, current: coords, bounds };
|
|
95
|
+
window.addEventListener(`mousemove`, on_window_mouse_move);
|
|
96
|
+
window.addEventListener(`mouseup`, on_window_mouse_up);
|
|
97
|
+
document.body.style.cursor = `crosshair`;
|
|
98
|
+
evt.preventDefault();
|
|
99
|
+
};
|
|
100
|
+
// Wheel handler for pan (requires focus and shift). Use shift_held state
|
|
101
|
+
// (tracked via window keydown/keyup) for compatibility with synthetic events.
|
|
102
|
+
const on_wheel = (evt) => {
|
|
103
|
+
const pan_cfg = opts.pan();
|
|
104
|
+
if (pan_cfg?.enabled === false || !is_focused || !shift_held)
|
|
105
|
+
return;
|
|
106
|
+
evt.preventDefault();
|
|
107
|
+
const dims = opts.plot_dims();
|
|
108
|
+
const sensitivity = pan_cfg?.wheel_sensitivity ?? 1;
|
|
109
|
+
const ranges = opts.ranges();
|
|
110
|
+
// Pan along the dominant wheel direction
|
|
111
|
+
if (Math.abs(evt.deltaX) > Math.abs(evt.deltaY)) {
|
|
112
|
+
const dx = evt.deltaX * sensitivity;
|
|
113
|
+
opts.set_range(`x`, pan_range_by_pixels(ranges.x, dx, dims.width, opts.scale_type(`x`)));
|
|
114
|
+
opts.set_range(`x2`, pan_range_by_pixels(ranges.x2, dx, dims.width, opts.scale_type(`x2`)));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const dy = evt.deltaY * sensitivity;
|
|
118
|
+
opts.set_range(`y`, pan_range_by_pixels(ranges.y, dy, dims.height, opts.scale_type(`y`)));
|
|
119
|
+
opts.set_range(`y2`, pan_range_by_pixels(ranges.y2, dy, dims.height, opts.scale_type(`y2`)));
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
// Touch handlers for pinch-zoom and two-finger pan
|
|
123
|
+
const on_touch_start = (evt) => {
|
|
124
|
+
const pan_cfg = opts.pan();
|
|
125
|
+
const touch_enabled = pan_cfg?.enabled !== false && pan_cfg?.touch_enabled !== false;
|
|
126
|
+
if (!touch_enabled || evt.touches.length !== 2)
|
|
127
|
+
return;
|
|
128
|
+
evt.preventDefault();
|
|
129
|
+
touch_state = {
|
|
130
|
+
start_touches: Array.from(evt.touches).map((touch) => ({
|
|
131
|
+
x: touch.clientX,
|
|
132
|
+
y: touch.clientY,
|
|
133
|
+
})),
|
|
134
|
+
...snapshot_ranges(opts.ranges()),
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
const on_touch_move = (evt) => {
|
|
138
|
+
if (!touch_state || evt.touches.length !== 2)
|
|
139
|
+
return;
|
|
140
|
+
evt.preventDefault();
|
|
141
|
+
const [t1, t2] = Array.from(evt.touches);
|
|
142
|
+
const [s1, s2] = touch_state.start_touches;
|
|
143
|
+
// Calculate center movement for pan
|
|
144
|
+
const start_center = { x: (s1.x + s2.x) / 2, y: (s1.y + s2.y) / 2 };
|
|
145
|
+
const curr_center = { x: (t1.clientX + t2.clientX) / 2, y: (t1.clientY + t2.clientY) / 2 };
|
|
146
|
+
const dx = curr_center.x - start_center.x;
|
|
147
|
+
const dy = curr_center.y - start_center.y;
|
|
148
|
+
// Calculate pinch scale (curr/start so spread = zoom in, pinch = zoom out)
|
|
149
|
+
const start_dist = Math.hypot(s2.x - s1.x, s2.y - s1.y);
|
|
150
|
+
// ignore near-coincident touches so curr_dist / start_dist can't blow up the scale
|
|
151
|
+
if (start_dist < MIN_TOUCH_DISTANCE_PIXELS)
|
|
152
|
+
return;
|
|
153
|
+
const curr_dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY);
|
|
154
|
+
const scale = curr_dist / start_dist;
|
|
155
|
+
// Pinch zoom about the view center if scale changed significantly, else pan
|
|
156
|
+
if (Math.abs(scale - 1) > PINCH_ZOOM_THRESHOLD && scale > Number.EPSILON) {
|
|
157
|
+
zoom_all_axes(touch_state, scale);
|
|
158
|
+
}
|
|
159
|
+
else
|
|
160
|
+
pan_all_axes(touch_state, -dx, dy);
|
|
161
|
+
};
|
|
162
|
+
const on_touch_end = () => {
|
|
163
|
+
touch_state = null;
|
|
164
|
+
};
|
|
165
|
+
// SVG keydown: Escape cancels an in-flight rect drag, Enter/Space resets the view.
|
|
166
|
+
// Target check keeps focusable plot children (bars, points) from triggering a reset
|
|
167
|
+
// when their own Enter/Space activation bubbles up.
|
|
168
|
+
const on_key_down = (evt) => {
|
|
169
|
+
if (evt.target !== evt.currentTarget)
|
|
170
|
+
return;
|
|
171
|
+
if (evt.key === `Escape` && drag_state.start)
|
|
172
|
+
cancel_rect_drag();
|
|
173
|
+
if ([`Enter`, ` `].includes(evt.key)) {
|
|
174
|
+
evt.preventDefault();
|
|
175
|
+
opts.on_reset();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
get drag_start() {
|
|
180
|
+
return drag_state.start;
|
|
181
|
+
},
|
|
182
|
+
get drag_current() {
|
|
183
|
+
return drag_state.current;
|
|
184
|
+
},
|
|
185
|
+
get is_pan_dragging() {
|
|
186
|
+
return pan_drag_state !== null;
|
|
187
|
+
},
|
|
188
|
+
get cursor() {
|
|
189
|
+
if (pan_drag_state)
|
|
190
|
+
return `grabbing`;
|
|
191
|
+
return shift_held && opts.pan()?.enabled !== false ? `grab` : `crosshair`;
|
|
192
|
+
},
|
|
193
|
+
set_focused: (focused) => {
|
|
194
|
+
is_focused = focused;
|
|
195
|
+
},
|
|
196
|
+
on_mouse_down,
|
|
197
|
+
on_wheel,
|
|
198
|
+
on_touch_start,
|
|
199
|
+
on_touch_move,
|
|
200
|
+
on_touch_end,
|
|
201
|
+
on_key_down,
|
|
202
|
+
on_window_key_down: (evt) => {
|
|
203
|
+
if (evt.key === `Shift`)
|
|
204
|
+
shift_held = true;
|
|
205
|
+
},
|
|
206
|
+
on_window_key_up: (evt) => {
|
|
207
|
+
if (evt.key === `Shift`)
|
|
208
|
+
shift_held = false;
|
|
209
|
+
},
|
|
210
|
+
reset_view: () => opts.on_reset(),
|
|
211
|
+
// Tear down any window listeners + cursor override if the component unmounts
|
|
212
|
+
// mid-drag (mouseup/panend would otherwise never fire, leaking listeners and a
|
|
213
|
+
// stuck cursor). Safe during SSR teardown, where window/document don't exist.
|
|
214
|
+
destroy: () => {
|
|
215
|
+
remove_drag_listeners([on_window_mouse_move, on_pan_move], [on_window_mouse_up, on_pan_end]);
|
|
216
|
+
drag_state = { start: null, current: null, bounds: null };
|
|
217
|
+
pan_drag_state = null;
|
|
218
|
+
touch_state = null;
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Tween, type TweenOptions } from 'svelte/motion';
|
|
2
|
+
type Point = {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function create_placed_tween(opts: {
|
|
7
|
+
placement: () => Point | null;
|
|
8
|
+
dims: () => {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
responsive: () => boolean;
|
|
13
|
+
element: () => Element | null | undefined;
|
|
14
|
+
tween?: () => TweenOptions<Point> | undefined;
|
|
15
|
+
suspended?: () => boolean;
|
|
16
|
+
manual_position?: () => Point | null;
|
|
17
|
+
}): {
|
|
18
|
+
coords: Tween<Point>;
|
|
19
|
+
set_locked: (locked: boolean) => void;
|
|
20
|
+
};
|
|
21
|
+
export {};
|