matterviz 0.3.0 → 0.3.2
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/FilePicker.svelte +37 -20
- package/dist/Icon.svelte +2 -2
- package/dist/MillerIndexInput.svelte +60 -0
- package/dist/MillerIndexInput.svelte.d.ts +7 -0
- package/dist/app.css +38 -2
- package/dist/brillouin/BrillouinZone.svelte +20 -62
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneExportPane.svelte +12 -20
- package/dist/brillouin/BrillouinZoneScene.svelte +2 -2
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +192 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +677 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2688 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +33 -0
- package/dist/chempot-diagram/compute.d.ts +38 -0
- package/dist/chempot-diagram/compute.js +650 -0
- package/dist/chempot-diagram/index.d.ts +5 -0
- package/dist/chempot-diagram/index.js +5 -0
- package/dist/chempot-diagram/pointer.d.ts +16 -0
- package/dist/chempot-diagram/pointer.js +40 -0
- package/dist/chempot-diagram/temperature.d.ts +15 -0
- package/dist/chempot-diagram/temperature.js +37 -0
- package/dist/chempot-diagram/types.d.ts +83 -0
- package/dist/chempot-diagram/types.js +27 -0
- package/dist/colors/index.d.ts +3 -1
- package/dist/colors/index.js +4 -0
- package/dist/composition/BarChart.svelte +13 -22
- package/dist/composition/BubbleChart.svelte +5 -3
- package/dist/composition/FormulaFilter.svelte +770 -90
- package/dist/composition/FormulaFilter.svelte.d.ts +37 -1
- package/dist/composition/PieChart.svelte +43 -18
- package/dist/composition/PieChart.svelte.d.ts +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/convex-hull/ConvexHull.svelte +14 -1
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +14 -45
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +396 -134
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +93 -42
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte +94 -31
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +4 -2
- package/dist/convex-hull/ConvexHullStats.svelte +697 -128
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +1 -0
- package/dist/convex-hull/GasPressureControls.svelte +72 -38
- package/dist/convex-hull/GasPressureControls.svelte.d.ts +2 -1
- package/dist/convex-hull/TemperatureSlider.svelte +46 -19
- package/dist/convex-hull/TemperatureSlider.svelte.d.ts +2 -1
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +36 -0
- package/dist/convex-hull/gas-thermodynamics.js +16 -5
- package/dist/convex-hull/helpers.d.ts +7 -1
- package/dist/convex-hull/helpers.js +45 -15
- package/dist/convex-hull/index.d.ts +15 -1
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +8 -21
- package/dist/convex-hull/thermodynamics.js +106 -17
- package/dist/convex-hull/types.d.ts +7 -0
- package/dist/convex-hull/types.js +11 -0
- package/dist/coordination/CoordinationBarPlot.svelte +29 -46
- package/dist/element/BohrAtom.svelte +1 -1
- package/dist/element/data.js +2 -14
- package/dist/element/data.json.gz +0 -0
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +1 -0
- package/dist/element/types.d.ts +1 -0
- package/dist/fermi-surface/FermiSurface.svelte +21 -65
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/compute.js +1 -21
- package/dist/fermi-surface/marching-cubes.d.ts +2 -13
- package/dist/fermi-surface/marching-cubes.js +2 -519
- package/dist/fermi-surface/parse.js +17 -23
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1273 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +171 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +31 -0
- package/dist/heatmap-matrix/index.d.ts +53 -0
- package/dist/heatmap-matrix/index.js +100 -0
- package/dist/heatmap-matrix/shared.d.ts +2 -0
- package/dist/heatmap-matrix/shared.js +4 -0
- package/dist/icons.d.ts +119 -0
- package/dist/icons.js +119 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/io/export.js +15 -3
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +43 -0
- package/dist/io/index.d.ts +2 -2
- package/dist/io/index.js +2 -112
- package/dist/io/types.d.ts +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +118 -0
- package/dist/isosurface/Isosurface.svelte +231 -0
- package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
- package/dist/isosurface/IsosurfaceControls.svelte +273 -0
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
- package/dist/isosurface/index.d.ts +5 -0
- package/dist/isosurface/index.js +6 -0
- package/dist/isosurface/parse.d.ts +6 -0
- package/dist/isosurface/parse.js +548 -0
- package/dist/isosurface/slice.d.ts +11 -0
- package/dist/isosurface/slice.js +145 -0
- package/dist/isosurface/types.d.ts +55 -0
- package/dist/isosurface/types.js +178 -0
- package/dist/labels.d.ts +2 -1
- package/dist/labels.js +1 -0
- package/dist/layout/InfoTag.svelte +62 -62
- package/dist/layout/SubpageGrid.svelte +74 -0
- package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +226 -53
- package/dist/layout/json-tree/JsonTree.svelte +425 -51
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
- package/dist/layout/json-tree/JsonValue.svelte +218 -97
- package/dist/layout/json-tree/types.d.ts +27 -2
- package/dist/layout/json-tree/utils.d.ts +14 -1
- package/dist/layout/json-tree/utils.js +254 -0
- package/dist/marching-cubes.d.ts +14 -0
- package/dist/marching-cubes.js +519 -0
- package/dist/math.d.ts +8 -0
- package/dist/math.js +374 -7
- package/dist/overlays/ContextMenu.svelte +3 -2
- package/dist/overlays/DraggablePane.svelte +163 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +232 -77
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +32 -11
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +103 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +102 -95
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +7 -0
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +100 -26
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
- package/dist/phase-diagram/index.d.ts +2 -0
- package/dist/phase-diagram/index.js +2 -0
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +865 -0
- package/dist/phase-diagram/types.d.ts +10 -0
- package/dist/phase-diagram/utils.d.ts +7 -4
- package/dist/phase-diagram/utils.js +149 -59
- package/dist/plot/AxisLabel.svelte +26 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +473 -228
- package/dist/plot/BarPlot.svelte.d.ts +3 -3
- package/dist/plot/BarPlotControls.svelte +3 -2
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +54 -54
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/ElementScatter.svelte +4 -3
- package/dist/plot/FillArea.svelte +4 -1
- package/dist/plot/Histogram.svelte +320 -230
- package/dist/plot/Histogram.svelte.d.ts +2 -2
- package/dist/plot/HistogramControls.svelte +29 -10
- package/dist/plot/HistogramControls.svelte.d.ts +6 -2
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +2 -2
- package/dist/plot/PlotControls.svelte +109 -27
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +1 -1
- package/dist/plot/PortalSelect.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
- package/dist/plot/ReferencePlane.svelte +1 -3
- package/dist/plot/ScatterPlot.svelte +343 -209
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +203 -250
- package/dist/plot/ScatterPlot3DScene.svelte +4 -7
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +95 -55
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ZeroLines.svelte +44 -0
- package/dist/plot/ZeroLines.svelte.d.ts +32 -0
- package/dist/plot/ZoomRect.svelte +21 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/axis-utils.d.ts +1 -1
- package/dist/plot/data-cleaning.js +1 -5
- package/dist/plot/index.d.ts +6 -2
- package/dist/plot/index.js +6 -2
- package/dist/plot/interactions.d.ts +8 -10
- package/dist/plot/interactions.js +10 -19
- package/dist/plot/layout.d.ts +7 -1
- package/dist/plot/layout.js +12 -4
- package/dist/plot/reference-line.d.ts +4 -21
- package/dist/plot/reference-line.js +7 -81
- package/dist/plot/types.d.ts +42 -17
- package/dist/plot/types.js +10 -0
- package/dist/plot/utils/label-placement.js +14 -11
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +55 -66
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/index.d.ts +1 -1
- package/dist/rdf/index.js +1 -1
- package/dist/settings.d.ts +5 -0
- package/dist/settings.js +37 -3
- package/dist/spectral/Bands.svelte +515 -143
- package/dist/spectral/Bands.svelte.d.ts +22 -2
- package/dist/spectral/helpers.d.ts +23 -1
- package/dist/spectral/helpers.js +65 -9
- package/dist/spectral/types.d.ts +2 -0
- package/dist/structure/AtomLegend.svelte +31 -10
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CellSelect.svelte +92 -22
- package/dist/structure/Lattice.svelte +2 -0
- package/dist/structure/Structure.svelte +716 -173
- package/dist/structure/Structure.svelte.d.ts +7 -2
- package/dist/structure/StructureControls.svelte +26 -14
- package/dist/structure/StructureControls.svelte.d.ts +5 -1
- package/dist/structure/StructureInfoPane.svelte +7 -1
- package/dist/structure/StructureScene.svelte +386 -95
- package/dist/structure/StructureScene.svelte.d.ts +15 -4
- package/dist/structure/atom-properties.d.ts +6 -2
- package/dist/structure/atom-properties.js +38 -25
- package/dist/structure/export.js +10 -7
- package/dist/structure/ferrox-wasm-types.d.ts +3 -2
- package/dist/structure/ferrox-wasm-types.js +0 -3
- package/dist/structure/ferrox-wasm.d.ts +3 -2
- package/dist/structure/ferrox-wasm.js +1 -2
- package/dist/structure/index.d.ts +7 -0
- package/dist/structure/index.js +22 -0
- package/dist/structure/parse.js +19 -16
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +102 -0
- package/dist/structure/validation.js +6 -3
- package/dist/symmetry/SymmetryStats.svelte +18 -4
- package/dist/symmetry/WyckoffTable.svelte +18 -10
- package/dist/symmetry/index.d.ts +7 -4
- package/dist/symmetry/index.js +83 -18
- package/dist/table/HeatmapTable.svelte +468 -69
- package/dist/table/HeatmapTable.svelte.d.ts +13 -1
- package/dist/table/ToggleMenu.svelte +291 -44
- package/dist/table/ToggleMenu.svelte.d.ts +4 -1
- package/dist/table/index.d.ts +3 -0
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tooltip/index.js +1 -0
- package/dist/trajectory/Trajectory.svelte +147 -145
- package/dist/trajectory/TrajectoryExportPane.svelte +13 -9
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.js +3 -5
- package/dist/trajectory/format-detect.d.ts +9 -0
- package/dist/trajectory/format-detect.js +76 -0
- package/dist/trajectory/frame-reader.d.ts +17 -0
- package/dist/trajectory/frame-reader.js +339 -0
- package/dist/trajectory/helpers.d.ts +15 -0
- package/dist/trajectory/helpers.js +187 -0
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +11 -4
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +76 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +121 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +304 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +169 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +65 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +109 -0
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +4 -0
- package/dist/xrd/XrdPlot.svelte +6 -4
- package/dist/xrd/calc-xrd.js +0 -1
- package/package.json +33 -23
- package/readme.md +4 -4
- package/dist/trajectory/parse.d.ts +0 -42
- package/dist/trajectory/parse.js +0 -1267
- /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
<script lang="ts">import { format_value } from '../labels';
|
|
2
2
|
import { FullscreenToggle, set_fullscreen_bg } from '../layout';
|
|
3
|
-
import { compute_element_placement, HistogramControls,
|
|
4
|
-
import {
|
|
3
|
+
import { AxisLabel, compute_element_placement, HistogramControls, PlotLegend, ReferenceLine, } from './';
|
|
4
|
+
import { create_axis_change_handler } from './axis-utils';
|
|
5
5
|
import { extract_series_color, prepare_legend_data } from './data-transform';
|
|
6
6
|
import { AXIS_DEFAULTS } from './defaults';
|
|
7
7
|
import { create_dimension_tracker, create_hover_lock, } from './hover-lock.svelte';
|
|
8
8
|
import { get_relative_coords, pan_range, PINCH_ZOOM_THRESHOLD, pixels_to_data_delta, } from './interactions';
|
|
9
|
-
import { calc_auto_padding, constrain_tooltip_position, filter_padding, LABEL_GAP_DEFAULT,
|
|
9
|
+
import { calc_auto_padding, constrain_tooltip_position, filter_padding, LABEL_GAP_DEFAULT, measure_max_tick_width, } from './layout';
|
|
10
10
|
import { group_ref_lines_by_z, index_ref_lines } from './reference-line';
|
|
11
11
|
import { create_scale, generate_ticks, get_nice_data_range, get_tick_label, } from './scales';
|
|
12
12
|
import { get_scale_type_name } from './types';
|
|
13
|
+
import ZeroLines from './ZeroLines.svelte';
|
|
14
|
+
import ZoomRect from './ZoomRect.svelte';
|
|
13
15
|
import { DEFAULTS } from '../settings';
|
|
14
16
|
import { bin, max } from 'd3-array';
|
|
15
17
|
import { untrack } from 'svelte';
|
|
16
18
|
import { Tween } from 'svelte/motion';
|
|
17
19
|
import PlotTooltip from './PlotTooltip.svelte';
|
|
18
20
|
import { bar_path } from './svg';
|
|
19
|
-
let { series = $bindable([]), x_axis: x_axis_init = {}, y_axis: y_axis_init = {}, y2_axis: y2_axis_init = {}, display: display_init = DEFAULTS.histogram.display, x_range = [null, null], y_range = [null, null], y2_range = [null, null], range_padding = 0.05, padding = { t: 20, b: 60, l: 60, r: 20 }, bins = $bindable(100), show_legend = $bindable(true), legend = {}, bar: bar_init = {}, selected_property = $bindable(``), mode = $bindable(`single`), tooltip, hovered = $bindable(false), change = () => { }, on_bar_click, on_bar_hover, ref_lines = $bindable([]), on_ref_line_click, on_ref_line_hover, show_controls = $bindable(true), controls_open = $bindable(false), on_series_toggle = () => { }, controls_toggle_props, controls_pane_props, fullscreen = $bindable(false), fullscreen_toggle = true, children, header_controls, controls_extra, data_loader, on_axis_change, on_error, pan = {}, ...rest } = $props();
|
|
21
|
+
let { series = $bindable([]), x_axis: x_axis_init = {}, x2_axis: x2_axis_init = {}, y_axis: y_axis_init = {}, y2_axis: y2_axis_init = {}, display: display_init = DEFAULTS.histogram.display, x_range = [null, null], x2_range = [null, null], y_range = [null, null], y2_range = [null, null], range_padding = 0.05, padding = { t: 20, b: 60, l: 60, r: 20 }, bins = $bindable(100), show_legend = $bindable(true), legend = {}, bar: bar_init = {}, selected_property = $bindable(``), mode = $bindable(`single`), tooltip, hovered = $bindable(false), change = () => { }, on_bar_click, on_bar_hover, ref_lines = $bindable([]), on_ref_line_click, on_ref_line_hover, show_controls = $bindable(true), controls_open = $bindable(false), on_series_toggle = () => { }, controls_toggle_props, controls_pane_props, fullscreen = $bindable(false), fullscreen_toggle = true, children, header_controls, controls_extra, data_loader, on_axis_change, on_error, pan = {}, ...rest } = $props();
|
|
20
22
|
// Local state for controls (initialized from props, owned by this component)
|
|
21
23
|
// Include key AXIS_DEFAULTS props (range, ticks, scale_type) that PlotControls needs
|
|
22
24
|
// Using $state because these have bindings in HistogramControls/PlotControls
|
|
@@ -24,6 +26,12 @@ let { series = $bindable([]), x_axis: x_axis_init = {}, y_axis: y_axis_init = {}
|
|
|
24
26
|
const { format: _, ...axis_state_defaults } = AXIS_DEFAULTS; // Exclude format (has component-specific default)
|
|
25
27
|
let bar = $state(untrack(() => ({ ...DEFAULTS.histogram.bar, ...bar_init })));
|
|
26
28
|
let x_axis = $state(untrack(() => ({ ...axis_state_defaults, ...x_axis_init })));
|
|
29
|
+
// x2-axis needs different default label_shift for top-side positioning
|
|
30
|
+
let x2_axis = $state(untrack(() => ({
|
|
31
|
+
...axis_state_defaults,
|
|
32
|
+
label_shift: { x: 0, y: 40 },
|
|
33
|
+
...x2_axis_init,
|
|
34
|
+
})));
|
|
27
35
|
let y_axis = $state(untrack(() => ({ ...axis_state_defaults, ...y_axis_init })));
|
|
28
36
|
// y2-axis needs different default label_shift for right-side positioning
|
|
29
37
|
let y2_axis = $state(untrack(() => ({
|
|
@@ -34,6 +42,7 @@ let y2_axis = $state(untrack(() => ({
|
|
|
34
42
|
let display = $state(untrack(() => ({ ...DEFAULTS.histogram.display, ...display_init })));
|
|
35
43
|
// Merge component-specific defaults with local state (format comes from here, not AXIS_DEFAULTS)
|
|
36
44
|
const final_x_axis = $derived({ label: `Value`, format: `.2~s`, ...x_axis });
|
|
45
|
+
const final_x2_axis = $derived({ label: `Value`, format: `.2~s`, ...x2_axis });
|
|
37
46
|
const final_y_axis = $derived({ label: `Count`, format: `d`, ...y_axis });
|
|
38
47
|
const final_bar = $derived({ ...DEFAULTS.histogram.bar, ...bar });
|
|
39
48
|
const final_y2_axis = $derived({ label: `Count`, format: `d`, ...y2_axis });
|
|
@@ -71,9 +80,14 @@ let selected_series = $derived(mode === `single` && selected_property
|
|
|
71
80
|
// Separate series by y-axis
|
|
72
81
|
let y1_series = $derived(selected_series.filter((srs) => (srs.y_axis ?? `y1`) === `y1`));
|
|
73
82
|
let y2_series = $derived(selected_series.filter((srs) => srs.y_axis === `y2`));
|
|
83
|
+
let x2_series = $derived(selected_series.filter((srs) => srs.x_axis === `x2`));
|
|
74
84
|
let auto_ranges = $derived.by(() => {
|
|
75
85
|
const all_values = selected_series.flatMap((srs) => srs.y);
|
|
76
86
|
const auto_x = get_nice_data_range(all_values.map((val) => ({ x: val, y: 0 })), ({ x }) => x, x_range, final_x_axis.scale_type ?? `linear`, range_padding, false);
|
|
87
|
+
const x2_values = x2_series.flatMap((srs) => srs.y);
|
|
88
|
+
const auto_x2 = x2_values.length > 0
|
|
89
|
+
? get_nice_data_range(x2_values.map((val) => ({ x: val, y: 0 })), ({ x }) => x, x2_range, final_x2_axis.scale_type ?? `linear`, range_padding, false)
|
|
90
|
+
: [0, 1];
|
|
77
91
|
// Calculate y-range for a specific set of series
|
|
78
92
|
const calc_y_range = (series_list, y_limit, scale_type) => {
|
|
79
93
|
const type_name = get_scale_type_name(scale_type);
|
|
@@ -96,17 +110,19 @@ let auto_ranges = $derived.by(() => {
|
|
|
96
110
|
};
|
|
97
111
|
const y1_range = calc_y_range(y1_series, y_range, final_y_axis.scale_type ?? `linear`);
|
|
98
112
|
const y2_auto_range = calc_y_range(y2_series, y2_range, final_y2_axis.scale_type ?? `linear`);
|
|
99
|
-
return { x: auto_x, y: y1_range, y2: y2_auto_range };
|
|
113
|
+
return { x: auto_x, x2: auto_x2, y: y1_range, y2: y2_auto_range };
|
|
100
114
|
});
|
|
101
115
|
// Initialize ranges
|
|
102
116
|
let ranges = $state({
|
|
103
117
|
initial: {
|
|
104
118
|
x: [0, 1],
|
|
119
|
+
x2: [0, 1],
|
|
105
120
|
y: [0, 1],
|
|
106
121
|
y2: [0, 1],
|
|
107
122
|
},
|
|
108
123
|
current: {
|
|
109
124
|
x: [0, 1],
|
|
125
|
+
x2: [0, 1],
|
|
110
126
|
y: [0, 1],
|
|
111
127
|
y2: [0, 1],
|
|
112
128
|
},
|
|
@@ -119,6 +135,12 @@ $effect(() => {
|
|
|
119
135
|
final_x_axis.range[1] ?? auto_ranges.x[1],
|
|
120
136
|
]
|
|
121
137
|
: auto_ranges.x;
|
|
138
|
+
const new_x2 = final_x2_axis.range
|
|
139
|
+
? [
|
|
140
|
+
final_x2_axis.range[0] ?? auto_ranges.x2[0],
|
|
141
|
+
final_x2_axis.range[1] ?? auto_ranges.x2[1],
|
|
142
|
+
]
|
|
143
|
+
: auto_ranges.x2;
|
|
122
144
|
const new_y = final_y_axis.range
|
|
123
145
|
? [
|
|
124
146
|
final_y_axis.range[0] ?? auto_ranges.y[0],
|
|
@@ -135,12 +157,16 @@ $effect(() => {
|
|
|
135
157
|
// Comparing against initial preserves user's pan/zoom state
|
|
136
158
|
const x_changed = new_x[0] !== ranges.initial.x[0] ||
|
|
137
159
|
new_x[1] !== ranges.initial.x[1];
|
|
160
|
+
const x2_changed = new_x2[0] !== ranges.initial.x2[0] ||
|
|
161
|
+
new_x2[1] !== ranges.initial.x2[1];
|
|
138
162
|
const y_changed = new_y[0] !== ranges.initial.y[0] ||
|
|
139
163
|
new_y[1] !== ranges.initial.y[1];
|
|
140
164
|
const y2_changed = new_y2[0] !== ranges.initial.y2[0] ||
|
|
141
165
|
new_y2[1] !== ranges.initial.y2[1];
|
|
142
166
|
if (x_changed)
|
|
143
167
|
[ranges.initial.x, ranges.current.x] = [new_x, new_x];
|
|
168
|
+
if (x2_changed)
|
|
169
|
+
[ranges.initial.x2, ranges.current.x2] = [new_x2, new_x2];
|
|
144
170
|
if (y_changed)
|
|
145
171
|
[ranges.initial.y, ranges.current.y] = [new_y, new_y];
|
|
146
172
|
if (y2_changed)
|
|
@@ -151,12 +177,14 @@ const default_padding = { t: 20, b: 60, l: 60, r: 20 };
|
|
|
151
177
|
let pad = $derived(filter_padding(padding, default_padding));
|
|
152
178
|
// Update padding based on tick label widths (untrack breaks circular dependency)
|
|
153
179
|
$effect(() => {
|
|
180
|
+
const current_ticks_x2 = untrack(() => ticks.x2);
|
|
154
181
|
const current_ticks_y = untrack(() => ticks.y);
|
|
155
182
|
const current_ticks_y2 = untrack(() => ticks.y2);
|
|
156
183
|
const new_pad = width && height && current_ticks_y.length
|
|
157
184
|
? calc_auto_padding({
|
|
158
185
|
padding,
|
|
159
186
|
default_padding,
|
|
187
|
+
x2_axis: { ...final_x2_axis, tick_values: current_ticks_x2 },
|
|
160
188
|
y_axis: { ...final_y_axis, tick_values: current_ticks_y },
|
|
161
189
|
y2_axis: { ...final_y2_axis, tick_values: current_ticks_y2 },
|
|
162
190
|
})
|
|
@@ -164,14 +192,23 @@ $effect(() => {
|
|
|
164
192
|
// Add y2 axis label space (calc_auto_padding only accounts for tick labels)
|
|
165
193
|
if (width && height && y2_series.length && current_ticks_y2.length &&
|
|
166
194
|
final_y2_axis.label) {
|
|
167
|
-
const y2_tick_width = Math.max(0, ...current_ticks_y2.map((tick) => measure_text_width(format_value(tick, final_y2_axis.format), `12px sans-serif`)));
|
|
168
195
|
const inside = final_y2_axis.tick?.label?.inside ?? false;
|
|
169
196
|
// When ticks are inside, they don't contribute to padding
|
|
170
197
|
const tick_shift = inside ? 0 : (final_y2_axis.tick?.label?.shift?.x ?? 0) + 8;
|
|
171
|
-
const tick_width_contribution = inside ? 0 :
|
|
198
|
+
const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max;
|
|
172
199
|
const label_thickness = Math.round(12 * 1.2);
|
|
173
200
|
new_pad.r = Math.max(new_pad.r, tick_width_contribution + LABEL_GAP_DEFAULT + tick_shift + label_thickness);
|
|
174
201
|
}
|
|
202
|
+
// Add x2 axis label space (mirroring y2 logic for top padding)
|
|
203
|
+
if (width && height && x2_series.length && current_ticks_x2.length &&
|
|
204
|
+
final_x2_axis.label) {
|
|
205
|
+
const inside = final_x2_axis.tick?.label?.inside ?? false;
|
|
206
|
+
const tick_shift = inside
|
|
207
|
+
? 0
|
|
208
|
+
: Math.abs(final_x2_axis.tick?.label?.shift?.y ?? 0) + 8;
|
|
209
|
+
const label_thickness = Math.round(12 * 1.2);
|
|
210
|
+
new_pad.t = Math.max(new_pad.t, tick_shift + LABEL_GAP_DEFAULT + label_thickness);
|
|
211
|
+
}
|
|
175
212
|
// Only update if padding actually changed
|
|
176
213
|
if (pad.t !== new_pad.t || pad.b !== new_pad.b || pad.l !== new_pad.l ||
|
|
177
214
|
pad.r !== new_pad.r)
|
|
@@ -180,6 +217,7 @@ $effect(() => {
|
|
|
180
217
|
// Scales and data
|
|
181
218
|
let scales = $derived({
|
|
182
219
|
x: create_scale(final_x_axis.scale_type ?? `linear`, ranges.current.x, [pad.l, width - pad.r]),
|
|
220
|
+
x2: create_scale(final_x2_axis.scale_type ?? `linear`, ranges.current.x2, [pad.l, width - pad.r]),
|
|
183
221
|
y: create_scale(final_y_axis.scale_type ?? `linear`, ranges.current.y, [height - pad.b, pad.t]),
|
|
184
222
|
y2: create_scale(final_y2_axis.scale_type ?? `linear`, ranges.current.y2, [height - pad.b, pad.t]),
|
|
185
223
|
});
|
|
@@ -189,8 +227,15 @@ let histogram_data = $derived.by(() => {
|
|
|
189
227
|
const hist_generator = bin()
|
|
190
228
|
.domain([ranges.current.x[0], ranges.current.x[1]])
|
|
191
229
|
.thresholds(bins);
|
|
230
|
+
const x2_hist_generator = x2_series.length > 0
|
|
231
|
+
? bin().domain([ranges.current.x2[0], ranges.current.x2[1]]).thresholds(bins)
|
|
232
|
+
: null;
|
|
192
233
|
return selected_series.map((series_data, series_idx) => {
|
|
193
|
-
const
|
|
234
|
+
const use_x2 = series_data.x_axis === `x2`;
|
|
235
|
+
const active_hist = use_x2 && x2_hist_generator
|
|
236
|
+
? x2_hist_generator
|
|
237
|
+
: hist_generator;
|
|
238
|
+
const bins_arr = active_hist(series_data.y);
|
|
194
239
|
const use_y2 = series_data.y_axis === `y2`;
|
|
195
240
|
return {
|
|
196
241
|
id: series_data.id ?? series_idx,
|
|
@@ -201,7 +246,9 @@ let histogram_data = $derived.by(() => {
|
|
|
201
246
|
: extract_series_color(series_data),
|
|
202
247
|
bins: bins_arr,
|
|
203
248
|
max_count: max(bins_arr, (data) => data.length) || 0,
|
|
249
|
+
x_axis: series_data.x_axis,
|
|
204
250
|
y_axis: series_data.y_axis,
|
|
251
|
+
x_scale: use_x2 ? scales.x2 : scales.x,
|
|
205
252
|
y_scale: use_y2 ? scales.y2 : scales.y,
|
|
206
253
|
};
|
|
207
254
|
});
|
|
@@ -210,6 +257,9 @@ let ticks = $derived({
|
|
|
210
257
|
x: width && height
|
|
211
258
|
? generate_ticks(ranges.current.x, final_x_axis.scale_type ?? `linear`, final_x_axis.ticks, scales.x, { default_count: 8 })
|
|
212
259
|
: [],
|
|
260
|
+
x2: width && height && x2_series.length > 0
|
|
261
|
+
? generate_ticks(ranges.current.x2, final_x2_axis.scale_type ?? `linear`, final_x2_axis.ticks, scales.x2, { default_count: 8 })
|
|
262
|
+
: [],
|
|
213
263
|
y: width && height
|
|
214
264
|
? generate_ticks(ranges.current.y, final_y_axis.scale_type ?? `linear`, final_y_axis.ticks, scales.y, { default_count: 6 })
|
|
215
265
|
: [],
|
|
@@ -217,16 +267,23 @@ let ticks = $derived({
|
|
|
217
267
|
? generate_ticks(ranges.current.y2, final_y2_axis.scale_type ?? `linear`, final_y2_axis.ticks, scales.y2, { default_count: 6 })
|
|
218
268
|
: [],
|
|
219
269
|
});
|
|
270
|
+
// Cache measured tick-label widths so expensive text measurement only runs
|
|
271
|
+
// when tick values/format change, not on every template rerender.
|
|
272
|
+
let tick_label_widths = $derived({
|
|
273
|
+
x2_max: measure_max_tick_width(ticks.x2, final_x2_axis.format ?? ``),
|
|
274
|
+
y_max: measure_max_tick_width(ticks.y, final_y_axis.format ?? ``),
|
|
275
|
+
y2_max: measure_max_tick_width(ticks.y2, final_y2_axis.format ?? ``),
|
|
276
|
+
});
|
|
220
277
|
let legend_data = $derived(prepare_legend_data(series));
|
|
221
278
|
// Collect histogram bar positions for legend placement
|
|
222
279
|
let hist_points_for_placement = $derived.by(() => {
|
|
223
280
|
if (!width || !height || !histogram_data.length)
|
|
224
281
|
return [];
|
|
225
282
|
const points = [];
|
|
226
|
-
for (const { bins, y_scale } of histogram_data) {
|
|
283
|
+
for (const { bins, x_scale, y_scale } of histogram_data) {
|
|
227
284
|
for (const bin of bins) {
|
|
228
285
|
if (bin.length > 0) {
|
|
229
|
-
const bar_x =
|
|
286
|
+
const bar_x = x_scale((bin.x0 + bin.x1) / 2);
|
|
230
287
|
const bar_y = y_scale(bin.length);
|
|
231
288
|
if (isFinite(bar_x) && isFinite(bar_y)) {
|
|
232
289
|
// Add multiple points for taller bars to increase their weight
|
|
@@ -291,6 +348,8 @@ const handle_zoom = () => {
|
|
|
291
348
|
return;
|
|
292
349
|
const start_x = scales.x.invert(drag_state.start.x);
|
|
293
350
|
const end_x = scales.x.invert(drag_state.current.x);
|
|
351
|
+
const start_x2 = scales.x2.invert(drag_state.start.x);
|
|
352
|
+
const end_x2 = scales.x2.invert(drag_state.current.x);
|
|
294
353
|
const start_y = scales.y.invert(drag_state.start.y);
|
|
295
354
|
const end_y = scales.y.invert(drag_state.current.y);
|
|
296
355
|
const start_y2 = scales.y2.invert(drag_state.start.y);
|
|
@@ -304,6 +363,12 @@ const handle_zoom = () => {
|
|
|
304
363
|
...x_axis,
|
|
305
364
|
range: [Math.min(start_x, end_x), Math.max(start_x, end_x)],
|
|
306
365
|
};
|
|
366
|
+
if (x2_series.length > 0) {
|
|
367
|
+
x2_axis = {
|
|
368
|
+
...x2_axis,
|
|
369
|
+
range: [Math.min(start_x2, end_x2), Math.max(start_x2, end_x2)],
|
|
370
|
+
};
|
|
371
|
+
}
|
|
307
372
|
y_axis = {
|
|
308
373
|
...y_axis,
|
|
309
374
|
range: [Math.min(start_y, end_y), Math.max(start_y, end_y)],
|
|
@@ -341,9 +406,11 @@ const on_pan_move = (evt) => {
|
|
|
341
406
|
const plot_height = height - pad.t - pad.b;
|
|
342
407
|
const sensitivity = pan?.drag_sensitivity ?? 1;
|
|
343
408
|
const x_delta = pixels_to_data_delta(-dx * sensitivity, pan_drag_state.initial_x_range, plot_width);
|
|
409
|
+
const x2_delta = pixels_to_data_delta(-dx * sensitivity, pan_drag_state.initial_x2_range, plot_width);
|
|
344
410
|
const y_delta = pixels_to_data_delta(dy * sensitivity, pan_drag_state.initial_y_range, plot_height);
|
|
345
411
|
const y2_delta = pixels_to_data_delta(dy * sensitivity, pan_drag_state.initial_y2_range, plot_height);
|
|
346
412
|
ranges.current.x = pan_range(pan_drag_state.initial_x_range, x_delta);
|
|
413
|
+
ranges.current.x2 = pan_range(pan_drag_state.initial_x2_range, x2_delta);
|
|
347
414
|
ranges.current.y = pan_range(pan_drag_state.initial_y_range, y_delta);
|
|
348
415
|
ranges.current.y2 = pan_range(pan_drag_state.initial_y2_range, y2_delta);
|
|
349
416
|
};
|
|
@@ -364,6 +431,7 @@ function handle_mouse_down(evt) {
|
|
|
364
431
|
pan_drag_state = {
|
|
365
432
|
start: { x: evt.clientX, y: evt.clientY },
|
|
366
433
|
initial_x_range: [...ranges.current.x],
|
|
434
|
+
initial_x2_range: [...ranges.current.x2],
|
|
367
435
|
initial_y_range: [...ranges.current.y],
|
|
368
436
|
initial_y2_range: [...ranges.current.y2],
|
|
369
437
|
};
|
|
@@ -395,10 +463,12 @@ function handle_wheel(evt) {
|
|
|
395
463
|
const sensitivity = pan?.wheel_sensitivity ?? 1;
|
|
396
464
|
// Determine pan direction based on wheel delta
|
|
397
465
|
const x_delta = pixels_to_data_delta(evt.deltaX * sensitivity, ranges.current.x, plot_width);
|
|
466
|
+
const x2_delta = pixels_to_data_delta(evt.deltaX * sensitivity, ranges.current.x2, plot_width);
|
|
398
467
|
const y_delta = pixels_to_data_delta(evt.deltaY * sensitivity, ranges.current.y, plot_height);
|
|
399
468
|
const y2_delta = pixels_to_data_delta(evt.deltaY * sensitivity, ranges.current.y2, plot_height);
|
|
400
469
|
if (Math.abs(evt.deltaX) > Math.abs(evt.deltaY)) {
|
|
401
470
|
ranges.current.x = pan_range(ranges.current.x, x_delta);
|
|
471
|
+
ranges.current.x2 = pan_range(ranges.current.x2, x2_delta);
|
|
402
472
|
}
|
|
403
473
|
else {
|
|
404
474
|
ranges.current.y = pan_range(ranges.current.y, y_delta);
|
|
@@ -415,6 +485,7 @@ function handle_touch_start(evt) {
|
|
|
415
485
|
touch_state = {
|
|
416
486
|
start_touches: touches.map((touch) => ({ x: touch.clientX, y: touch.clientY })),
|
|
417
487
|
initial_x_range: [...ranges.current.x],
|
|
488
|
+
initial_x2_range: [...ranges.current.x2],
|
|
418
489
|
initial_y_range: [...ranges.current.y],
|
|
419
490
|
initial_y2_range: [...ranges.current.y2],
|
|
420
491
|
};
|
|
@@ -449,16 +520,23 @@ function handle_touch_move(evt) {
|
|
|
449
520
|
// Pinch zoom centered on gesture center
|
|
450
521
|
// Divide by scale so spread (scale > 1) = smaller span (zoom in)
|
|
451
522
|
const x_span = touch_state.initial_x_range[1] - touch_state.initial_x_range[0];
|
|
523
|
+
const x2_span = touch_state.initial_x2_range[1] -
|
|
524
|
+
touch_state.initial_x2_range[0];
|
|
452
525
|
const y_span = touch_state.initial_y_range[1] - touch_state.initial_y_range[0];
|
|
453
526
|
const y2_span = touch_state.initial_y2_range[1] -
|
|
454
527
|
touch_state.initial_y2_range[0];
|
|
455
528
|
const x_center = (touch_state.initial_x_range[0] + touch_state.initial_x_range[1]) / 2;
|
|
529
|
+
const x2_center = (touch_state.initial_x2_range[0] + touch_state.initial_x2_range[1]) / 2;
|
|
456
530
|
const y_center = (touch_state.initial_y_range[0] + touch_state.initial_y_range[1]) / 2;
|
|
457
531
|
const y2_center = (touch_state.initial_y2_range[0] + touch_state.initial_y2_range[1]) / 2;
|
|
458
532
|
ranges.current.x = [
|
|
459
533
|
x_center - x_span / scale / 2,
|
|
460
534
|
x_center + x_span / scale / 2,
|
|
461
535
|
];
|
|
536
|
+
ranges.current.x2 = [
|
|
537
|
+
x2_center - x2_span / scale / 2,
|
|
538
|
+
x2_center + x2_span / scale / 2,
|
|
539
|
+
];
|
|
462
540
|
ranges.current.y = [
|
|
463
541
|
y_center - y_span / scale / 2,
|
|
464
542
|
y_center + y_span / scale / 2,
|
|
@@ -471,9 +549,11 @@ function handle_touch_move(evt) {
|
|
|
471
549
|
else {
|
|
472
550
|
// Pan
|
|
473
551
|
const x_delta = pixels_to_data_delta(-dx, touch_state.initial_x_range, plot_width);
|
|
552
|
+
const x2_delta = pixels_to_data_delta(-dx, touch_state.initial_x2_range, plot_width);
|
|
474
553
|
const y_delta = pixels_to_data_delta(dy, touch_state.initial_y_range, plot_height);
|
|
475
554
|
const y2_delta = pixels_to_data_delta(dy, touch_state.initial_y2_range, plot_height);
|
|
476
555
|
ranges.current.x = pan_range(touch_state.initial_x_range, x_delta);
|
|
556
|
+
ranges.current.x2 = pan_range(touch_state.initial_x2_range, x2_delta);
|
|
477
557
|
ranges.current.y = pan_range(touch_state.initial_y_range, y_delta);
|
|
478
558
|
ranges.current.y2 = pan_range(touch_state.initial_y2_range, y2_delta);
|
|
479
559
|
}
|
|
@@ -484,26 +564,30 @@ function handle_touch_end() {
|
|
|
484
564
|
function handle_double_click() {
|
|
485
565
|
// Reset zoom to initial ranges (undo any pan/zoom)
|
|
486
566
|
ranges.current.x = [...ranges.initial.x];
|
|
567
|
+
ranges.current.x2 = [...ranges.initial.x2];
|
|
487
568
|
ranges.current.y = [...ranges.initial.y];
|
|
488
569
|
ranges.current.y2 = [...ranges.initial.y2];
|
|
489
570
|
// Also reset axis props so future data changes recalculate auto ranges
|
|
490
571
|
x_axis = { ...x_axis, range: [null, null] };
|
|
572
|
+
x2_axis = { ...x2_axis, range: [null, null] };
|
|
491
573
|
y_axis = { ...y_axis, range: [null, null] };
|
|
492
574
|
y2_axis = { ...y2_axis, range: [null, null] };
|
|
493
575
|
}
|
|
494
|
-
function handle_mouse_move(evt, value, count, property, active_y_axis = `y1`, series_idx = 0) {
|
|
576
|
+
function handle_mouse_move(evt, value, count, property, active_y_axis = `y1`, series_idx = 0, active_x_axis = `x1`) {
|
|
495
577
|
hovered = true;
|
|
496
578
|
hover_info = {
|
|
497
579
|
value,
|
|
498
580
|
count,
|
|
499
581
|
property,
|
|
500
582
|
active_y_axis,
|
|
583
|
+
active_x_axis,
|
|
501
584
|
x: value,
|
|
502
585
|
y: count,
|
|
503
586
|
series_idx,
|
|
504
587
|
metadata: null,
|
|
505
588
|
label: property,
|
|
506
|
-
x_axis,
|
|
589
|
+
x_axis: active_x_axis === `x2` ? x2_axis : x_axis,
|
|
590
|
+
x2_axis,
|
|
507
591
|
y_axis: active_y_axis === `y2` ? y2_axis : y_axis,
|
|
508
592
|
y2_axis,
|
|
509
593
|
};
|
|
@@ -527,11 +611,21 @@ $effect(() => {
|
|
|
527
611
|
});
|
|
528
612
|
// State accessors for shared axis change handler
|
|
529
613
|
const axis_state = {
|
|
530
|
-
get_axis: (axis) =>
|
|
614
|
+
get_axis: (axis) => {
|
|
615
|
+
if (axis === `x`)
|
|
616
|
+
return x_axis;
|
|
617
|
+
if (axis === `x2`)
|
|
618
|
+
return x2_axis;
|
|
619
|
+
if (axis === `y`)
|
|
620
|
+
return y_axis;
|
|
621
|
+
return y2_axis;
|
|
622
|
+
},
|
|
531
623
|
set_axis: (axis, config) => {
|
|
532
624
|
// Spread into existing state to preserve merged type structure
|
|
533
625
|
if (axis === `x`)
|
|
534
626
|
x_axis = { ...x_axis, ...config };
|
|
627
|
+
else if (axis === `x2`)
|
|
628
|
+
x2_axis = { ...x2_axis, ...config };
|
|
535
629
|
else if (axis === `y`)
|
|
536
630
|
y_axis = { ...y_axis, ...config };
|
|
537
631
|
else
|
|
@@ -569,11 +663,12 @@ $effect(() => {
|
|
|
569
663
|
<ReferenceLine
|
|
570
664
|
ref_line={line}
|
|
571
665
|
line_idx={line.idx}
|
|
572
|
-
x_min={ranges.current.x[0]}
|
|
573
|
-
x_max={ranges.current.x[1]}
|
|
666
|
+
x_min={line.x_axis === `x2` ? ranges.current.x2[0] : ranges.current.x[0]}
|
|
667
|
+
x_max={line.x_axis === `x2` ? ranges.current.x2[1] : ranges.current.x[1]}
|
|
574
668
|
y_min={line.y_axis === `y2` ? ranges.current.y2[0] : ranges.current.y[0]}
|
|
575
669
|
y_max={line.y_axis === `y2` ? ranges.current.y2[1] : ranges.current.y[1]}
|
|
576
670
|
x_scale={scales.x}
|
|
671
|
+
x2_scale={scales.x2}
|
|
577
672
|
y_scale={scales.y}
|
|
578
673
|
y2_scale={scales.y2}
|
|
579
674
|
{clip_path_id}
|
|
@@ -625,6 +720,9 @@ $effect(() => {
|
|
|
625
720
|
<svg
|
|
626
721
|
bind:this={svg_element}
|
|
627
722
|
role="application"
|
|
723
|
+
aria-label={rest[`aria-label`] ??
|
|
724
|
+
([final_x_axis.label, final_y_axis.label].filter(Boolean).join(` vs `) ||
|
|
725
|
+
`Histogram`)}
|
|
628
726
|
tabindex="0"
|
|
629
727
|
onfocusin={() => (is_focused = true)}
|
|
630
728
|
onfocusout={() => (is_focused = false)}
|
|
@@ -670,79 +768,33 @@ $effect(() => {
|
|
|
670
768
|
<!-- Reference lines: below grid (must render first to appear behind grid) -->
|
|
671
769
|
{@render ref_lines_layer(ref_lines_by_z.below_grid)}
|
|
672
770
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
{
|
|
678
|
-
{
|
|
679
|
-
{
|
|
680
|
-
{
|
|
681
|
-
|
|
682
|
-
|
|
771
|
+
<ZoomRect start={drag_state.start} current={drag_state.current} />
|
|
772
|
+
|
|
773
|
+
<ZeroLines
|
|
774
|
+
{display}
|
|
775
|
+
x_scale_fn={scales.x}
|
|
776
|
+
x2_scale_fn={scales.x2}
|
|
777
|
+
y_scale_fn={scales.y}
|
|
778
|
+
y2_scale_fn={scales.y2}
|
|
779
|
+
x_range={ranges.current.x}
|
|
780
|
+
x2_range={ranges.current.x2}
|
|
781
|
+
y_range={ranges.current.y}
|
|
782
|
+
y2_range={ranges.current.y2}
|
|
783
|
+
x_scale_type={final_x_axis.scale_type}
|
|
784
|
+
x2_scale_type={final_x2_axis.scale_type}
|
|
785
|
+
y_scale_type={final_y_axis.scale_type}
|
|
786
|
+
y2_scale_type={final_y2_axis.scale_type}
|
|
787
|
+
has_x2={x2_series.length > 0}
|
|
788
|
+
has_y2={y2_series.length > 0}
|
|
789
|
+
{width}
|
|
790
|
+
{height}
|
|
791
|
+
{pad}
|
|
792
|
+
/>
|
|
683
793
|
|
|
684
794
|
<!-- Reference lines: below lines -->
|
|
685
795
|
{@render ref_lines_layer(ref_lines_by_z.below_lines)}
|
|
686
796
|
|
|
687
|
-
<!--
|
|
688
|
-
{#each histogram_data as
|
|
689
|
-
{ id, bins, color, label, y_scale, y_axis },
|
|
690
|
-
series_idx
|
|
691
|
-
(id ?? series_idx)
|
|
692
|
-
}
|
|
693
|
-
<g class="histogram-series" data-series-idx={series_idx}>
|
|
694
|
-
{#each bins as bin, bin_idx (bin_idx)}
|
|
695
|
-
{@const bar_x = scales.x(bin.x0!)}
|
|
696
|
-
{@const bar_width = Math.max(1, Math.abs(scales.x(bin.x1!) - bar_x))}
|
|
697
|
-
{@const bar_height = Math.max(0, (height - pad.b) - y_scale(bin.length))}
|
|
698
|
-
{@const bar_y = y_scale(bin.length)}
|
|
699
|
-
{@const value = (bin.x0! + bin.x1!) / 2}
|
|
700
|
-
{#if bar_height > 0}
|
|
701
|
-
<path
|
|
702
|
-
d={bar_path(
|
|
703
|
-
bar_x,
|
|
704
|
-
bar_y,
|
|
705
|
-
bar_width,
|
|
706
|
-
bar_height,
|
|
707
|
-
Math.min(final_bar.border_radius ?? 0, bar_width / 2, bar_height / 2),
|
|
708
|
-
)}
|
|
709
|
-
fill={color}
|
|
710
|
-
opacity={final_bar.opacity}
|
|
711
|
-
stroke={final_bar.stroke_color}
|
|
712
|
-
stroke-opacity={final_bar.stroke_opacity}
|
|
713
|
-
stroke-width={final_bar.stroke_width}
|
|
714
|
-
role="button"
|
|
715
|
-
tabindex="0"
|
|
716
|
-
onmousemove={(evt) =>
|
|
717
|
-
handle_mouse_move(
|
|
718
|
-
evt,
|
|
719
|
-
value,
|
|
720
|
-
bin.length,
|
|
721
|
-
label,
|
|
722
|
-
(y_axis ?? `y1`) as `y1` | `y2`,
|
|
723
|
-
series_idx,
|
|
724
|
-
)}
|
|
725
|
-
onmouseleave={() => {
|
|
726
|
-
hover_info = null
|
|
727
|
-
change(null)
|
|
728
|
-
on_bar_hover?.(null)
|
|
729
|
-
}}
|
|
730
|
-
onclick={(event) =>
|
|
731
|
-
on_bar_click?.({ value, count: bin.length, property: label, event })}
|
|
732
|
-
onkeydown={(event: KeyboardEvent) => {
|
|
733
|
-
if ([`Enter`, ` `].includes(event.key)) {
|
|
734
|
-
event.preventDefault()
|
|
735
|
-
on_bar_click?.({ value, count: bin.length, property: label, event })
|
|
736
|
-
}
|
|
737
|
-
}}
|
|
738
|
-
style:cursor={on_bar_click ? `pointer` : undefined}
|
|
739
|
-
/>
|
|
740
|
-
{/if}
|
|
741
|
-
{/each}
|
|
742
|
-
</g>
|
|
743
|
-
{/each}
|
|
744
|
-
|
|
745
|
-
<!-- Reference lines: below points (after bars, before axes/labels) -->
|
|
797
|
+
<!-- Reference lines: below points -->
|
|
746
798
|
{@render ref_lines_layer(ref_lines_by_z.below_points)}
|
|
747
799
|
|
|
748
800
|
<!-- X-axis -->
|
|
@@ -761,7 +813,7 @@ $effect(() => {
|
|
|
761
813
|
{@const inside = final_x_axis.tick?.label?.inside ?? false}
|
|
762
814
|
{@const shift_x = final_x_axis.tick?.label?.shift?.x ?? 0}
|
|
763
815
|
{@const shift_y = final_x_axis.tick?.label?.shift?.y ?? 0}
|
|
764
|
-
{@const base_y = inside ? -8 :
|
|
816
|
+
{@const base_y = inside ? -8 : 8}
|
|
765
817
|
{@const text_y = base_y + shift_y}
|
|
766
818
|
{@const dominant_baseline = inside ? `auto` : `hanging`}
|
|
767
819
|
<g class="tick" transform="translate({tick_x}, {height - pad.b})">
|
|
@@ -793,31 +845,87 @@ $effect(() => {
|
|
|
793
845
|
</g>
|
|
794
846
|
{/each}
|
|
795
847
|
{#if final_x_axis.label || x_axis.options?.length}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
y={height - 10 + (
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
options={x_axis.options}
|
|
809
|
-
selected_key={x_axis.selected_key}
|
|
810
|
-
loading={axis_loading === `x`}
|
|
811
|
-
axis_type="x"
|
|
812
|
-
color={final_x_axis.color}
|
|
813
|
-
on_select={(key) => handle_axis_change(`x`, key)}
|
|
814
|
-
class="axis-label x-label"
|
|
815
|
-
/>
|
|
816
|
-
</div>
|
|
817
|
-
</foreignObject>
|
|
848
|
+
{@const { label_shift, label = ``, options, selected_key, color } = final_x_axis}
|
|
849
|
+
<AxisLabel
|
|
850
|
+
x={(pad.l + width - pad.r) / 2 + (label_shift?.x ?? 0)}
|
|
851
|
+
y={height - 10 + (label_shift?.y ?? 0)}
|
|
852
|
+
{label}
|
|
853
|
+
{options}
|
|
854
|
+
{selected_key}
|
|
855
|
+
loading={axis_loading === `x`}
|
|
856
|
+
axis_type="x"
|
|
857
|
+
{color}
|
|
858
|
+
on_select={(key) => handle_axis_change(`x`, key)}
|
|
859
|
+
/>
|
|
818
860
|
{/if}
|
|
819
861
|
</g>
|
|
820
862
|
|
|
863
|
+
<!-- X2-axis (Top) -->
|
|
864
|
+
{#if x2_series.length > 0}
|
|
865
|
+
<g class="x2-axis">
|
|
866
|
+
<line
|
|
867
|
+
x1={pad.l}
|
|
868
|
+
x2={width - pad.r}
|
|
869
|
+
y1={pad.t}
|
|
870
|
+
y2={pad.t}
|
|
871
|
+
stroke={final_x2_axis.color || `var(--border-color, gray)`}
|
|
872
|
+
stroke-width="1"
|
|
873
|
+
/>
|
|
874
|
+
{#each ticks.x2 as tick (tick)}
|
|
875
|
+
{@const tick_x = scales.x2(tick as number)}
|
|
876
|
+
{@const custom_label = get_tick_label(tick as number, final_x2_axis.ticks)}
|
|
877
|
+
{@const inside = final_x2_axis.tick?.label?.inside ?? false}
|
|
878
|
+
{@const shift_x = final_x2_axis.tick?.label?.shift?.x ?? 0}
|
|
879
|
+
{@const shift_y = final_x2_axis.tick?.label?.shift?.y ?? 0}
|
|
880
|
+
{@const base_y = inside ? 8 : -20}
|
|
881
|
+
{@const text_y = base_y + shift_y}
|
|
882
|
+
{@const dominant_baseline = inside ? `hanging` : `auto`}
|
|
883
|
+
<g class="tick" transform="translate({tick_x}, {pad.t})">
|
|
884
|
+
{#if display.x2_grid}
|
|
885
|
+
<line
|
|
886
|
+
y1="0"
|
|
887
|
+
y2={height - pad.b - pad.t}
|
|
888
|
+
stroke="var(--border-color, gray)"
|
|
889
|
+
stroke-dasharray="4"
|
|
890
|
+
stroke-width="1"
|
|
891
|
+
{...final_x2_axis.grid_style ?? {}}
|
|
892
|
+
/>
|
|
893
|
+
{/if}
|
|
894
|
+
<line
|
|
895
|
+
y1={inside ? 0 : -5}
|
|
896
|
+
y2={inside ? 5 : 0}
|
|
897
|
+
stroke={final_x2_axis.color || `var(--border-color, gray)`}
|
|
898
|
+
stroke-width="1"
|
|
899
|
+
/>
|
|
900
|
+
<text
|
|
901
|
+
x={shift_x}
|
|
902
|
+
y={text_y}
|
|
903
|
+
text-anchor="middle"
|
|
904
|
+
dominant-baseline={dominant_baseline}
|
|
905
|
+
fill={final_x2_axis.color || `var(--text-color)`}
|
|
906
|
+
>
|
|
907
|
+
{custom_label ?? format_value(tick, final_x2_axis.format)}
|
|
908
|
+
</text>
|
|
909
|
+
</g>
|
|
910
|
+
{/each}
|
|
911
|
+
{#if final_x2_axis.label || x2_axis.options?.length}
|
|
912
|
+
{@const { label_shift, label = ``, options, selected_key, color } =
|
|
913
|
+
final_x2_axis}
|
|
914
|
+
<AxisLabel
|
|
915
|
+
x={(pad.l + width - pad.r) / 2 + (label_shift?.x ?? 0)}
|
|
916
|
+
y={Math.max(12, pad.t - (label_shift?.y ?? 40))}
|
|
917
|
+
{label}
|
|
918
|
+
{options}
|
|
919
|
+
{selected_key}
|
|
920
|
+
loading={axis_loading === `x2`}
|
|
921
|
+
axis_type="x2"
|
|
922
|
+
{color}
|
|
923
|
+
on_select={(key) => handle_axis_change(`x2`, key)}
|
|
924
|
+
/>
|
|
925
|
+
{/if}
|
|
926
|
+
</g>
|
|
927
|
+
{/if}
|
|
928
|
+
|
|
821
929
|
<!-- Y-axis -->
|
|
822
930
|
<g class="y-axis">
|
|
823
931
|
<line
|
|
@@ -866,41 +974,25 @@ $effect(() => {
|
|
|
866
974
|
</g>
|
|
867
975
|
{/each}
|
|
868
976
|
{#if final_y_axis.label || y_axis.options?.length}
|
|
869
|
-
{@const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
)
|
|
876
|
-
)
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
style="overflow: visible; pointer-events: none"
|
|
889
|
-
transform="rotate(-90, {y_label_x}, {y_label_y})"
|
|
890
|
-
>
|
|
891
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="pointer-events: auto">
|
|
892
|
-
<InteractiveAxisLabel
|
|
893
|
-
label={final_y_axis.label ?? ``}
|
|
894
|
-
options={y_axis.options}
|
|
895
|
-
selected_key={y_axis.selected_key}
|
|
896
|
-
loading={axis_loading === `y`}
|
|
897
|
-
axis_type="y"
|
|
898
|
-
color={final_y_axis.color}
|
|
899
|
-
on_select={(key) => handle_axis_change(`y`, key)}
|
|
900
|
-
class="axis-label y-label"
|
|
901
|
-
/>
|
|
902
|
-
</div>
|
|
903
|
-
</foreignObject>
|
|
977
|
+
{@const { label_shift, label = ``, options, selected_key, color, tick } =
|
|
978
|
+
final_y_axis}
|
|
979
|
+
{@const y_inside = tick?.label?.inside ?? false}
|
|
980
|
+
<AxisLabel
|
|
981
|
+
x={Math.max(
|
|
982
|
+
12,
|
|
983
|
+
pad.l - (y_inside ? 0 : tick_label_widths.y_max) - LABEL_GAP_DEFAULT,
|
|
984
|
+
) +
|
|
985
|
+
(label_shift?.x ?? 0)}
|
|
986
|
+
y={pad.t + (height - pad.t - pad.b) / 2 + (label_shift?.y ?? 0)}
|
|
987
|
+
rotate
|
|
988
|
+
{label}
|
|
989
|
+
{options}
|
|
990
|
+
{selected_key}
|
|
991
|
+
loading={axis_loading === `y`}
|
|
992
|
+
axis_type="y"
|
|
993
|
+
{color}
|
|
994
|
+
on_select={(key) => handle_axis_change(`y`, key)}
|
|
995
|
+
/>
|
|
904
996
|
{/if}
|
|
905
997
|
</g>
|
|
906
998
|
|
|
@@ -952,80 +1044,86 @@ $effect(() => {
|
|
|
952
1044
|
</g>
|
|
953
1045
|
{/each}
|
|
954
1046
|
{#if final_y2_axis.label || y2_axis.options?.length}
|
|
955
|
-
{@const
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
<foreignObject
|
|
974
|
-
x={y2_label_x - AXIS_LABEL_CONTAINER.x_offset}
|
|
975
|
-
y={y2_label_y - AXIS_LABEL_CONTAINER.y_offset}
|
|
976
|
-
width={AXIS_LABEL_CONTAINER.width}
|
|
977
|
-
height={AXIS_LABEL_CONTAINER.height}
|
|
978
|
-
style="overflow: visible; pointer-events: none"
|
|
979
|
-
transform="rotate(-90, {y2_label_x}, {y2_label_y})"
|
|
980
|
-
>
|
|
981
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="pointer-events: auto">
|
|
982
|
-
<InteractiveAxisLabel
|
|
983
|
-
label={final_y2_axis.label ?? ``}
|
|
984
|
-
options={y2_axis.options}
|
|
985
|
-
selected_key={y2_axis.selected_key}
|
|
986
|
-
loading={axis_loading === `y2`}
|
|
987
|
-
axis_type="y2"
|
|
988
|
-
color={final_y2_axis.color}
|
|
989
|
-
on_select={(key) => handle_axis_change(`y2`, key)}
|
|
990
|
-
class="axis-label y2-label"
|
|
991
|
-
/>
|
|
992
|
-
</div>
|
|
993
|
-
</foreignObject>
|
|
1047
|
+
{@const { label_shift, label = ``, options, selected_key, color, tick } =
|
|
1048
|
+
final_y2_axis}
|
|
1049
|
+
{@const inside = tick?.label?.inside ?? false}
|
|
1050
|
+
{@const tick_shift = inside ? 0 : (tick?.label?.shift?.x ?? 0) + 8}
|
|
1051
|
+
{@const tick_width_contribution = inside ? 0 : tick_label_widths.y2_max}
|
|
1052
|
+
<AxisLabel
|
|
1053
|
+
x={width - pad.r + tick_shift + tick_width_contribution +
|
|
1054
|
+
LABEL_GAP_DEFAULT + (label_shift?.x ?? 0)}
|
|
1055
|
+
y={pad.t + (height - pad.t - pad.b) / 2 + (label_shift?.y ?? 0)}
|
|
1056
|
+
rotate
|
|
1057
|
+
{label}
|
|
1058
|
+
{options}
|
|
1059
|
+
{selected_key}
|
|
1060
|
+
loading={axis_loading === `y2`}
|
|
1061
|
+
axis_type="y2"
|
|
1062
|
+
{color}
|
|
1063
|
+
on_select={(key) => handle_axis_change(`y2`, key)}
|
|
1064
|
+
/>
|
|
994
1065
|
{/if}
|
|
995
1066
|
</g>
|
|
996
1067
|
{/if}
|
|
997
1068
|
|
|
998
|
-
<!--
|
|
999
|
-
{#
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1069
|
+
<!-- Histogram bars (rendered after axes so bars appear above grid lines) -->
|
|
1070
|
+
{#each histogram_data as
|
|
1071
|
+
{ id, bins, color, label, x_scale, y_scale, x_axis: srs_x_axis, y_axis },
|
|
1072
|
+
series_idx
|
|
1073
|
+
(id ?? series_idx)
|
|
1074
|
+
}
|
|
1075
|
+
<g class="histogram-series" data-series-idx={series_idx}>
|
|
1076
|
+
{#each bins as bin, bin_idx (bin_idx)}
|
|
1077
|
+
{@const bar_x = x_scale(bin.x0!)}
|
|
1078
|
+
{@const bar_width = Math.max(1, Math.abs(x_scale(bin.x1!) - bar_x))}
|
|
1079
|
+
{@const bar_height = Math.max(0, (height - pad.b) - y_scale(bin.length))}
|
|
1080
|
+
{@const bar_y = y_scale(bin.length)}
|
|
1081
|
+
{@const value = (bin.x0! + bin.x1!) / 2}
|
|
1082
|
+
{#if bar_height > 0}
|
|
1083
|
+
<path
|
|
1084
|
+
d={bar_path(
|
|
1085
|
+
bar_x,
|
|
1086
|
+
bar_y,
|
|
1087
|
+
bar_width,
|
|
1088
|
+
bar_height,
|
|
1089
|
+
Math.min(final_bar.border_radius ?? 0, bar_width / 2, bar_height / 2),
|
|
1090
|
+
)}
|
|
1091
|
+
fill={color}
|
|
1092
|
+
opacity={final_bar.opacity}
|
|
1093
|
+
stroke={final_bar.stroke_color}
|
|
1094
|
+
stroke-opacity={final_bar.stroke_opacity}
|
|
1095
|
+
stroke-width={final_bar.stroke_width}
|
|
1096
|
+
role="button"
|
|
1097
|
+
tabindex="0"
|
|
1098
|
+
onmousemove={(evt) =>
|
|
1099
|
+
handle_mouse_move(
|
|
1100
|
+
evt,
|
|
1101
|
+
value,
|
|
1102
|
+
bin.length,
|
|
1103
|
+
label,
|
|
1104
|
+
(y_axis ?? `y1`) as `y1` | `y2`,
|
|
1105
|
+
series_idx,
|
|
1106
|
+
(srs_x_axis ?? `x1`) as `x1` | `x2`,
|
|
1107
|
+
)}
|
|
1108
|
+
onmouseleave={() => {
|
|
1109
|
+
hover_info = null
|
|
1110
|
+
change(null)
|
|
1111
|
+
on_bar_hover?.(null)
|
|
1112
|
+
}}
|
|
1113
|
+
onclick={(event) =>
|
|
1114
|
+
on_bar_click?.({ value, count: bin.length, property: label, event })}
|
|
1115
|
+
onkeydown={(event: KeyboardEvent) => {
|
|
1116
|
+
if ([`Enter`, ` `].includes(event.key)) {
|
|
1117
|
+
event.preventDefault()
|
|
1118
|
+
on_bar_click?.({ value, count: bin.length, property: label, event })
|
|
1119
|
+
}
|
|
1120
|
+
}}
|
|
1121
|
+
style:cursor={on_bar_click ? `pointer` : undefined}
|
|
1122
|
+
/>
|
|
1123
|
+
{/if}
|
|
1124
|
+
{/each}
|
|
1125
|
+
</g>
|
|
1126
|
+
{/each}
|
|
1029
1127
|
|
|
1030
1128
|
<!-- Reference lines: above all -->
|
|
1031
1129
|
{@render ref_lines_layer(ref_lines_by_z.above_all)}
|
|
@@ -1033,8 +1131,8 @@ $effect(() => {
|
|
|
1033
1131
|
|
|
1034
1132
|
<!-- Tooltip (outside SVG for proper HTML rendering) -->
|
|
1035
1133
|
{#if hover_info}
|
|
1036
|
-
{@const { value, count, property, active_y_axis } = hover_info}
|
|
1037
|
-
{@const tooltip_x = scales.x(value)}
|
|
1134
|
+
{@const { value, count, property, active_y_axis, active_x_axis } = hover_info}
|
|
1135
|
+
{@const tooltip_x = (active_x_axis === `x2` ? scales.x2 : scales.x)(value)}
|
|
1038
1136
|
{@const tooltip_y = (active_y_axis === `y2` ? scales.y2 : scales.y)(count)}
|
|
1039
1137
|
{@const tooltip_pos = constrain_tooltip_position(
|
|
1040
1138
|
tooltip_x,
|
|
@@ -1045,7 +1143,6 @@ $effect(() => {
|
|
|
1045
1143
|
height,
|
|
1046
1144
|
{ offset_x: 5, offset_y: -10 },
|
|
1047
1145
|
)}
|
|
1048
|
-
{@const active_y_config = active_y_axis === `y2` ? final_y2_axis : final_y_axis}
|
|
1049
1146
|
<PlotTooltip
|
|
1050
1147
|
x={tooltip_pos.x}
|
|
1051
1148
|
y={tooltip_pos.y}
|
|
@@ -1055,8 +1152,8 @@ $effect(() => {
|
|
|
1055
1152
|
{#if tooltip}
|
|
1056
1153
|
{@render tooltip({ ...hover_info, fullscreen })}
|
|
1057
1154
|
{:else}
|
|
1058
|
-
<div>Value: {format_value(value,
|
|
1059
|
-
<div>Count: {format_value(count,
|
|
1155
|
+
<div>Value: {format_value(value, hover_info.x_axis.format || `.3~s`)}</div>
|
|
1156
|
+
<div>Count: {format_value(count, hover_info.y_axis.format || `.3~s`)}</div>
|
|
1060
1157
|
{#if mode === `overlay`}<div>{property}</div>{/if}
|
|
1061
1158
|
{/if}
|
|
1062
1159
|
</PlotTooltip>
|
|
@@ -1066,7 +1163,7 @@ $effect(() => {
|
|
|
1066
1163
|
<HistogramControls
|
|
1067
1164
|
toggle_props={{
|
|
1068
1165
|
...controls_toggle_props,
|
|
1069
|
-
style: `--ctrl-btn-right: var(--fullscreen-btn-offset,
|
|
1166
|
+
style: `--ctrl-btn-right: var(--fullscreen-btn-offset, 30px); ${
|
|
1070
1167
|
controls_toggle_props?.style ?? ``
|
|
1071
1168
|
}`,
|
|
1072
1169
|
}}
|
|
@@ -1080,12 +1177,16 @@ $effect(() => {
|
|
|
1080
1177
|
bind:display
|
|
1081
1178
|
bind:bar
|
|
1082
1179
|
bind:x_axis
|
|
1180
|
+
bind:x2_axis
|
|
1083
1181
|
bind:y_axis
|
|
1084
1182
|
bind:y2_axis
|
|
1085
1183
|
auto_x_range={auto_ranges.x}
|
|
1184
|
+
auto_x2_range={auto_ranges.x2}
|
|
1086
1185
|
auto_y_range={auto_ranges.y}
|
|
1087
1186
|
auto_y2_range={auto_ranges.y2}
|
|
1088
1187
|
{series}
|
|
1188
|
+
has_x2_points={x2_series.length > 0}
|
|
1189
|
+
has_y2_points={y2_series.length > 0}
|
|
1089
1190
|
children={controls_extra}
|
|
1090
1191
|
/>
|
|
1091
1192
|
{/if}
|
|
@@ -1178,7 +1279,7 @@ $effect(() => {
|
|
|
1178
1279
|
font-weight: var(--histogram-font-weight);
|
|
1179
1280
|
font-size: var(--histogram-font-size);
|
|
1180
1281
|
}
|
|
1181
|
-
g:is(.x-axis, .y-axis, .y2-axis) .tick text {
|
|
1282
|
+
g:is(.x-axis, .x2-axis, .y-axis, .y2-axis) .tick text {
|
|
1182
1283
|
font-size: var(--tick-font-size, 0.8em); /* shrink tick labels */
|
|
1183
1284
|
}
|
|
1184
1285
|
.histogram-series path {
|
|
@@ -1187,15 +1288,4 @@ $effect(() => {
|
|
|
1187
1288
|
.histogram-series path:hover {
|
|
1188
1289
|
opacity: 1 !important;
|
|
1189
1290
|
}
|
|
1190
|
-
.zoom-rect {
|
|
1191
|
-
fill: var(--histogram-zoom-rect-fill, rgba(100, 100, 255, 0.2));
|
|
1192
|
-
stroke: var(--histogram-zoom-rect-stroke, rgba(100, 100, 255, 0.8));
|
|
1193
|
-
stroke-width: var(--histogram-zoom-rect-stroke-width, 1);
|
|
1194
|
-
pointer-events: none;
|
|
1195
|
-
}
|
|
1196
|
-
.zero-line {
|
|
1197
|
-
stroke: var(--histogram-zero-line-color, light-dark(black, white));
|
|
1198
|
-
stroke-width: var(--histogram-zero-line-width, 1);
|
|
1199
|
-
opacity: var(--histogram-zero-line-opacity);
|
|
1200
|
-
}
|
|
1201
1291
|
</style>
|