td-plots 1.11.1 → 1.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/BarPlot.d.ts +1 -0
- package/dist/components/SplitBoxPlot.d.ts +2 -1
- package/dist/components/SummaryComparisonPlot.d.ts +1 -0
- package/dist/index.esm.js +75 -46
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +75 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -38,6 +38,7 @@ export interface BarPlotProps {
|
|
|
38
38
|
barHoverTemplate?: string;
|
|
39
39
|
barGroups?: BarGroup[];
|
|
40
40
|
barGroupTooltipTitle?: string;
|
|
41
|
+
d3FormatValueString?: string;
|
|
41
42
|
}
|
|
42
43
|
declare const BarPlot: (props: BarPlotProps) => import("react/jsx-runtime").JSX.Element;
|
|
43
44
|
export default BarPlot;
|
|
@@ -18,7 +18,8 @@ export interface SplitBoxPlotProps {
|
|
|
18
18
|
text?: string;
|
|
19
19
|
color?: string;
|
|
20
20
|
}[];
|
|
21
|
-
|
|
21
|
+
d3FormatValueString?: string;
|
|
22
|
+
addExtraYTitleRoom?: boolean;
|
|
22
23
|
}
|
|
23
24
|
declare const SplitBoxPlot: (props: SplitBoxPlotProps) => import("react/jsx-runtime").JSX.Element;
|
|
24
25
|
export default SplitBoxPlot;
|
|
@@ -26,6 +26,7 @@ export type SummaryComparisonPlotProps = {
|
|
|
26
26
|
populationMaxLabel?: string;
|
|
27
27
|
userValueLabel?: string;
|
|
28
28
|
};
|
|
29
|
+
d3FormatValueString?: string;
|
|
29
30
|
};
|
|
30
31
|
declare const SummaryComparisonPlot: (props: SummaryComparisonPlotProps) => import("react/jsx-runtime").JSX.Element;
|
|
31
32
|
export default SummaryComparisonPlot;
|
package/dist/index.esm.js
CHANGED
|
@@ -1538,7 +1538,6 @@ const BoxPlot = (props) => {
|
|
|
1538
1538
|
staticPlot: false, // Enable interactivity
|
|
1539
1539
|
};
|
|
1540
1540
|
const containerStyles = Object.assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
1541
|
-
console.log("layout:", layout); // Debugging log to inspect the final layout object
|
|
1542
1541
|
return (jsx("div", { ref: containerRef,
|
|
1543
1542
|
// className={`plot-container ${plotId}`}
|
|
1544
1543
|
style: Object.assign({}, containerStyles), children: jsx(Suspense, { fallback: jsx(Loading, {}), children: jsxs("div", { style: {
|
|
@@ -1819,7 +1818,7 @@ const PairedComparisonsBoxPlot = (props) => {
|
|
|
1819
1818
|
// This component shows a set of main boxplots as one collection, then allowes for additional
|
|
1820
1819
|
// boxes to be shown in a subplot above the main boxplots for comparison.
|
|
1821
1820
|
const SplitBoxPlot = (props) => {
|
|
1822
|
-
const { groups, additionalGroups = [], width = 600, height = 400, title = "", xAxisTitle, yAxisTitle, secondXAxisTitle, secondYAxisTitle, containerStyleOverrides, plotId = "paired-comparisons-boxplot", xAnnotations = [],
|
|
1821
|
+
const { groups, additionalGroups = [], width = 600, height = 400, title = "", xAxisTitle, yAxisTitle, secondXAxisTitle, secondYAxisTitle, containerStyleOverrides, plotId = "paired-comparisons-boxplot", xAnnotations = [], d3FormatValueString = ".1f", addExtraYTitleRoom = false, } = props;
|
|
1823
1822
|
// Transform the grouped data into an array for BoxPlot
|
|
1824
1823
|
const boxPlotData = [
|
|
1825
1824
|
...groups.flatMap((group, groupIndex) => {
|
|
@@ -1923,25 +1922,14 @@ const SplitBoxPlot = (props) => {
|
|
|
1923
1922
|
});
|
|
1924
1923
|
const totalGroups = groups.length + additionalGroups.length;
|
|
1925
1924
|
const yAxisSplitProportion = additionalGroups.length > 0 ? groups.length / totalGroups : 1;
|
|
1926
|
-
|
|
1927
|
-
// Using this annotations approach because we found the standoff prop to be unreliable across subplots with different label widths.
|
|
1928
|
-
const charWidth = 8; // ~px per character for Open Sans 14px (Plotly title font)
|
|
1929
|
-
const primaryMaxChars = Math.max(0, ...groups.map((g) => g.label.length));
|
|
1930
|
-
const secondaryMaxChars = additionalGroups.length > 0
|
|
1931
|
-
? Math.max(0, ...additionalGroups.map((g) => g.label.length))
|
|
1932
|
-
: primaryMaxChars;
|
|
1933
|
-
const maxLabelChars = Math.max(primaryMaxChars, secondaryMaxChars);
|
|
1934
|
-
const approxLabelPx = maxLabelChars * charWidth;
|
|
1935
|
-
const leftMargin = approxLabelPx + 75; // tick labels + title + gaps
|
|
1936
|
-
const plotContentWidth = Math.max(1, width - leftMargin - 50);
|
|
1937
|
-
// 0.83 corrects for charWidth=8 overestimating rendered tick-label width (Open Sans 12px ≈ 6.6px/char)
|
|
1938
|
-
const titleXPaper = -(approxLabelPx * 0.83) / plotContentWidth;
|
|
1925
|
+
const xshift = addExtraYTitleRoom ? -140 : -130; // Add extra shift if we're adding extra room for y-axis titles
|
|
1939
1926
|
const yAxisTitleAnnotations = [];
|
|
1940
1927
|
if (yAxisTitle) {
|
|
1941
1928
|
const domainTop = additionalGroups.length > 0 ? yAxisSplitProportion - 0.01 : 1;
|
|
1942
1929
|
yAxisTitleAnnotations.push({
|
|
1943
1930
|
text: yAxisTitle,
|
|
1944
|
-
x:
|
|
1931
|
+
x: 0,
|
|
1932
|
+
xshift: xshift,
|
|
1945
1933
|
y: domainTop / 2,
|
|
1946
1934
|
xref: "paper",
|
|
1947
1935
|
yref: "paper",
|
|
@@ -1959,7 +1947,8 @@ const SplitBoxPlot = (props) => {
|
|
|
1959
1947
|
if (secondYAxisTitle && additionalGroups.length > 0) {
|
|
1960
1948
|
yAxisTitleAnnotations.push({
|
|
1961
1949
|
text: secondYAxisTitle,
|
|
1962
|
-
x:
|
|
1950
|
+
x: 0,
|
|
1951
|
+
xshift: xshift,
|
|
1963
1952
|
y: (yAxisSplitProportion + 1) / 2,
|
|
1964
1953
|
xref: "paper",
|
|
1965
1954
|
yref: "paper",
|
|
@@ -1979,7 +1968,7 @@ const SplitBoxPlot = (props) => {
|
|
|
1979
1968
|
tickmode: "array",
|
|
1980
1969
|
tickvals,
|
|
1981
1970
|
ticktext,
|
|
1982
|
-
automargin: true,
|
|
1971
|
+
// automargin: true,
|
|
1983
1972
|
range: [-0.5, groups.length - 0.5], // Add some padding to the y-axis range to accommodate the boxes
|
|
1984
1973
|
domain: additionalGroups.length > 0 ? [0, yAxisSplitProportion - 0.01] : [0, 1], // Ensure primary y-axis takes full height
|
|
1985
1974
|
tickcolor: "#ffffff",
|
|
@@ -1990,15 +1979,17 @@ const SplitBoxPlot = (props) => {
|
|
|
1990
1979
|
ticklabelstandoff: 7,
|
|
1991
1980
|
ticklabelposition: "outside left",
|
|
1992
1981
|
title: { text: "" }, // rendered via annotation instead
|
|
1982
|
+
hoverformat: d3FormatValueString, // Format hover values using provided d3 format string
|
|
1993
1983
|
}, xaxis: {
|
|
1994
1984
|
anchor: "y", // Anchor to primary y-axis
|
|
1985
|
+
tickformat: d3FormatValueString, // Format ticks using provided d3 format string
|
|
1986
|
+
hoverformat: d3FormatValueString, // Format hover values using provided d3 format string
|
|
1995
1987
|
}, margin: {
|
|
1996
1988
|
t: title ? 50 : 70,
|
|
1997
|
-
r:
|
|
1998
|
-
l:
|
|
1989
|
+
r: 20,
|
|
1990
|
+
l: 80, // Got to complicated to calculate. Adjust if necessary.
|
|
1999
1991
|
}, shapes: [
|
|
2000
1992
|
...separatorShapes,
|
|
2001
|
-
// ...differenceBetweenMediansLines,
|
|
2002
1993
|
...xAnnotations.map((annotation, annotationIndex) => ({
|
|
2003
1994
|
type: "line",
|
|
2004
1995
|
x0: annotation.x,
|
|
@@ -2018,12 +2009,13 @@ const SplitBoxPlot = (props) => {
|
|
|
2018
2009
|
// ...differenceAnnotations,
|
|
2019
2010
|
...xAnnotations.map((annotation, annotationIndex) => ({
|
|
2020
2011
|
x: annotation.x,
|
|
2021
|
-
y: 1
|
|
2012
|
+
y: 1,
|
|
2022
2013
|
xref: "x",
|
|
2023
2014
|
yref: "paper",
|
|
2024
2015
|
text: annotation.text || "",
|
|
2025
2016
|
showarrow: false,
|
|
2026
2017
|
yanchor: "bottom",
|
|
2018
|
+
yshift: 18 + annotationIndex * 20, // stack in pixels — stable across screen sizes
|
|
2027
2019
|
font: {
|
|
2028
2020
|
color: annotation.color || "rgba(255, 0, 0, 0.7)",
|
|
2029
2021
|
size: 12,
|
|
@@ -2050,6 +2042,7 @@ const SplitBoxPlot = (props) => {
|
|
|
2050
2042
|
fixedrange: true,
|
|
2051
2043
|
automargin: true,
|
|
2052
2044
|
matches: "x", // Match the range of xaxis to keep them synchronized
|
|
2045
|
+
tickformat: d3FormatValueString, // Format ticks using provided d3 format string
|
|
2053
2046
|
},
|
|
2054
2047
|
})), (additionalGroups.length > 0 && {
|
|
2055
2048
|
yaxis2: {
|
|
@@ -2085,7 +2078,7 @@ const Plot$2 = lazy(() => Promise.resolve().then(function () { return reactPlotl
|
|
|
2085
2078
|
const SummaryComparisonPlot = (props) => {
|
|
2086
2079
|
const { groups, userColor = "orange", height = 250, title = "", xAxisTitle, yAxisTitle, containerStyleOverrides, plotId = "summary-comparison-plot", tooltipPosition = "right", startXAxisAtZero = true, unit = "",
|
|
2087
2080
|
// xAnnotations = [], TO DO
|
|
2088
|
-
tooltipLabels = {}, } = props;
|
|
2081
|
+
tooltipLabels = {}, d3FormatValueString = ".1f", } = props;
|
|
2089
2082
|
// Ref for plot container
|
|
2090
2083
|
const containerRef = useRef(null);
|
|
2091
2084
|
// State for custom tooltip
|
|
@@ -2171,6 +2164,7 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2171
2164
|
};
|
|
2172
2165
|
const comparedLines = [];
|
|
2173
2166
|
const comparedAnnotations = [];
|
|
2167
|
+
console.log("d3FormatValueString:", d3FormatValueString);
|
|
2174
2168
|
// Transform the data into a format suitable for a plotly scatterplot
|
|
2175
2169
|
const plotlyData = groups.flatMap((group, groupIndex) => {
|
|
2176
2170
|
const traces = [];
|
|
@@ -2228,7 +2222,7 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2228
2222
|
y: 1.1,
|
|
2229
2223
|
xref: "x",
|
|
2230
2224
|
yref: "paper",
|
|
2231
|
-
text: `${group.data.userValue
|
|
2225
|
+
text: `${format$1(d3FormatValueString)(group.data.userValue)} ${unit}`,
|
|
2232
2226
|
showarrow: false,
|
|
2233
2227
|
xanchor: "center",
|
|
2234
2228
|
yanchor: "bottom",
|
|
@@ -2243,9 +2237,10 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2243
2237
|
// Add tick label for the compared annotation value
|
|
2244
2238
|
if (comparedAnnotations.length > 0) {
|
|
2245
2239
|
comparedAnnotations.push({
|
|
2246
|
-
x:
|
|
2240
|
+
x: 0, // Position to the left of the y-axis
|
|
2247
2241
|
y: 1.1, // Should match the y position of the compared median annotation
|
|
2248
2242
|
xref: "paper",
|
|
2243
|
+
xshift: -10,
|
|
2249
2244
|
yref: "paper",
|
|
2250
2245
|
text: "My AVG",
|
|
2251
2246
|
showarrow: false,
|
|
@@ -2269,7 +2264,7 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2269
2264
|
height: height,
|
|
2270
2265
|
autosize: true,
|
|
2271
2266
|
margin: {
|
|
2272
|
-
l:
|
|
2267
|
+
l: 100,
|
|
2273
2268
|
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
2274
2269
|
t: title ? 70 : 40,
|
|
2275
2270
|
b: 50,
|
|
@@ -2310,6 +2305,7 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2310
2305
|
zerolinewidth: 1,
|
|
2311
2306
|
linecolor: "#bababa",
|
|
2312
2307
|
linewidth: 1,
|
|
2308
|
+
tickformat: d3FormatValueString, // Format ticks using provided d3 format string
|
|
2313
2309
|
},
|
|
2314
2310
|
yaxis: {
|
|
2315
2311
|
title: {
|
|
@@ -2647,25 +2643,41 @@ const BarPlot = (props) => {
|
|
|
2647
2643
|
xAxisTitle = "X Axis", yAxisTitle = "Y Axis", xAxis2Title = "", yAxis2Title = "", xAccessor = (d) => d.x, yAccessor = (d) => d.y, containerStyleOverrides = {}, plotId = "bar-plot", xAnnotations = [], barHoverTemplate = "", // Default hover template for bars
|
|
2648
2644
|
barGroups = [], // Optional array of bar groups for grouping bars by color
|
|
2649
2645
|
barGroupTooltipTitle = "Group", // Default title for the bar group tooltip
|
|
2650
|
-
|
|
2646
|
+
d3FormatValueString = ".1f", } = props;
|
|
2651
2647
|
// Ref for plot container
|
|
2652
2648
|
const containerRef = useRef(null);
|
|
2653
2649
|
const plotMetaRef = useRef(null);
|
|
2650
|
+
// Pixel offsets from the x-axis line for the bar group shapes.
|
|
2651
|
+
// 45px clears tick marks + labels + axis title; the 15px band sits below all of them.
|
|
2652
|
+
const BAR_GROUP_SHAPE_TOP_PX = 8;
|
|
2653
|
+
const BAR_GROUP_SHAPE_HEIGHT_PX = 20;
|
|
2654
|
+
// px above the top of the plot area — lands between x2 tick labels (~15px) and x2 title (~35px)
|
|
2655
|
+
const X_ANNOTATION_TOP_PX = 22;
|
|
2656
|
+
// Tracks the rendered plot area height so we can convert the shape's fixed pixel
|
|
2657
|
+
// center back into a paper y coordinate for the annotation.
|
|
2658
|
+
const [plotAreaHeight, setPlotAreaHeight] = useState(300);
|
|
2654
2659
|
const [barGroupTooltip, setBarGroupTooltip] = useState(null);
|
|
2655
2660
|
const y2AxisPosition = 0.72; // Position of the secondary y-axis (histogram) as a fraction of the plot height
|
|
2656
2661
|
const capturePlotMeta = (_figure, graphDiv) => {
|
|
2657
|
-
var _a, _b, _c;
|
|
2662
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2658
2663
|
try {
|
|
2659
2664
|
const m = (_a = graphDiv._fullLayout) === null || _a === void 0 ? void 0 : _a.margin;
|
|
2660
2665
|
const r = (_c = (_b = graphDiv._fullLayout) === null || _b === void 0 ? void 0 : _b.xaxis) === null || _c === void 0 ? void 0 : _c.range;
|
|
2666
|
+
const h = (_d = graphDiv._fullLayout) === null || _d === void 0 ? void 0 : _d.height;
|
|
2661
2667
|
if (m && r) {
|
|
2662
2668
|
plotMetaRef.current = {
|
|
2663
2669
|
xRange: r,
|
|
2664
2670
|
margin: { l: m.l, r: m.r, t: m.t, b: m.b },
|
|
2671
|
+
height: (_f = h !== null && h !== void 0 ? h : (_e = containerRef.current) === null || _e === void 0 ? void 0 : _e.clientHeight) !== null && _f !== void 0 ? _f : 400,
|
|
2665
2672
|
};
|
|
2673
|
+
if (h) {
|
|
2674
|
+
const newPlotH = h - m.t - m.b;
|
|
2675
|
+
if (newPlotH > 0)
|
|
2676
|
+
setPlotAreaHeight(newPlotH);
|
|
2677
|
+
}
|
|
2666
2678
|
}
|
|
2667
2679
|
}
|
|
2668
|
-
catch (
|
|
2680
|
+
catch (_g) { }
|
|
2669
2681
|
};
|
|
2670
2682
|
const handleBarGroupMouseMove = (e) => {
|
|
2671
2683
|
var _a;
|
|
@@ -2675,18 +2687,18 @@ const BarPlot = (props) => {
|
|
|
2675
2687
|
setBarGroupTooltip(null);
|
|
2676
2688
|
return;
|
|
2677
2689
|
}
|
|
2678
|
-
const { xRange, margin } = plotMetaRef.current;
|
|
2690
|
+
const { xRange, margin, height: plotlyHeight } = plotMetaRef.current;
|
|
2679
2691
|
const rect = containerRef.current.getBoundingClientRect();
|
|
2680
2692
|
const mouseX = e.clientX - rect.left;
|
|
2681
2693
|
const mouseY = e.clientY - rect.top;
|
|
2682
|
-
const containerHeight = containerRef.current.clientHeight;
|
|
2683
2694
|
const containerWidth = containerRef.current.clientWidth;
|
|
2684
2695
|
const plotW = containerWidth - margin.l - margin.r;
|
|
2685
|
-
|
|
2686
|
-
const plotBottom =
|
|
2687
|
-
//
|
|
2688
|
-
|
|
2689
|
-
const
|
|
2696
|
+
// Use Plotly's own reported height so plotBottom is consistent with the margin values
|
|
2697
|
+
const plotBottom = plotlyHeight - margin.b - 35; // Subtracting and extra 35px to finally get it in the right spot.
|
|
2698
|
+
// Shapes use yanchor=0 (x-axis line) with negative pixel y values, which maps to
|
|
2699
|
+
// positive screen-y (downward). Strip bounds mirror those pixel offsets exactly.
|
|
2700
|
+
const stripTop = plotBottom;
|
|
2701
|
+
const stripBottom = plotBottom + BAR_GROUP_SHAPE_TOP_PX + BAR_GROUP_SHAPE_HEIGHT_PX + 5; // Give a little extra room on the bottom.
|
|
2690
2702
|
if (mouseY < stripTop || mouseY > stripBottom) {
|
|
2691
2703
|
setBarGroupTooltip(null);
|
|
2692
2704
|
return;
|
|
@@ -2767,8 +2779,8 @@ const BarPlot = (props) => {
|
|
|
2767
2779
|
xref: "paper",
|
|
2768
2780
|
yref: "paper",
|
|
2769
2781
|
x0: 0,
|
|
2770
|
-
y0: y2AxisPosition - 0.
|
|
2771
|
-
x1: 0.02 + title.length * 0.
|
|
2782
|
+
y0: y2AxisPosition - 0.11, // Position behind the primary title
|
|
2783
|
+
x1: 0.02 + title.length * 0.01, // Approximate width based on title length 0.3/
|
|
2772
2784
|
y1: y2AxisPosition - 0.01,
|
|
2773
2785
|
fillcolor: "rgba(255, 255, 255, 0.5)",
|
|
2774
2786
|
line: {
|
|
@@ -2837,8 +2849,12 @@ const BarPlot = (props) => {
|
|
|
2837
2849
|
yref: "paper",
|
|
2838
2850
|
x0: group.min,
|
|
2839
2851
|
x1: group.max > xMax ? xMax + barWidth : group.max,
|
|
2840
|
-
|
|
2841
|
-
|
|
2852
|
+
// Anchor at the x-axis line (paper y=0) so the pixel offset is consistent
|
|
2853
|
+
// regardless of plot height — avoids overlap with tick labels on small screens.
|
|
2854
|
+
yanchor: 0,
|
|
2855
|
+
ysizemode: "pixel",
|
|
2856
|
+
y0: -BAR_GROUP_SHAPE_TOP_PX,
|
|
2857
|
+
y1: -28,
|
|
2842
2858
|
fillcolor: group.color,
|
|
2843
2859
|
line: {
|
|
2844
2860
|
width: 1,
|
|
@@ -2851,7 +2867,10 @@ const BarPlot = (props) => {
|
|
|
2851
2867
|
xref: "x",
|
|
2852
2868
|
yref: "paper",
|
|
2853
2869
|
x: barGroups[0].min + barDataWidth / 2,
|
|
2854
|
-
y
|
|
2870
|
+
// Convert the pixel center of the shape band to a paper y coordinate using
|
|
2871
|
+
// the actual rendered plot area height so it stays inside the shape on any screen size.
|
|
2872
|
+
y: -18 /
|
|
2873
|
+
plotAreaHeight,
|
|
2855
2874
|
text: barGroupTooltipTitle,
|
|
2856
2875
|
showarrow: false,
|
|
2857
2876
|
yanchor: "middle",
|
|
@@ -2890,13 +2909,16 @@ const BarPlot = (props) => {
|
|
|
2890
2909
|
l: 50,
|
|
2891
2910
|
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
2892
2911
|
t: 40 + (title ? 50 : 0), // Add extra top margin if there is a title
|
|
2893
|
-
b:
|
|
2912
|
+
b: barGroups.length > 0
|
|
2913
|
+
? BAR_GROUP_SHAPE_TOP_PX + BAR_GROUP_SHAPE_HEIGHT_PX + 15
|
|
2914
|
+
: 50,
|
|
2894
2915
|
pad: 4,
|
|
2895
2916
|
}, xaxis: {
|
|
2896
2917
|
title: {
|
|
2897
2918
|
text: xAxisTitle,
|
|
2898
2919
|
},
|
|
2899
2920
|
anchor: "y", // Anchor to primary y-axis
|
|
2921
|
+
hoverformat: d3FormatValueString, // Format hover values using provided d3 format string
|
|
2900
2922
|
showgrid: true,
|
|
2901
2923
|
zeroline: false,
|
|
2902
2924
|
showline: true,
|
|
@@ -2909,12 +2931,16 @@ const BarPlot = (props) => {
|
|
|
2909
2931
|
linewidth: 1,
|
|
2910
2932
|
fixedrange: true, // Disable zooming
|
|
2911
2933
|
automargin: true, // Adjust margin if tick labels rotate
|
|
2912
|
-
ticklen:
|
|
2934
|
+
ticklen: barGroups.length > 0
|
|
2935
|
+
? BAR_GROUP_SHAPE_TOP_PX + BAR_GROUP_SHAPE_HEIGHT_PX
|
|
2936
|
+
: 8, // tick length in px.
|
|
2913
2937
|
tickcolor: "white",
|
|
2938
|
+
tickformat: d3FormatValueString, // Format ticks using provided d3 format string
|
|
2914
2939
|
} }, (data2 && {
|
|
2915
2940
|
xaxis2: {
|
|
2916
2941
|
title: {
|
|
2917
2942
|
text: xAxis2Title,
|
|
2943
|
+
standoff: 22,
|
|
2918
2944
|
},
|
|
2919
2945
|
side: "top",
|
|
2920
2946
|
anchor: "y2", // Anchor to secondary y-axis
|
|
@@ -2931,13 +2957,16 @@ const BarPlot = (props) => {
|
|
|
2931
2957
|
fixedrange: true,
|
|
2932
2958
|
automargin: true,
|
|
2933
2959
|
matches: "x", // Match the range of xaxis to keep them synchronized
|
|
2960
|
+
tickformat: d3FormatValueString, // Format ticks using provided d3 format string
|
|
2934
2961
|
},
|
|
2935
2962
|
})), { yaxis: {
|
|
2936
2963
|
title: {
|
|
2937
2964
|
text: yAxisTitle !== null && yAxisTitle !== void 0 ? yAxisTitle : "Count",
|
|
2938
|
-
standoff:
|
|
2965
|
+
standoff: 15, // Add space between title and axis
|
|
2939
2966
|
},
|
|
2940
2967
|
domain: data2 ? [0, y2AxisPosition - 0.01] : [0, 1], // Ensure primary y-axis takes full height
|
|
2968
|
+
hoverformat: d3FormatValueString, // Format hover values using provided d3 format string
|
|
2969
|
+
nticks: 7, // Limit number of ticks to prevent overcrowding with the histogram
|
|
2941
2970
|
automargin: true, // Required for standoff to work properly
|
|
2942
2971
|
showgrid: true,
|
|
2943
2972
|
zeroline: false,
|
|
@@ -2982,7 +3011,7 @@ const BarPlot = (props) => {
|
|
|
2982
3011
|
x0: annotation.x,
|
|
2983
3012
|
x1: annotation.x,
|
|
2984
3013
|
y0: 0,
|
|
2985
|
-
y1: 1
|
|
3014
|
+
y1: 1 + (X_ANNOTATION_TOP_PX - 4) / plotAreaHeight,
|
|
2986
3015
|
xref: "x",
|
|
2987
3016
|
yref: "paper",
|
|
2988
3017
|
line: {
|
|
@@ -2995,7 +3024,7 @@ const BarPlot = (props) => {
|
|
|
2995
3024
|
...(barGroupShapeAnnotation ? [barGroupShapeAnnotation] : []),
|
|
2996
3025
|
...xAnnotations.map((annotation) => ({
|
|
2997
3026
|
x: annotation.x,
|
|
2998
|
-
y: 1
|
|
3027
|
+
y: 1 + X_ANNOTATION_TOP_PX / plotAreaHeight,
|
|
2999
3028
|
xref: "x",
|
|
3000
3029
|
yref: "paper",
|
|
3001
3030
|
text: annotation.text || "",
|