matterviz 0.1.12 → 0.1.13
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/ContextMenu.svelte +1 -1
- package/dist/ContextMenu.svelte.d.ts +3 -3
- package/dist/DraggablePane.svelte +10 -5
- package/dist/DraggablePane.svelte.d.ts +3 -3
- package/dist/FilePicker.svelte.d.ts +3 -3
- package/dist/Icon.svelte.d.ts +3 -3
- package/dist/Nav.svelte +76 -31
- package/dist/SettingsSection.svelte.d.ts +3 -3
- package/dist/Spinner.svelte +18 -29
- package/dist/Spinner.svelte.d.ts +3 -3
- package/dist/app.css +4 -0
- package/dist/bands/Bands.svelte +216 -0
- package/dist/bands/Bands.svelte.d.ts +16 -0
- package/dist/bands/BandsAndDos.svelte +26 -0
- package/dist/bands/BandsAndDos.svelte.d.ts +16 -0
- package/dist/bands/Dos.svelte +124 -0
- package/dist/bands/Dos.svelte.d.ts +18 -0
- package/dist/bands/helpers.d.ts +11 -0
- package/dist/bands/helpers.js +195 -0
- package/dist/bands/index.d.ts +5 -0
- package/dist/bands/index.js +6 -0
- package/dist/bands/types.d.ts +54 -0
- package/dist/bands/types.js +2 -0
- package/dist/brillouin/BrillouinZone.svelte +373 -0
- package/dist/brillouin/BrillouinZone.svelte.d.ts +57 -0
- package/dist/brillouin/BrillouinZoneControls.svelte +88 -0
- package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +14 -0
- package/dist/brillouin/BrillouinZoneExportPane.svelte +129 -0
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +15 -0
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +115 -0
- package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +13 -0
- package/dist/brillouin/BrillouinZoneScene.svelte +180 -0
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +34 -0
- package/dist/brillouin/compute.d.ts +7 -0
- package/dist/brillouin/compute.js +215 -0
- package/dist/brillouin/index.d.ts +7 -0
- package/dist/brillouin/index.js +7 -0
- package/dist/brillouin/types.d.ts +23 -0
- package/dist/brillouin/types.js +1 -0
- package/dist/composition/BarChart.svelte.d.ts +3 -3
- package/dist/composition/BubbleChart.svelte +7 -6
- package/dist/composition/BubbleChart.svelte.d.ts +3 -3
- package/dist/composition/Composition.svelte.d.ts +3 -3
- package/dist/composition/PieChart.svelte +1 -1
- package/dist/composition/PieChart.svelte.d.ts +3 -3
- package/dist/composition/parse.d.ts +3 -3
- package/dist/coordination/CoordinationBarPlot.svelte +241 -0
- package/dist/coordination/CoordinationBarPlot.svelte.d.ts +29 -0
- package/dist/coordination/calc-coordination.d.ts +15 -0
- package/dist/coordination/calc-coordination.js +66 -0
- package/dist/coordination/index.d.ts +8 -0
- package/dist/coordination/index.js +7 -0
- package/dist/element/BohrAtom.svelte.d.ts +3 -3
- package/dist/element/ElementHeading.svelte.d.ts +3 -3
- package/dist/element/ElementPhoto.svelte.d.ts +3 -3
- package/dist/element/ElementStats.svelte.d.ts +3 -3
- package/dist/element/ElementTile.svelte +1 -1
- package/dist/element/ElementTile.svelte.d.ts +4 -4
- package/dist/element/Nucleus.svelte.d.ts +3 -3
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +4 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/io/export.d.ts +1 -6
- package/dist/io/export.js +12 -12
- package/dist/labels.d.ts +19 -0
- package/dist/labels.js +59 -0
- package/dist/math.d.ts +7 -2
- package/dist/math.js +24 -12
- package/dist/periodic-table/PeriodicTable.svelte.d.ts +3 -3
- package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +3 -3
- package/dist/periodic-table/PropertySelect.svelte +1 -1
- package/dist/periodic-table/PropertySelect.svelte.d.ts +5 -4
- package/dist/periodic-table/TableInset.svelte.d.ts +3 -3
- package/dist/phase-diagram/PhaseDiagram2D.svelte +44 -107
- package/dist/phase-diagram/PhaseDiagram2D.svelte.d.ts +7 -27
- package/dist/phase-diagram/PhaseDiagram3D.svelte +67 -170
- package/dist/phase-diagram/PhaseDiagram3D.svelte.d.ts +7 -31
- package/dist/phase-diagram/PhaseDiagram4D.svelte +87 -145
- package/dist/phase-diagram/PhaseDiagram4D.svelte.d.ts +5 -28
- package/dist/phase-diagram/PhaseDiagramControls.svelte +9 -9
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +6 -6
- package/dist/phase-diagram/PhaseDiagramInfoPane.svelte +4 -4
- package/dist/phase-diagram/PhaseDiagramInfoPane.svelte.d.ts +5 -5
- package/dist/phase-diagram/PhaseDiagramStats.svelte +9 -16
- package/dist/phase-diagram/PhaseDiagramStats.svelte.d.ts +3 -3
- package/dist/phase-diagram/StructurePopup.svelte.d.ts +3 -3
- package/dist/phase-diagram/barycentric-coords.js +13 -24
- package/dist/phase-diagram/helpers.d.ts +12 -14
- package/dist/phase-diagram/helpers.js +70 -23
- package/dist/phase-diagram/index.d.ts +58 -0
- package/dist/phase-diagram/index.js +44 -0
- package/dist/phase-diagram/thermodynamics.js +2 -3
- package/dist/phase-diagram/types.d.ts +3 -8
- package/dist/plot/BarPlot.svelte +474 -240
- package/dist/plot/BarPlot.svelte.d.ts +16 -37
- package/dist/plot/BarPlotControls.svelte +33 -201
- package/dist/plot/BarPlotControls.svelte.d.ts +11 -22
- package/dist/plot/ColorBar.svelte.d.ts +3 -3
- package/dist/plot/ColorScaleSelect.svelte +1 -1
- package/dist/plot/ColorScaleSelect.svelte.d.ts +3 -3
- package/dist/plot/ElementScatter.svelte +5 -5
- package/dist/plot/ElementScatter.svelte.d.ts +8 -8
- package/dist/plot/Histogram.svelte +318 -170
- package/dist/plot/Histogram.svelte.d.ts +21 -41
- package/dist/plot/HistogramControls.svelte +115 -347
- package/dist/plot/HistogramControls.svelte.d.ts +13 -28
- package/dist/plot/Line.svelte +1 -1
- package/dist/plot/Line.svelte.d.ts +4 -4
- package/dist/plot/PlotControls.svelte +280 -0
- package/dist/plot/PlotControls.svelte.d.ts +4 -0
- package/dist/plot/PlotLegend.svelte +9 -24
- package/dist/plot/PlotLegend.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot.svelte +536 -571
- package/dist/plot/ScatterPlot.svelte.d.ts +18 -90
- package/dist/plot/ScatterPlotControls.svelte +108 -316
- package/dist/plot/ScatterPlotControls.svelte.d.ts +11 -38
- package/dist/plot/ScatterPoint.svelte +1 -1
- package/dist/plot/ScatterPoint.svelte.d.ts +5 -5
- package/dist/plot/SpacegroupBarPlot.svelte +235 -0
- package/dist/plot/SpacegroupBarPlot.svelte.d.ts +9 -0
- package/dist/plot/data-transform.d.ts +2 -2
- package/dist/plot/data-transform.js +1 -5
- package/dist/plot/index.d.ts +12 -200
- package/dist/plot/index.js +14 -6
- package/dist/plot/layout.d.ts +10 -16
- package/dist/plot/layout.js +40 -25
- package/dist/plot/scales.d.ts +7 -8
- package/dist/plot/scales.js +22 -7
- package/dist/plot/types.d.ts +303 -0
- package/dist/plot/types.js +1 -0
- package/dist/rdf/RdfPlot.svelte +156 -0
- package/dist/rdf/RdfPlot.svelte.d.ts +20 -0
- package/dist/rdf/calc-rdf.d.ts +4 -0
- package/dist/rdf/calc-rdf.js +107 -0
- package/dist/rdf/index.d.ts +22 -0
- package/dist/rdf/index.js +2 -0
- package/dist/settings.d.ts +86 -75
- package/dist/settings.js +257 -155
- package/dist/structure/Bond.svelte +126 -110
- package/dist/structure/Bond.svelte.d.ts +7 -20
- package/dist/structure/CanvasTooltip.svelte.d.ts +4 -4
- package/dist/structure/Cylinder.svelte +29 -0
- package/dist/structure/Cylinder.svelte.d.ts +10 -0
- package/dist/structure/Lattice.svelte +1 -2
- package/dist/structure/Lattice.svelte.d.ts +3 -3
- package/dist/structure/Structure.svelte +23 -8
- package/dist/structure/Structure.svelte.d.ts +10 -7
- package/dist/structure/StructureControls.svelte +25 -134
- package/dist/structure/StructureControls.svelte.d.ts +4 -9
- package/dist/structure/StructureExportPane.svelte +188 -0
- package/dist/structure/StructureExportPane.svelte.d.ts +17 -0
- package/dist/structure/StructureInfoPane.svelte.d.ts +3 -3
- package/dist/structure/StructureLegend.svelte +91 -27
- package/dist/structure/StructureLegend.svelte.d.ts +5 -4
- package/dist/structure/StructureScene.svelte +93 -100
- package/dist/structure/StructureScene.svelte.d.ts +15 -12
- package/dist/structure/Vector.svelte +19 -25
- package/dist/structure/Vector.svelte.d.ts +3 -3
- package/dist/structure/bonding.d.ts +16 -14
- package/dist/structure/bonding.js +207 -216
- package/dist/structure/export.d.ts +3 -0
- package/dist/structure/export.js +120 -0
- package/dist/structure/index.d.ts +15 -1
- package/dist/structure/index.js +2 -0
- package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -3
- package/dist/symmetry/index.d.ts +1 -0
- package/dist/symmetry/index.js +1 -0
- package/dist/symmetry/spacegroups.d.ts +9 -0
- package/dist/symmetry/spacegroups.js +397 -0
- package/dist/theme/ThemeControl.svelte.d.ts +3 -3
- package/dist/theme/themes.js +2 -16
- package/dist/trajectory/Trajectory.svelte +52 -78
- package/dist/trajectory/Trajectory.svelte.d.ts +5 -5
- package/dist/trajectory/TrajectoryError.svelte.d.ts +3 -3
- package/dist/trajectory/TrajectoryExportPane.svelte +1 -1
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +5 -5
- package/dist/trajectory/TrajectoryInfoPane.svelte +1 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -3
- package/dist/trajectory/extract.js +2 -1
- package/dist/trajectory/index.d.ts +1 -1
- package/dist/trajectory/index.js +1 -1
- package/dist/trajectory/parse.js +21 -14
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +17 -0
- package/dist/xrd/XrdPlot.svelte +14 -11
- package/dist/xrd/XrdPlot.svelte.d.ts +6 -5
- package/package.json +20 -12
- package/readme.md +1 -1
- package/dist/material/MaterialCard.svelte +0 -123
- package/dist/material/MaterialCard.svelte.d.ts +0 -9
- package/dist/material/index.d.ts +0 -1
- package/dist/material/index.js +0 -1
- package/dist/plot/formatting.d.ts +0 -7
- package/dist/plot/formatting.js +0 -53
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
1
|
+
<script lang="ts">import { format_value } from '../labels';
|
|
2
2
|
import { find_best_plot_area, HistogramControls, PlotLegend } from './';
|
|
3
|
+
import { DEFAULTS } from '../settings';
|
|
3
4
|
import { bin, max } from 'd3-array';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { untrack } from 'svelte';
|
|
6
|
+
import { extract_series_color, prepare_legend_data } from './data-transform';
|
|
6
7
|
import { get_relative_coords } from './interactions';
|
|
7
8
|
import { calc_auto_padding, constrain_tooltip_position } from './layout';
|
|
8
|
-
import { create_scale, generate_ticks, get_nice_data_range } from './scales';
|
|
9
|
-
let { series = $bindable([]),
|
|
9
|
+
import { create_scale, generate_ticks, get_nice_data_range, get_tick_label, } from './scales';
|
|
10
|
+
let { series = $bindable([]), x_axis = $bindable({ label: `Value`, format: `.2~s`, scale_type: `linear` }), y_axis = $bindable({ label: `Count`, format: `d`, scale_type: `linear` }), y2_axis = $bindable({ label: `Count`, format: `d`, scale_type: `linear` }), display = $bindable(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 = { series_data: [] }, bar = $bindable({}), selected_property = $bindable(``), mode = $bindable(`single`), tooltip, hovered = $bindable(false), change = () => { }, on_bar_click, on_bar_hover, show_controls = $bindable(true), controls_open = $bindable(false), on_series_toggle = () => { }, controls_toggle_props, controls_pane_props, children, ...rest } = $props();
|
|
11
|
+
bar = { ...DEFAULTS.histogram.bar, ...bar }; // Initialize bar style defaults
|
|
12
|
+
y2_axis = {
|
|
13
|
+
format: `d`,
|
|
14
|
+
scale_type: `linear`,
|
|
15
|
+
ticks: 5,
|
|
16
|
+
label_shift: { y: 60 },
|
|
17
|
+
tick_label_shift: { x: 8, y: 0 },
|
|
18
|
+
range: [null, null],
|
|
19
|
+
...y2_axis,
|
|
20
|
+
};
|
|
10
21
|
// Core state
|
|
11
22
|
let [width, height] = $state([0, 0]);
|
|
12
23
|
let svg_element = $state(null);
|
|
@@ -14,63 +25,93 @@ let hover_info = $state(null);
|
|
|
14
25
|
let drag_state = $state({ start: null, current: null, bounds: null });
|
|
15
26
|
// Derived data
|
|
16
27
|
let selected_series = $derived(mode === `single` && selected_property
|
|
17
|
-
?
|
|
18
|
-
:
|
|
28
|
+
? series.filter((srs) => (srs.visible ?? true) && srs.label === selected_property)
|
|
29
|
+
: series.filter((srs) => srs.visible ?? true));
|
|
30
|
+
// Separate series by y-axis
|
|
31
|
+
let y1_series = $derived(selected_series.filter((srs) => (srs.y_axis ?? `y1`) === `y1`));
|
|
32
|
+
let y2_series = $derived(selected_series.filter((srs) => srs.y_axis === `y2`));
|
|
19
33
|
let auto_ranges = $derived.by(() => {
|
|
20
34
|
const all_values = selected_series.flatMap((s) => s.y);
|
|
21
|
-
const auto_x = get_nice_data_range(all_values.map((val) => ({ x: val, y: 0 })), (p) => p.x,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
const auto_x = get_nice_data_range(all_values.map((val) => ({ x: val, y: 0 })), (p) => p.x, x_range, x_axis.scale_type ?? `linear`, range_padding, false);
|
|
36
|
+
// Calculate y-range for a specific set of series
|
|
37
|
+
const calc_y_range = (series_list, y_limit, scale_type) => {
|
|
38
|
+
if (!series_list.length) {
|
|
39
|
+
const fallback = scale_type === `log` ? 1 : 0;
|
|
40
|
+
return [fallback, 1];
|
|
41
|
+
}
|
|
42
|
+
const hist = bin().domain([auto_x[0], auto_x[1]]).thresholds(bins);
|
|
43
|
+
const max_count = Math.max(0, ...series_list.map((s) => max(hist(s.y), (d) => d.length) || 0));
|
|
44
|
+
const [y0, y1] = get_nice_data_range([{ x: 0, y: 0 }, { x: max_count, y: 0 }], (p) => p.x, y_limit, scale_type, range_padding, false);
|
|
45
|
+
const y_min = scale_type === `log` ? Math.max(1, y0) : Math.max(0, y0);
|
|
46
|
+
return [y_min, y1];
|
|
47
|
+
};
|
|
48
|
+
const y1_range = calc_y_range(y1_series, y_range, y_axis.scale_type ?? `linear`);
|
|
49
|
+
const y2_auto_range = calc_y_range(y2_series, y2_range, y2_axis.scale_type ?? `linear`);
|
|
50
|
+
return { x: auto_x, y: y1_range, y2: y2_auto_range };
|
|
33
51
|
});
|
|
34
52
|
// Initialize ranges
|
|
35
53
|
let ranges = $state({
|
|
36
|
-
initial: {
|
|
37
|
-
|
|
54
|
+
initial: {
|
|
55
|
+
x: [0, 1],
|
|
56
|
+
y: [0, 1],
|
|
57
|
+
y2: [0, 1],
|
|
58
|
+
},
|
|
59
|
+
current: {
|
|
60
|
+
x: [0, 1],
|
|
61
|
+
y: [0, 1],
|
|
62
|
+
y2: [0, 1],
|
|
63
|
+
},
|
|
38
64
|
});
|
|
39
65
|
$effect(() => {
|
|
40
66
|
// Support one-sided range pinning: merge user range with auto range for null values
|
|
41
|
-
const new_x =
|
|
42
|
-
? [
|
|
67
|
+
const new_x = x_axis.range
|
|
68
|
+
? [x_axis.range[0] ?? auto_ranges.x[0], x_axis.range[1] ?? auto_ranges.x[1]]
|
|
43
69
|
: auto_ranges.x;
|
|
44
|
-
const new_y =
|
|
45
|
-
? [
|
|
70
|
+
const new_y = y_axis.range
|
|
71
|
+
? [y_axis.range[0] ?? auto_ranges.y[0], y_axis.range[1] ?? auto_ranges.y[1]]
|
|
46
72
|
: auto_ranges.y;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
73
|
+
const new_y2 = y2_axis.range
|
|
74
|
+
? [y2_axis.range[0] ?? auto_ranges.y2[0], y2_axis.range[1] ?? auto_ranges.y2[1]]
|
|
75
|
+
: auto_ranges.y2;
|
|
76
|
+
// Only update if values changed (prevent infinite loop)
|
|
77
|
+
const x_changed = new_x[0] !== ranges.current.x[0] ||
|
|
78
|
+
new_x[1] !== ranges.current.x[1];
|
|
79
|
+
const y_changed = new_y[0] !== ranges.current.y[0] ||
|
|
80
|
+
new_y[1] !== ranges.current.y[1];
|
|
81
|
+
const y2_changed = new_y2[0] !== ranges.current.y2[0] ||
|
|
82
|
+
new_y2[1] !== ranges.current.y2[1];
|
|
51
83
|
if (x_changed)
|
|
52
84
|
[ranges.initial.x, ranges.current.x] = [new_x, new_x];
|
|
53
85
|
if (y_changed)
|
|
54
86
|
[ranges.initial.y, ranges.current.y] = [new_y, new_y];
|
|
87
|
+
if (y2_changed)
|
|
88
|
+
[ranges.initial.y2, ranges.current.y2] = [new_y2, new_y2];
|
|
55
89
|
});
|
|
56
90
|
// Layout: dynamic padding based on tick label widths
|
|
57
91
|
const default_padding = { t: 20, b: 60, l: 60, r: 20 };
|
|
58
92
|
let pad = $state({ ...default_padding, ...padding });
|
|
59
|
-
// Update padding
|
|
93
|
+
// Update padding based on tick label widths (untrack breaks circular dependency)
|
|
60
94
|
$effect(() => {
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
const current_ticks_y = untrack(() => ticks.y);
|
|
96
|
+
const current_ticks_y2 = untrack(() => ticks.y2);
|
|
97
|
+
const new_pad = width && height && current_ticks_y.length
|
|
98
|
+
? calc_auto_padding({
|
|
99
|
+
padding,
|
|
100
|
+
default_padding,
|
|
101
|
+
y_axis: { ...y_axis, tick_values: current_ticks_y },
|
|
102
|
+
y2_axis: { ...y2_axis, tick_values: current_ticks_y2 },
|
|
103
|
+
})
|
|
104
|
+
: { ...default_padding, ...padding };
|
|
105
|
+
// Only update if padding actually changed
|
|
66
106
|
if (pad.t !== new_pad.t || pad.b !== new_pad.b || pad.l !== new_pad.l ||
|
|
67
107
|
pad.r !== new_pad.r)
|
|
68
108
|
pad = new_pad;
|
|
69
109
|
});
|
|
70
110
|
// Scales and data
|
|
71
111
|
let scales = $derived({
|
|
72
|
-
x: create_scale(
|
|
73
|
-
y: create_scale(
|
|
112
|
+
x: create_scale(x_axis.scale_type ?? `linear`, ranges.current.x, [pad.l, width - pad.r]),
|
|
113
|
+
y: create_scale(y_axis.scale_type ?? `linear`, ranges.current.y, [height - pad.b, pad.t]),
|
|
114
|
+
y2: create_scale(y2_axis.scale_type ?? `linear`, ranges.current.y2, [height - pad.b, pad.t]),
|
|
74
115
|
});
|
|
75
116
|
let histogram_data = $derived.by(() => {
|
|
76
117
|
if (!selected_series.length || !width || !height)
|
|
@@ -80,27 +121,30 @@ let histogram_data = $derived.by(() => {
|
|
|
80
121
|
.thresholds(bins);
|
|
81
122
|
return selected_series.map((series_data, series_idx) => {
|
|
82
123
|
const bins_arr = hist_generator(series_data.y);
|
|
124
|
+
const use_y2 = series_data.y_axis === `y2`;
|
|
83
125
|
return {
|
|
126
|
+
id: series_data.id ?? series_idx,
|
|
84
127
|
series_idx,
|
|
85
128
|
label: series_data.label || `Series ${series_idx + 1}`,
|
|
86
129
|
color: selected_series.length === 1
|
|
87
|
-
?
|
|
130
|
+
? bar.color
|
|
88
131
|
: extract_series_color(series_data),
|
|
89
132
|
bins: bins_arr,
|
|
90
133
|
max_count: max(bins_arr, (d) => d.length) || 0,
|
|
134
|
+
y_axis: series_data.y_axis,
|
|
135
|
+
y_scale: use_y2 ? scales.y2 : scales.y,
|
|
91
136
|
};
|
|
92
137
|
});
|
|
93
138
|
});
|
|
94
139
|
let ticks = $derived({
|
|
95
140
|
x: width && height
|
|
96
|
-
? generate_ticks(ranges.current.x,
|
|
97
|
-
default_count: 8,
|
|
98
|
-
})
|
|
141
|
+
? generate_ticks(ranges.current.x, x_axis.scale_type ?? `linear`, x_axis.ticks, scales.x, { default_count: 8 })
|
|
99
142
|
: [],
|
|
100
143
|
y: width && height
|
|
101
|
-
? generate_ticks(ranges.current.y,
|
|
102
|
-
|
|
103
|
-
|
|
144
|
+
? generate_ticks(ranges.current.y, y_axis.scale_type ?? `linear`, y_axis.ticks, scales.y, { default_count: 6 })
|
|
145
|
+
: [],
|
|
146
|
+
y2: width && height && y2_series.length > 0
|
|
147
|
+
? generate_ticks(ranges.current.y2, y2_axis.scale_type ?? `linear`, y2_axis.ticks, scales.y2, { default_count: 6 })
|
|
104
148
|
: [],
|
|
105
149
|
});
|
|
106
150
|
let legend_data = $derived(prepare_legend_data(series));
|
|
@@ -109,11 +153,11 @@ let hist_points_for_placement = $derived.by(() => {
|
|
|
109
153
|
if (!width || !height || !histogram_data.length)
|
|
110
154
|
return [];
|
|
111
155
|
const points = [];
|
|
112
|
-
for (const { bins } of histogram_data) {
|
|
156
|
+
for (const { bins, y_scale } of histogram_data) {
|
|
113
157
|
for (const bin of bins) {
|
|
114
158
|
if (bin.length > 0) {
|
|
115
159
|
const bar_x = scales.x((bin.x0 + bin.x1) / 2);
|
|
116
|
-
const bar_y =
|
|
160
|
+
const bar_y = y_scale(bin.length);
|
|
117
161
|
if (isFinite(bar_x) && isFinite(bar_y)) {
|
|
118
162
|
// Add multiple points for taller bars to increase their weight
|
|
119
163
|
const weight = Math.ceil(bin.length / 10); // More points for taller bars
|
|
@@ -146,12 +190,25 @@ const handle_zoom = () => {
|
|
|
146
190
|
const end_x = scales.x.invert(drag_state.current.x);
|
|
147
191
|
const start_y = scales.y.invert(drag_state.start.y);
|
|
148
192
|
const end_y = scales.y.invert(drag_state.current.y);
|
|
193
|
+
const start_y2 = scales.y2.invert(drag_state.start.y);
|
|
194
|
+
const end_y2 = scales.y2.invert(drag_state.current.y);
|
|
149
195
|
if (typeof start_x === `number` && typeof end_x === `number`) {
|
|
150
196
|
const dx = Math.abs(drag_state.start.x - drag_state.current.x);
|
|
151
197
|
const dy = Math.abs(drag_state.start.y - drag_state.current.y);
|
|
152
198
|
if (dx > 5 && dy > 5) {
|
|
153
|
-
ranges
|
|
154
|
-
|
|
199
|
+
// Update axis ranges to trigger reactivity and prevent effect from overriding
|
|
200
|
+
x_axis = {
|
|
201
|
+
...x_axis,
|
|
202
|
+
range: [Math.min(start_x, end_x), Math.max(start_x, end_x)],
|
|
203
|
+
};
|
|
204
|
+
y_axis = {
|
|
205
|
+
...y_axis,
|
|
206
|
+
range: [Math.min(start_y, end_y), Math.max(start_y, end_y)],
|
|
207
|
+
};
|
|
208
|
+
y2_axis = {
|
|
209
|
+
...y2_axis,
|
|
210
|
+
range: [Math.min(start_y2, end_y2), Math.max(start_y2, end_y2)],
|
|
211
|
+
};
|
|
155
212
|
}
|
|
156
213
|
}
|
|
157
214
|
};
|
|
@@ -184,11 +241,14 @@ function handle_mouse_down(evt) {
|
|
|
184
241
|
evt.preventDefault();
|
|
185
242
|
}
|
|
186
243
|
function handle_double_click() {
|
|
187
|
-
ranges
|
|
244
|
+
// Clear axis ranges to reset to auto ranges
|
|
245
|
+
x_axis = { ...x_axis, range: undefined };
|
|
246
|
+
y_axis = { ...y_axis, range: undefined };
|
|
247
|
+
y2_axis = { ...y2_axis, range: undefined };
|
|
188
248
|
}
|
|
189
|
-
function handle_mouse_move(evt, value, count, property) {
|
|
249
|
+
function handle_mouse_move(evt, value, count, property, axis = `y1`) {
|
|
190
250
|
hovered = true;
|
|
191
|
-
hover_info = { value, count, property };
|
|
251
|
+
hover_info = { value, count, property, axis };
|
|
192
252
|
change({ value, count, property });
|
|
193
253
|
on_bar_hover?.({ value, count, property, event: evt });
|
|
194
254
|
}
|
|
@@ -231,83 +291,13 @@ function toggle_series_visibility(series_idx) {
|
|
|
231
291
|
}
|
|
232
292
|
}}
|
|
233
293
|
>
|
|
234
|
-
<!-- Zero lines -->
|
|
235
|
-
{#if show_zero_lines}
|
|
236
|
-
{#if ranges.current.x[0] <= 0 && ranges.current.x[1] >= 0}
|
|
237
|
-
{@const zero_x = scales.x(0)}
|
|
238
|
-
{#if isFinite(zero_x)}
|
|
239
|
-
<line
|
|
240
|
-
y1={pad.t}
|
|
241
|
-
y2={height - pad.b}
|
|
242
|
-
x1={zero_x}
|
|
243
|
-
x2={zero_x}
|
|
244
|
-
stroke="gray"
|
|
245
|
-
stroke-width="0.5"
|
|
246
|
-
/>
|
|
247
|
-
{/if}
|
|
248
|
-
{/if}
|
|
249
|
-
{#if y_scale_type === `linear` && ranges.current.y[0] < 0 &&
|
|
250
|
-
ranges.current.y[1] > 0}
|
|
251
|
-
{@const zero_y = scales.y(0)}
|
|
252
|
-
{#if isFinite(zero_y)}
|
|
253
|
-
<line
|
|
254
|
-
x1={pad.l}
|
|
255
|
-
x2={width - pad.r}
|
|
256
|
-
y1={zero_y}
|
|
257
|
-
y2={zero_y}
|
|
258
|
-
stroke="gray"
|
|
259
|
-
stroke-width="0.5"
|
|
260
|
-
/>
|
|
261
|
-
{/if}
|
|
262
|
-
{/if}
|
|
263
|
-
{/if}
|
|
264
|
-
|
|
265
|
-
<!-- Histogram bars -->
|
|
266
|
-
{#each histogram_data as { bins, color, label }, series_idx (series_idx)}
|
|
267
|
-
<g class="histogram-series" data-series-idx={series_idx}>
|
|
268
|
-
{#each bins as bin, bin_idx (bin_idx)}
|
|
269
|
-
{@const bar_x = scales.x(bin.x0!)}
|
|
270
|
-
{@const bar_width = Math.max(1, Math.abs(scales.x(bin.x1!) - bar_x))}
|
|
271
|
-
{@const bar_height = Math.max(0, (height - pad.b) - scales.y(bin.length))}
|
|
272
|
-
{@const bar_y = scales.y(bin.length)}
|
|
273
|
-
{@const value = (bin.x0! + bin.x1!) / 2}
|
|
274
|
-
{#if bar_height > 0}
|
|
275
|
-
<rect
|
|
276
|
-
x={bar_x}
|
|
277
|
-
y={bar_y}
|
|
278
|
-
width={bar_width}
|
|
279
|
-
height={bar_height}
|
|
280
|
-
fill={color}
|
|
281
|
-
opacity={bar_opacity}
|
|
282
|
-
stroke={mode === `overlay` ? color : `none`}
|
|
283
|
-
stroke-width={mode === `overlay` ? bar_stroke_width : 0}
|
|
284
|
-
role="button"
|
|
285
|
-
tabindex="0"
|
|
286
|
-
onmousemove={(evt) => handle_mouse_move(evt, value, bin.length, label)}
|
|
287
|
-
onmouseleave={() => {
|
|
288
|
-
hover_info = null
|
|
289
|
-
change(null)
|
|
290
|
-
on_bar_hover?.(null)
|
|
291
|
-
}}
|
|
292
|
-
onclick={(event) =>
|
|
293
|
-
on_bar_click?.({ value, count: bin.length, property: label, event })}
|
|
294
|
-
onkeydown={(event: KeyboardEvent) => {
|
|
295
|
-
if ([`Enter`, ` `].includes(event.key)) {
|
|
296
|
-
event.preventDefault()
|
|
297
|
-
on_bar_click?.({ value, count: bin.length, property: label, event })
|
|
298
|
-
}
|
|
299
|
-
}}
|
|
300
|
-
style:cursor={on_bar_click ? `pointer` : undefined}
|
|
301
|
-
/>
|
|
302
|
-
{/if}
|
|
303
|
-
{/each}
|
|
304
|
-
</g>
|
|
305
|
-
{/each}
|
|
306
|
-
|
|
307
294
|
<!-- Tooltip -->
|
|
308
295
|
{#if hover_info}
|
|
309
296
|
{@const tooltip_x = scales.x(hover_info.value)}
|
|
310
|
-
{@const
|
|
297
|
+
{@const y_cfg = (hover_info.axis === `y2`) ? y2_axis : y_axis}
|
|
298
|
+
{@const tooltip_y = (hover_info.axis === `y2` ? scales.y2 : scales.y)(
|
|
299
|
+
hover_info.count,
|
|
300
|
+
)}
|
|
311
301
|
{@const tooltip_size = { width: 120, height: mode === `overlay` ? 60 : 40 }}
|
|
312
302
|
{@const tooltip_pos = constrain_tooltip_position(
|
|
313
303
|
tooltip_x,
|
|
@@ -327,8 +317,8 @@ function toggle_series_visibility(series_idx) {
|
|
|
327
317
|
{#if tooltip}
|
|
328
318
|
{@render tooltip(hover_info)}
|
|
329
319
|
{:else}
|
|
330
|
-
<div>Value: {format_value(hover_info.value,
|
|
331
|
-
<div>Count: {hover_info.count}</div>
|
|
320
|
+
<div>Value: {format_value(hover_info.value, x_axis.format || `.3~s`)}</div>
|
|
321
|
+
<div>Count: {format_value(hover_info.count, y_cfg.format || `.3~s`)}</div>
|
|
332
322
|
{#if mode === `overlay`}<div>{hover_info.property}</div>{/if}
|
|
333
323
|
{/if}
|
|
334
324
|
</div>
|
|
@@ -351,35 +341,41 @@ function toggle_series_visibility(series_idx) {
|
|
|
351
341
|
x2={width - pad.r}
|
|
352
342
|
y1={height - pad.b}
|
|
353
343
|
y2={height - pad.b}
|
|
354
|
-
stroke=
|
|
344
|
+
stroke={x_axis.color || `var(--border-color, gray)`}
|
|
355
345
|
stroke-width="1"
|
|
356
346
|
/>
|
|
357
347
|
{#each ticks.x as tick (tick)}
|
|
358
348
|
{@const tick_x = scales.x(tick as number)}
|
|
349
|
+
{@const custom_label = get_tick_label(tick as number, x_axis.ticks)}
|
|
359
350
|
<g class="tick" transform="translate({tick_x}, {height - pad.b})">
|
|
360
|
-
{#if x_grid}
|
|
351
|
+
{#if display.x_grid}
|
|
361
352
|
<line
|
|
362
353
|
y1={-(height - pad.b - pad.t)}
|
|
363
354
|
y2="0"
|
|
364
355
|
stroke="var(--border-color, gray)"
|
|
365
356
|
stroke-dasharray="4"
|
|
366
|
-
stroke-width="
|
|
367
|
-
{...
|
|
357
|
+
stroke-width="1"
|
|
358
|
+
{...x_axis.grid_style ?? {}}
|
|
368
359
|
/>
|
|
369
360
|
{/if}
|
|
370
|
-
<line
|
|
371
|
-
|
|
372
|
-
|
|
361
|
+
<line
|
|
362
|
+
y1="0"
|
|
363
|
+
y2="5"
|
|
364
|
+
stroke={x_axis.color || `var(--border-color, gray)`}
|
|
365
|
+
stroke-width="1"
|
|
366
|
+
/>
|
|
367
|
+
<text y="18" text-anchor="middle" fill={x_axis.color || `var(--text-color)`}>
|
|
368
|
+
{custom_label ?? format_value(tick, x_axis.format)}
|
|
373
369
|
</text>
|
|
374
370
|
</g>
|
|
375
371
|
{/each}
|
|
376
372
|
<text
|
|
377
|
-
x={(pad.l + width - pad.r) / 2}
|
|
378
|
-
y={height - 10}
|
|
373
|
+
x={(pad.l + width - pad.r) / 2 + (x_axis.label_shift?.x ?? 0)}
|
|
374
|
+
y={height - 10 + (x_axis.label_shift?.y ?? 0)}
|
|
379
375
|
text-anchor="middle"
|
|
380
|
-
fill=
|
|
376
|
+
fill={x_axis.color || `var(--text-color)`}
|
|
381
377
|
>
|
|
382
|
-
{
|
|
378
|
+
{@html x_axis.label}
|
|
383
379
|
</text>
|
|
384
380
|
</g>
|
|
385
381
|
|
|
@@ -390,73 +386,217 @@ function toggle_series_visibility(series_idx) {
|
|
|
390
386
|
x2={pad.l}
|
|
391
387
|
y1={pad.t}
|
|
392
388
|
y2={height - pad.b}
|
|
393
|
-
stroke=
|
|
389
|
+
stroke={y_axis.color || `var(--border-color, gray)`}
|
|
394
390
|
stroke-width="1"
|
|
395
391
|
/>
|
|
396
392
|
{#each ticks.y as tick (tick)}
|
|
397
393
|
{@const tick_y = scales.y(tick as number)}
|
|
394
|
+
{@const custom_label = get_tick_label(tick as number, y_axis.ticks)}
|
|
398
395
|
<g class="tick" transform="translate({pad.l}, {tick_y})">
|
|
399
|
-
{#if y_grid}
|
|
396
|
+
{#if display.y_grid}
|
|
400
397
|
<line
|
|
401
398
|
x1="0"
|
|
402
399
|
x2={width - pad.l - pad.r}
|
|
403
400
|
stroke="var(--border-color, gray)"
|
|
404
401
|
stroke-dasharray="4"
|
|
405
|
-
stroke-width="
|
|
406
|
-
{...
|
|
402
|
+
stroke-width="1"
|
|
403
|
+
{...y_axis.grid_style ?? {}}
|
|
407
404
|
/>
|
|
408
405
|
{/if}
|
|
409
|
-
<line
|
|
406
|
+
<line
|
|
407
|
+
x1="-5"
|
|
408
|
+
x2="0"
|
|
409
|
+
stroke={y_axis.color || `var(--border-color, gray)`}
|
|
410
|
+
stroke-width="1"
|
|
411
|
+
/>
|
|
410
412
|
<text
|
|
411
413
|
x="-10"
|
|
412
414
|
text-anchor="end"
|
|
413
415
|
dominant-baseline="central"
|
|
414
|
-
fill=
|
|
416
|
+
fill={y_axis.color || `var(--text-color)`}
|
|
415
417
|
>
|
|
416
|
-
{format_value(tick,
|
|
418
|
+
{custom_label ?? format_value(tick, y_axis.format)}
|
|
417
419
|
</text>
|
|
418
420
|
</g>
|
|
419
421
|
{/each}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
text
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
422
|
+
{#if y_axis.label}
|
|
423
|
+
{@const y_label_x = 15 + (y_axis.label_shift?.x ?? 0)}
|
|
424
|
+
{@const y_label_y = (pad.t + height - pad.b) / 2 + (y_axis.label_shift?.y ?? 0)}
|
|
425
|
+
<text
|
|
426
|
+
x={y_label_x}
|
|
427
|
+
y={y_label_y}
|
|
428
|
+
text-anchor="middle"
|
|
429
|
+
fill={y_axis.color || `var(--text-color)`}
|
|
430
|
+
transform="rotate(-90, {y_label_x}, {y_label_y})"
|
|
431
|
+
>
|
|
432
|
+
{@html y_axis.label}
|
|
433
|
+
</text>
|
|
434
|
+
{/if}
|
|
429
435
|
</g>
|
|
436
|
+
|
|
437
|
+
<!-- Y2-axis (Right) -->
|
|
438
|
+
{#if y2_series.length > 0}
|
|
439
|
+
<g class="y2-axis">
|
|
440
|
+
<line
|
|
441
|
+
x1={width - pad.r}
|
|
442
|
+
x2={width - pad.r}
|
|
443
|
+
y1={pad.t}
|
|
444
|
+
y2={height - pad.b}
|
|
445
|
+
stroke={y2_axis.color || `var(--border-color, gray)`}
|
|
446
|
+
stroke-width="1"
|
|
447
|
+
/>
|
|
448
|
+
{#each ticks.y2 as tick (tick)}
|
|
449
|
+
{@const tick_y = scales.y2(tick as number)}
|
|
450
|
+
{@const custom_label = get_tick_label(tick as number, y2_axis.ticks)}
|
|
451
|
+
<g class="tick" transform="translate({width - pad.r}, {tick_y})">
|
|
452
|
+
{#if display.y2_grid}
|
|
453
|
+
<line
|
|
454
|
+
x1={-(width - pad.l - pad.r)}
|
|
455
|
+
x2="0"
|
|
456
|
+
stroke="var(--border-color, gray)"
|
|
457
|
+
stroke-dasharray="4"
|
|
458
|
+
stroke-width="1"
|
|
459
|
+
{...y2_axis.grid_style ?? {}}
|
|
460
|
+
/>
|
|
461
|
+
{/if}
|
|
462
|
+
<line
|
|
463
|
+
x1="0"
|
|
464
|
+
x2="5"
|
|
465
|
+
stroke={y2_axis.color || `var(--border-color, gray)`}
|
|
466
|
+
stroke-width="1"
|
|
467
|
+
/>
|
|
468
|
+
<text
|
|
469
|
+
x={y2_axis.tick_label_shift?.x ?? 8}
|
|
470
|
+
y={y2_axis.tick_label_shift?.y ?? 0}
|
|
471
|
+
text-anchor="start"
|
|
472
|
+
dominant-baseline="central"
|
|
473
|
+
fill={y2_axis.color || `var(--text-color)`}
|
|
474
|
+
>
|
|
475
|
+
{custom_label ?? format_value(tick, y2_axis.format)}
|
|
476
|
+
</text>
|
|
477
|
+
</g>
|
|
478
|
+
{/each}
|
|
479
|
+
{#if y2_axis.label}
|
|
480
|
+
{@const y2_label_x = width - pad.r + 50 + (y2_axis.label_shift?.x ?? 0)}
|
|
481
|
+
{@const y2_label_y = (pad.t + height - pad.b) / 2 +
|
|
482
|
+
(y2_axis.label_shift?.y ?? 0)}
|
|
483
|
+
<text
|
|
484
|
+
x={y2_label_x}
|
|
485
|
+
y={y2_label_y}
|
|
486
|
+
text-anchor="middle"
|
|
487
|
+
fill={y2_axis.color || `var(--text-color)`}
|
|
488
|
+
transform="rotate(-90, {y2_label_x}, {y2_label_y})"
|
|
489
|
+
>
|
|
490
|
+
{@html y2_axis.label}
|
|
491
|
+
</text>
|
|
492
|
+
{/if}
|
|
493
|
+
</g>
|
|
494
|
+
{/if}
|
|
495
|
+
|
|
496
|
+
<!-- Zero lines -->
|
|
497
|
+
{#if display.x_zero_line && ranges.current.x[0] <= 0 && ranges.current.x[1] >= 0}
|
|
498
|
+
{@const x0 = scales.x(0)}
|
|
499
|
+
{#if isFinite(x0)}
|
|
500
|
+
<line class="zero-line" x1={x0} x2={x0} y1={pad.t} y2={height - pad.b} />
|
|
501
|
+
{/if}
|
|
502
|
+
{/if}
|
|
503
|
+
{#if display.y_zero_line && (y_axis.scale_type ?? `linear`) === `linear` &&
|
|
504
|
+
ranges.current.y[0] <= 0 && ranges.current.y[1] >= 0}
|
|
505
|
+
{@const zero_y = scales.y(0)}
|
|
506
|
+
{#if isFinite(zero_y)}
|
|
507
|
+
<line class="zero-line" x1={pad.l} x2={width - pad.r} y1={zero_y} y2={zero_y} />
|
|
508
|
+
{/if}
|
|
509
|
+
{/if}
|
|
510
|
+
{#if display.y_zero_line && y2_series.length > 0 &&
|
|
511
|
+
(y2_axis.scale_type ?? `linear`) === `linear` &&
|
|
512
|
+
ranges.current.y2[0] <= 0 && ranges.current.y2[1] >= 0}
|
|
513
|
+
{@const zero_y2 = scales.y2(0)}
|
|
514
|
+
{#if isFinite(zero_y2)}
|
|
515
|
+
<line
|
|
516
|
+
class="zero-line"
|
|
517
|
+
x1={pad.l}
|
|
518
|
+
x2={width - pad.r}
|
|
519
|
+
y1={zero_y2}
|
|
520
|
+
y2={zero_y2}
|
|
521
|
+
/>
|
|
522
|
+
{/if}
|
|
523
|
+
{/if}
|
|
524
|
+
|
|
525
|
+
<!-- Histogram bars -->
|
|
526
|
+
{#each histogram_data as
|
|
527
|
+
{ id, bins, color, label, y_scale, y_axis },
|
|
528
|
+
series_idx
|
|
529
|
+
(id ?? series_idx)
|
|
530
|
+
}
|
|
531
|
+
<g class="histogram-series" data-series-idx={series_idx}>
|
|
532
|
+
{#each bins as bin, bin_idx (bin_idx)}
|
|
533
|
+
{@const bar_x = scales.x(bin.x0!)}
|
|
534
|
+
{@const bar_width = Math.max(1, Math.abs(scales.x(bin.x1!) - bar_x))}
|
|
535
|
+
{@const bar_height = Math.max(0, (height - pad.b) - y_scale(bin.length))}
|
|
536
|
+
{@const bar_y = y_scale(bin.length)}
|
|
537
|
+
{@const value = (bin.x0! + bin.x1!) / 2}
|
|
538
|
+
{#if bar_height > 0}
|
|
539
|
+
<rect
|
|
540
|
+
x={bar_x}
|
|
541
|
+
y={bar_y}
|
|
542
|
+
width={bar_width}
|
|
543
|
+
height={bar_height}
|
|
544
|
+
fill={color}
|
|
545
|
+
opacity={bar.opacity}
|
|
546
|
+
stroke={bar.stroke_color}
|
|
547
|
+
stroke-opacity={bar.stroke_opacity}
|
|
548
|
+
stroke-width={bar.stroke_width}
|
|
549
|
+
role="button"
|
|
550
|
+
tabindex="0"
|
|
551
|
+
onmousemove={(evt) =>
|
|
552
|
+
handle_mouse_move(
|
|
553
|
+
evt,
|
|
554
|
+
value,
|
|
555
|
+
bin.length,
|
|
556
|
+
label,
|
|
557
|
+
(y_axis ?? `y1`) as `y1` | `y2`,
|
|
558
|
+
)}
|
|
559
|
+
onmouseleave={() => {
|
|
560
|
+
hover_info = null
|
|
561
|
+
change(null)
|
|
562
|
+
on_bar_hover?.(null)
|
|
563
|
+
}}
|
|
564
|
+
onclick={(event) =>
|
|
565
|
+
on_bar_click?.({ value, count: bin.length, property: label, event })}
|
|
566
|
+
onkeydown={(event: KeyboardEvent) => {
|
|
567
|
+
if ([`Enter`, ` `].includes(event.key)) {
|
|
568
|
+
event.preventDefault()
|
|
569
|
+
on_bar_click?.({ value, count: bin.length, property: label, event })
|
|
570
|
+
}
|
|
571
|
+
}}
|
|
572
|
+
style:cursor={on_bar_click ? `pointer` : undefined}
|
|
573
|
+
/>
|
|
574
|
+
{/if}
|
|
575
|
+
{/each}
|
|
576
|
+
</g>
|
|
577
|
+
{/each}
|
|
430
578
|
</svg>
|
|
431
579
|
{/if}
|
|
432
580
|
|
|
433
581
|
{#if show_controls}
|
|
434
582
|
<HistogramControls
|
|
435
583
|
toggle_props={controls_toggle_props}
|
|
584
|
+
pane_props={controls_pane_props}
|
|
436
585
|
bind:show_controls
|
|
437
586
|
bind:controls_open
|
|
438
587
|
bind:bins
|
|
439
588
|
bind:mode
|
|
440
|
-
bind:
|
|
441
|
-
bind:bar_stroke_width
|
|
442
|
-
bind:bar_color
|
|
589
|
+
bind:bar
|
|
443
590
|
bind:show_legend
|
|
444
|
-
bind:x_grid
|
|
445
|
-
bind:y_grid
|
|
446
|
-
bind:x_scale_type
|
|
447
|
-
bind:y_scale_type
|
|
448
|
-
bind:x_ticks
|
|
449
|
-
bind:y_ticks
|
|
450
|
-
bind:x_format
|
|
451
|
-
bind:y_format
|
|
452
591
|
bind:selected_property
|
|
453
|
-
bind:
|
|
454
|
-
bind:
|
|
455
|
-
bind:
|
|
592
|
+
bind:x_axis
|
|
593
|
+
bind:y_axis
|
|
594
|
+
bind:y2_axis
|
|
595
|
+
bind:display
|
|
456
596
|
auto_x_range={auto_ranges.x}
|
|
457
597
|
auto_y_range={auto_ranges.y}
|
|
598
|
+
auto_y2_range={auto_ranges.y2}
|
|
458
599
|
{series}
|
|
459
|
-
{plot_controls}
|
|
460
600
|
/>
|
|
461
601
|
{/if}
|
|
462
602
|
|
|
@@ -468,6 +608,9 @@ function toggle_series_visibility(series_idx) {
|
|
|
468
608
|
wrapper_style="position: absolute; left: {legend_placement.x}px; top: {legend_placement.y}px; transform: {legend_placement.transform}; {legend?.wrapper_style || ``}"
|
|
469
609
|
/>
|
|
470
610
|
{/if}
|
|
611
|
+
|
|
612
|
+
<!-- User-provided children (e.g. for custom absolutely-positioned overlays) -->
|
|
613
|
+
{@render children?.()}
|
|
471
614
|
</div>
|
|
472
615
|
|
|
473
616
|
<style>
|
|
@@ -483,7 +626,7 @@ function toggle_series_visibility(series_idx) {
|
|
|
483
626
|
width: 100%;
|
|
484
627
|
height: 100%;
|
|
485
628
|
}
|
|
486
|
-
g:is(.x-axis, .y-axis) .tick text {
|
|
629
|
+
g:is(.x-axis, .y-axis, .y2-axis) .tick text {
|
|
487
630
|
font-size: var(--tick-font-size, 0.8em); /* shrink tick labels */
|
|
488
631
|
}
|
|
489
632
|
.tooltip {
|
|
@@ -508,4 +651,9 @@ function toggle_series_visibility(series_idx) {
|
|
|
508
651
|
stroke-width: var(--histogram-zoom-rect-stroke-width, 1);
|
|
509
652
|
pointer-events: none;
|
|
510
653
|
}
|
|
654
|
+
.zero-line {
|
|
655
|
+
stroke: var(--histogram-zero-line-color, light-dark(black, white));
|
|
656
|
+
stroke-width: var(--histogram-zero-line-width, 1);
|
|
657
|
+
opacity: var(--histogram-zero-line-opacity);
|
|
658
|
+
}
|
|
511
659
|
</style>
|