td-plots 1.11.0 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/LegendUtils.d.ts +4 -1
- package/dist/components/SplitBoxPlot.d.ts +1 -0
- package/dist/components/SummaryComparisonPlot.d.ts +13 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +176 -94
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +176 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,4 +14,7 @@ export type LegendBoxPlotItemProps = LegendItemProps & {
|
|
|
14
14
|
};
|
|
15
15
|
export declare const LegendBoxPlotItem: (props: LegendBoxPlotItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
16
|
export declare const LegendColorItem: (props: LegendItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
-
export
|
|
17
|
+
export type LegendLineItemProps = LegendItemProps & {
|
|
18
|
+
strokeDasharray?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare const LegendLineItem: (props: LegendLineItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
summarizedMean?: number;
|
|
1
|
+
type BracketData = {
|
|
2
|
+
userValue?: number;
|
|
3
|
+
populationMin: number;
|
|
4
|
+
populationMax: number;
|
|
6
5
|
};
|
|
7
|
-
type
|
|
6
|
+
type BracketDataWithMeta = {
|
|
8
7
|
groupLabel: string;
|
|
9
|
-
data:
|
|
8
|
+
data: BracketData;
|
|
10
9
|
color?: string;
|
|
11
10
|
};
|
|
12
11
|
export type SummaryComparisonPlotProps = {
|
|
13
|
-
groups:
|
|
12
|
+
groups: BracketDataWithMeta[];
|
|
13
|
+
userColor?: string;
|
|
14
14
|
width?: number;
|
|
15
15
|
height?: number;
|
|
16
16
|
title?: string;
|
|
@@ -21,6 +21,11 @@ export type SummaryComparisonPlotProps = {
|
|
|
21
21
|
tooltipPosition?: "left" | "right";
|
|
22
22
|
startXAxisAtZero?: boolean;
|
|
23
23
|
unit?: string;
|
|
24
|
+
tooltipLabels?: {
|
|
25
|
+
populationMinLabel?: string;
|
|
26
|
+
populationMaxLabel?: string;
|
|
27
|
+
userValueLabel?: string;
|
|
28
|
+
};
|
|
24
29
|
};
|
|
25
30
|
declare const SummaryComparisonPlot: (props: SummaryComparisonPlotProps) => import("react/jsx-runtime").JSX.Element;
|
|
26
31
|
export default SummaryComparisonPlot;
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,6 @@ export type { LineWithHistogramProps } from "./components/LineWithHistogram";
|
|
|
19
19
|
export { default as BarPlot } from "./components/BarPlot";
|
|
20
20
|
export type { BarPlotProps } from "./components/BarPlot";
|
|
21
21
|
export { LegendColorItem, LegendLineItem } from "./components/LegendUtils";
|
|
22
|
-
export type { LegendItemProps } from "./components/LegendUtils";
|
|
22
|
+
export type { LegendItemProps, LegendLineItemProps, } from "./components/LegendUtils";
|
|
23
23
|
export { isDateArray, isNumberArray } from "./components/Utils";
|
|
24
24
|
export type { PlotParams } from "react-plotly.js";
|
package/dist/index.esm.js
CHANGED
|
@@ -1619,6 +1619,7 @@ const LegendColorItem = (props) => {
|
|
|
1619
1619
|
const LegendLineItem = (props) => {
|
|
1620
1620
|
const lineWidth = props.width || 40;
|
|
1621
1621
|
const lineHeight = props.height || 4;
|
|
1622
|
+
const dashArray = props.strokeDasharray || "";
|
|
1622
1623
|
const labelKey = props.label == null
|
|
1623
1624
|
? ""
|
|
1624
1625
|
: typeof props.label === "string"
|
|
@@ -1629,7 +1630,7 @@ const LegendLineItem = (props) => {
|
|
|
1629
1630
|
alignItems: "center",
|
|
1630
1631
|
mr: 4,
|
|
1631
1632
|
fontFamily: "Open Sans, verdana, arial, sans-serif",
|
|
1632
|
-
}, children: [jsx("svg", { width: lineWidth, height: lineHeight, style: { marginRight: 8 }, children: jsx("line", { x1: 0, y1: lineHeight / 2, x2: lineWidth, y2: lineHeight / 2, stroke: props.color, strokeWidth: lineHeight }) }), props.label] }, labelKey));
|
|
1633
|
+
}, children: [jsx("svg", { width: lineWidth, height: lineHeight, style: { marginRight: 8 }, children: jsx("line", { x1: 0, y1: lineHeight / 2, x2: lineWidth, y2: lineHeight / 2, stroke: props.color, strokeWidth: lineHeight, strokeDasharray: dashArray }) }), props.label] }, labelKey));
|
|
1633
1634
|
};
|
|
1634
1635
|
|
|
1635
1636
|
// This component takes grouped data and transforms it for displaying with the BoxPlot component.
|
|
@@ -1818,7 +1819,7 @@ const PairedComparisonsBoxPlot = (props) => {
|
|
|
1818
1819
|
// This component shows a set of main boxplots as one collection, then allowes for additional
|
|
1819
1820
|
// boxes to be shown in a subplot above the main boxplots for comparison.
|
|
1820
1821
|
const SplitBoxPlot = (props) => {
|
|
1821
|
-
const { groups, additionalGroups = [], width = 600, height = 400, title = "", xAxisTitle, yAxisTitle, secondXAxisTitle, secondYAxisTitle, containerStyleOverrides, plotId = "paired-comparisons-boxplot", xAnnotations = [], } = props;
|
|
1822
|
+
const { groups, additionalGroups = [], width = 600, height = 400, title = "", xAxisTitle, yAxisTitle, secondXAxisTitle, secondYAxisTitle, containerStyleOverrides, plotId = "paired-comparisons-boxplot", xAnnotations = [], yTitleLocationOverride, } = props;
|
|
1822
1823
|
// Transform the grouped data into an array for BoxPlot
|
|
1823
1824
|
const boxPlotData = [
|
|
1824
1825
|
...groups.flatMap((group, groupIndex) => {
|
|
@@ -1922,6 +1923,57 @@ const SplitBoxPlot = (props) => {
|
|
|
1922
1923
|
});
|
|
1923
1924
|
const totalGroups = groups.length + additionalGroups.length;
|
|
1924
1925
|
const yAxisSplitProportion = additionalGroups.length > 0 ? groups.length / totalGroups : 1;
|
|
1926
|
+
// Render y-axis titles as annotations so both always land at the same paper x,
|
|
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;
|
|
1939
|
+
const yAxisTitleAnnotations = [];
|
|
1940
|
+
if (yAxisTitle) {
|
|
1941
|
+
const domainTop = additionalGroups.length > 0 ? yAxisSplitProportion - 0.01 : 1;
|
|
1942
|
+
yAxisTitleAnnotations.push({
|
|
1943
|
+
text: yAxisTitle,
|
|
1944
|
+
x: yTitleLocationOverride || titleXPaper,
|
|
1945
|
+
y: domainTop / 2,
|
|
1946
|
+
xref: "paper",
|
|
1947
|
+
yref: "paper",
|
|
1948
|
+
showarrow: false,
|
|
1949
|
+
textangle: "-90",
|
|
1950
|
+
xanchor: "center",
|
|
1951
|
+
yanchor: "middle",
|
|
1952
|
+
font: {
|
|
1953
|
+
family: '"Open Sans", verdana, arial, sans-serif',
|
|
1954
|
+
size: 14,
|
|
1955
|
+
color: "rgb(68, 68, 68)",
|
|
1956
|
+
},
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
if (secondYAxisTitle && additionalGroups.length > 0) {
|
|
1960
|
+
yAxisTitleAnnotations.push({
|
|
1961
|
+
text: secondYAxisTitle,
|
|
1962
|
+
x: yTitleLocationOverride || titleXPaper,
|
|
1963
|
+
y: (yAxisSplitProportion + 1) / 2,
|
|
1964
|
+
xref: "paper",
|
|
1965
|
+
yref: "paper",
|
|
1966
|
+
showarrow: false,
|
|
1967
|
+
textangle: "-90",
|
|
1968
|
+
xanchor: "center",
|
|
1969
|
+
yanchor: "middle",
|
|
1970
|
+
font: {
|
|
1971
|
+
family: '"Open Sans", verdana, arial, sans-serif',
|
|
1972
|
+
size: 14,
|
|
1973
|
+
color: "rgb(68, 68, 68)",
|
|
1974
|
+
}, // styled to look like plotly's default title styling
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1925
1977
|
const extraLayoutConfig = Object.assign(Object.assign({ yaxis: {
|
|
1926
1978
|
type: "linear", // Use linear axis for numeric positioning of boxes
|
|
1927
1979
|
tickmode: "array",
|
|
@@ -1929,44 +1981,44 @@ const SplitBoxPlot = (props) => {
|
|
|
1929
1981
|
ticktext,
|
|
1930
1982
|
automargin: true,
|
|
1931
1983
|
range: [-0.5, groups.length - 0.5], // Add some padding to the y-axis range to accommodate the boxes
|
|
1932
|
-
domain: additionalGroups ? [0, yAxisSplitProportion - 0.01] : [0, 1], // Ensure primary y-axis takes full height
|
|
1984
|
+
domain: additionalGroups.length > 0 ? [0, yAxisSplitProportion - 0.01] : [0, 1], // Ensure primary y-axis takes full height
|
|
1933
1985
|
tickcolor: "#ffffff",
|
|
1934
1986
|
ticklen: 0,
|
|
1987
|
+
ticksuffix: "", // clear the BoxPlot default suffix so label widths match yaxis2
|
|
1935
1988
|
showgrid: false,
|
|
1936
1989
|
//@ts-ignore
|
|
1937
1990
|
ticklabelstandoff: 7,
|
|
1938
1991
|
ticklabelposition: "outside left",
|
|
1939
|
-
title: {
|
|
1940
|
-
text: yAxisTitle || "", // Set default to empty string to prevent Plotly from adding its own default title
|
|
1941
|
-
standoff: 45,
|
|
1942
|
-
},
|
|
1992
|
+
title: { text: "" }, // rendered via annotation instead
|
|
1943
1993
|
}, xaxis: {
|
|
1944
1994
|
anchor: "y", // Anchor to primary y-axis
|
|
1945
1995
|
}, margin: {
|
|
1946
|
-
t: title ? 50 :
|
|
1996
|
+
t: title ? 50 : 70,
|
|
1947
1997
|
r: 50,
|
|
1998
|
+
l: leftMargin,
|
|
1948
1999
|
}, shapes: [
|
|
1949
2000
|
...separatorShapes,
|
|
1950
2001
|
// ...differenceBetweenMediansLines,
|
|
1951
|
-
...xAnnotations.map((annotation) => ({
|
|
2002
|
+
...xAnnotations.map((annotation, annotationIndex) => ({
|
|
1952
2003
|
type: "line",
|
|
1953
2004
|
x0: annotation.x,
|
|
1954
2005
|
x1: annotation.x,
|
|
1955
2006
|
y0: 0,
|
|
1956
|
-
y1: 1.05,
|
|
2007
|
+
y1: 1.05 + annotationIndex * 0.05,
|
|
1957
2008
|
xref: "x",
|
|
1958
2009
|
yref: "paper",
|
|
1959
2010
|
line: {
|
|
1960
2011
|
color: annotation.color || "rgba(255, 0, 0, 0.7)",
|
|
1961
2012
|
width: 2,
|
|
1962
|
-
dash: "
|
|
2013
|
+
dash: "dot",
|
|
1963
2014
|
},
|
|
1964
2015
|
})),
|
|
1965
2016
|
], annotations: [
|
|
2017
|
+
...yAxisTitleAnnotations,
|
|
1966
2018
|
// ...differenceAnnotations,
|
|
1967
|
-
...xAnnotations.map((annotation) => ({
|
|
2019
|
+
...xAnnotations.map((annotation, annotationIndex) => ({
|
|
1968
2020
|
x: annotation.x,
|
|
1969
|
-
y: 1.
|
|
2021
|
+
y: 1.05 + annotationIndex * 0.05, // Stack annotations above the plot with some spacing
|
|
1970
2022
|
xref: "x",
|
|
1971
2023
|
yref: "paper",
|
|
1972
2024
|
text: annotation.text || "",
|
|
@@ -1977,10 +2029,11 @@ const SplitBoxPlot = (props) => {
|
|
|
1977
2029
|
size: 12,
|
|
1978
2030
|
},
|
|
1979
2031
|
})),
|
|
1980
|
-
] }, (additionalGroups && {
|
|
2032
|
+
] }, (additionalGroups.length > 0 && {
|
|
1981
2033
|
xaxis2: {
|
|
1982
2034
|
title: {
|
|
1983
2035
|
text: secondXAxisTitle || "", // Set default to empty string to prevent Plotly from adding its own default title
|
|
2036
|
+
standoff: 10 + xAnnotations.length * 12, // Add extra space to accommodate annotations.
|
|
1984
2037
|
},
|
|
1985
2038
|
side: "top",
|
|
1986
2039
|
anchor: "y2", // Anchor to secondary y-axis
|
|
@@ -1998,17 +2051,16 @@ const SplitBoxPlot = (props) => {
|
|
|
1998
2051
|
automargin: true,
|
|
1999
2052
|
matches: "x", // Match the range of xaxis to keep them synchronized
|
|
2000
2053
|
},
|
|
2001
|
-
})), (additionalGroups && {
|
|
2054
|
+
})), (additionalGroups.length > 0 && {
|
|
2002
2055
|
yaxis2: {
|
|
2003
2056
|
domain: [yAxisSplitProportion, 1], // Adjust domain for secondary y-axis (histogram)
|
|
2004
|
-
title: {
|
|
2005
|
-
text: secondYAxisTitle || "", // Set default to empty string to prevent Plotly from adding its own default title
|
|
2006
|
-
standoff: 45, // Add space between title and axis
|
|
2007
|
-
},
|
|
2057
|
+
title: { text: "" }, // rendered via annotation instead
|
|
2008
2058
|
range: [-0.5, additionalGroups.length - 0.5], // Add some padding to the y-axis range to accommodate the boxes
|
|
2009
2059
|
automargin: true, // Required for standoff to work properly
|
|
2010
2060
|
showgrid: true,
|
|
2011
2061
|
zeroline: false,
|
|
2062
|
+
ticklen: 0,
|
|
2063
|
+
ticksuffix: "",
|
|
2012
2064
|
ticklabelposition: "outside left",
|
|
2013
2065
|
showline: true,
|
|
2014
2066
|
mirror: "ticks",
|
|
@@ -2025,15 +2077,15 @@ const SplitBoxPlot = (props) => {
|
|
|
2025
2077
|
ticklabelstandoff: 7,
|
|
2026
2078
|
},
|
|
2027
2079
|
}));
|
|
2028
|
-
console.log("extraLayoutConfig:", extraLayoutConfig);
|
|
2029
2080
|
const containerStyles = Object.assign({ width: width, height: height, position: "relative", display: "flex", flexDirection: "column", gap: 0 }, containerStyleOverrides);
|
|
2030
|
-
console.log(boxPlotData);
|
|
2031
2081
|
return (jsx("div", { style: Object.assign({}, containerStyles), children: jsx(BoxPlot, { data: boxPlotData, width: width, height: height, title: title, xAxisTitle: xAxisTitle, yAxisTitle: yAxisTitle, extraLayoutConfig: extraLayoutConfig, containerStyleOverrides: containerStyleOverrides, plotId: `${plotId}-boxplot` }) }));
|
|
2032
2082
|
};
|
|
2033
2083
|
|
|
2034
2084
|
const Plot$2 = lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
|
|
2035
2085
|
const SummaryComparisonPlot = (props) => {
|
|
2036
|
-
const { groups, height = 250, title = "", xAxisTitle, yAxisTitle, containerStyleOverrides, plotId = "summary-comparison-plot", tooltipPosition = "right", startXAxisAtZero = true, unit = "",
|
|
2086
|
+
const { groups, userColor = "orange", height = 250, title = "", xAxisTitle, yAxisTitle, containerStyleOverrides, plotId = "summary-comparison-plot", tooltipPosition = "right", startXAxisAtZero = true, unit = "",
|
|
2087
|
+
// xAnnotations = [], TO DO
|
|
2088
|
+
tooltipLabels = {}, } = props;
|
|
2037
2089
|
// Ref for plot container
|
|
2038
2090
|
const containerRef = useRef(null);
|
|
2039
2091
|
// State for custom tooltip
|
|
@@ -2063,40 +2115,42 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2063
2115
|
let tooltipX = event.event.clientX;
|
|
2064
2116
|
let tooltipY = event.event.clientY;
|
|
2065
2117
|
content += `<strong>${groupName}</strong><br/>`;
|
|
2066
|
-
const
|
|
2067
|
-
? groupData.
|
|
2068
|
-
: "NA";
|
|
2069
|
-
const summarizedMaxText = groupData.summarizedMax
|
|
2070
|
-
? groupData.summarizedMax.toFixed(2)
|
|
2118
|
+
const populationMinText = groupData.populationMin !== undefined
|
|
2119
|
+
? groupData.populationMin.toFixed(2)
|
|
2071
2120
|
: "NA";
|
|
2072
|
-
const
|
|
2073
|
-
? groupData.
|
|
2121
|
+
const populationMaxText = groupData.populationMax !== undefined
|
|
2122
|
+
? groupData.populationMax.toFixed(2)
|
|
2074
2123
|
: "NA";
|
|
2075
2124
|
content += `
|
|
2076
2125
|
<table style="width: 100%; margin-top: 4px;">
|
|
2077
2126
|
<tr>
|
|
2078
|
-
<td style="text-align: left; padding: 2px 18px 2px 0;"
|
|
2079
|
-
<td style="text-align: right; padding: 2px 0;">${
|
|
2127
|
+
<td style="text-align: left; padding: 2px 18px 2px 0;">${tooltipLabels.populationMinLabel || "Population avg-\u03C3"}:</td>
|
|
2128
|
+
<td style="text-align: right; padding: 2px 0;">${populationMinText}</td>
|
|
2080
2129
|
</tr>
|
|
2081
2130
|
<tr>
|
|
2082
|
-
<td style="text-align: left; padding: 2px 18px 2px 0;"
|
|
2083
|
-
<td style="text-align: right; padding: 2px 0;">${
|
|
2131
|
+
<td style="text-align: left; padding: 2px 18px 2px 0;">${tooltipLabels.populationMaxLabel || "Population avg+\u03C3"}:</td>
|
|
2132
|
+
<td style="text-align: right; padding: 2px 0;">${populationMaxText}</td>
|
|
2084
2133
|
</tr>
|
|
2134
|
+
`;
|
|
2135
|
+
if (groupData.userValue !== undefined) {
|
|
2136
|
+
const userValueText = groupData.userValue.toFixed(2);
|
|
2137
|
+
content += `
|
|
2085
2138
|
<tr>
|
|
2086
|
-
<td style="text-align: left; padding: 2px 18px 2px 0;"
|
|
2087
|
-
<td style="text-align: right; padding: 2px 0;">${
|
|
2139
|
+
<td style="text-align: left; padding: 2px 18px 2px 0;">${tooltipLabels.userValueLabel || "My value"}:</td>
|
|
2140
|
+
<td style="text-align: right; padding: 2px 0;">${userValueText}</td>
|
|
2088
2141
|
</tr>
|
|
2089
|
-
|
|
2090
|
-
|
|
2142
|
+
`;
|
|
2143
|
+
}
|
|
2144
|
+
content += `</table></div>`;
|
|
2091
2145
|
contentColor = eventData.line
|
|
2092
2146
|
? eventData.line.color
|
|
2093
2147
|
: eventData.marker.color || contentColor;
|
|
2094
|
-
// Position tooltip at the end of the line (
|
|
2148
|
+
// Position tooltip at the end of the line (populationMax for right tooltip, populationMin for left tooltip)
|
|
2095
2149
|
// Use the xaxis d2p method to convert data coordinate to pixel coordinate
|
|
2096
2150
|
if (point.xaxis && typeof point.xaxis.d2p === "function") {
|
|
2097
2151
|
const pixelX = tooltipPosition === "right"
|
|
2098
|
-
? point.xaxis.d2p(groupData.
|
|
2099
|
-
: point.xaxis.d2p(groupData.
|
|
2152
|
+
? point.xaxis.d2p(groupData.populationMax)
|
|
2153
|
+
: point.xaxis.d2p(groupData.populationMin);
|
|
2100
2154
|
const pixelY = point.yaxis.d2p(eventData.y[0]); // Use the y coordinate of the line for vertical positioning
|
|
2101
2155
|
const containerRect = (_b = containerRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
|
|
2102
2156
|
if (containerRect) {
|
|
@@ -2120,63 +2174,68 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2120
2174
|
// Transform the data into a format suitable for a plotly scatterplot
|
|
2121
2175
|
const plotlyData = groups.flatMap((group, groupIndex) => {
|
|
2122
2176
|
const traces = [];
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
}
|
|
2139
|
-
if (group.data.comparedMedian !== undefined) {
|
|
2140
|
-
traces.push({
|
|
2141
|
-
type: "scatter",
|
|
2142
|
-
mode: "markers",
|
|
2143
|
-
name: group.groupLabel,
|
|
2144
|
-
x: [group.data.comparedMedian],
|
|
2145
|
-
y: [groupIndex * 0.1],
|
|
2146
|
-
marker: {
|
|
2147
|
-
color: colorToRGBA(group.color || "orange", 1),
|
|
2148
|
-
size: 10,
|
|
2149
|
-
symbol: "circle",
|
|
2150
|
-
line: {
|
|
2151
|
-
color: "white",
|
|
2152
|
-
width: 1,
|
|
2153
|
-
},
|
|
2154
|
-
},
|
|
2155
|
-
showlegend: false,
|
|
2156
|
-
hoverinfo: "none",
|
|
2157
|
-
});
|
|
2177
|
+
traces.push({
|
|
2178
|
+
type: "scatter",
|
|
2179
|
+
mode: "lines",
|
|
2180
|
+
name: group.groupLabel,
|
|
2181
|
+
x: [group.data.populationMin, group.data.populationMax],
|
|
2182
|
+
y: [groupIndex * 0.1, groupIndex * 0.1],
|
|
2183
|
+
line: {
|
|
2184
|
+
color: colorToRGBA(group.color || "orange", 1),
|
|
2185
|
+
width: 6,
|
|
2186
|
+
},
|
|
2187
|
+
showlegend: false,
|
|
2188
|
+
hoverinfo: "none",
|
|
2189
|
+
});
|
|
2190
|
+
if (group.data.userValue !== undefined) {
|
|
2191
|
+
const CIRCLE_RADIUS_PX = 6;
|
|
2158
2192
|
comparedLines.push({
|
|
2159
2193
|
type: "line",
|
|
2160
2194
|
name: group.groupLabel,
|
|
2161
|
-
x0: group.data.
|
|
2162
|
-
x1: group.data.
|
|
2195
|
+
x0: group.data.userValue,
|
|
2196
|
+
x1: group.data.userValue,
|
|
2163
2197
|
y0: 0,
|
|
2164
2198
|
y1: 1.1,
|
|
2165
2199
|
yref: "paper",
|
|
2166
2200
|
line: {
|
|
2167
|
-
color:
|
|
2201
|
+
color: colorToRGBA(userColor, 1),
|
|
2168
2202
|
width: 2,
|
|
2169
2203
|
},
|
|
2170
2204
|
});
|
|
2205
|
+
comparedLines.push({
|
|
2206
|
+
type: "circle",
|
|
2207
|
+
xref: "x",
|
|
2208
|
+
yref: "y",
|
|
2209
|
+
// Pixel-mode: xanchor/yanchor are data coords for the center;
|
|
2210
|
+
// x0/x1/y0/y1 are pixel offsets, so the circle stays a fixed
|
|
2211
|
+
// visual size regardless of the axis scale.
|
|
2212
|
+
xsizemode: "pixel",
|
|
2213
|
+
ysizemode: "pixel",
|
|
2214
|
+
xanchor: group.data.userValue,
|
|
2215
|
+
yanchor: groupIndex * 0.1,
|
|
2216
|
+
x0: -CIRCLE_RADIUS_PX,
|
|
2217
|
+
x1: CIRCLE_RADIUS_PX,
|
|
2218
|
+
y0: -CIRCLE_RADIUS_PX,
|
|
2219
|
+
y1: CIRCLE_RADIUS_PX,
|
|
2220
|
+
fillcolor: colorToRGBA(userColor, 1),
|
|
2221
|
+
line: {
|
|
2222
|
+
color: "white",
|
|
2223
|
+
width: 1,
|
|
2224
|
+
},
|
|
2225
|
+
});
|
|
2171
2226
|
comparedAnnotations.push({
|
|
2172
|
-
x: group.data.
|
|
2173
|
-
y: 1.
|
|
2227
|
+
x: group.data.userValue,
|
|
2228
|
+
y: 1.1,
|
|
2174
2229
|
xref: "x",
|
|
2175
2230
|
yref: "paper",
|
|
2176
|
-
text: `${group.data.
|
|
2231
|
+
text: `${group.data.userValue.toFixed(2)} ${unit}`,
|
|
2177
2232
|
showarrow: false,
|
|
2178
2233
|
xanchor: "center",
|
|
2179
2234
|
yanchor: "bottom",
|
|
2235
|
+
font: {
|
|
2236
|
+
color: colorToRGBA(userColor, 1),
|
|
2237
|
+
size: 12,
|
|
2238
|
+
},
|
|
2180
2239
|
});
|
|
2181
2240
|
}
|
|
2182
2241
|
return traces;
|
|
@@ -2185,7 +2244,7 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2185
2244
|
if (comparedAnnotations.length > 0) {
|
|
2186
2245
|
comparedAnnotations.push({
|
|
2187
2246
|
x: -0.03, // Position to the left of the y-axis
|
|
2188
|
-
y: 1.
|
|
2247
|
+
y: 1.1, // Should match the y position of the compared median annotation
|
|
2189
2248
|
xref: "paper",
|
|
2190
2249
|
yref: "paper",
|
|
2191
2250
|
text: "My AVG",
|
|
@@ -2194,14 +2253,17 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2194
2253
|
yanchor: "bottom",
|
|
2195
2254
|
});
|
|
2196
2255
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2256
|
+
// xRangeMin a little funky because we want to ensure a non-zero value is calculated
|
|
2257
|
+
// in case startXAxisAtZero is false. populationMin is our anchor and
|
|
2258
|
+
// if that is not defined then we can fall back to a min of 0. If userValue is not defined
|
|
2259
|
+
// we want to listen to populationMin for computing xRangeMin.
|
|
2260
|
+
const xRangeMin = groups.reduce((min, group) => { var _a; return Math.min(min, group.data.populationMin, (_a = group.data.userValue) !== null && _a !== void 0 ? _a : Infinity); }, Infinity);
|
|
2261
|
+
// Similar logic for xRangeMax. If nothing is defined, set the max to 0.
|
|
2262
|
+
// Otherwise, listen to populationMax and userValue if given.
|
|
2201
2263
|
const xRangeMax = groups.reduce((max, group) => {
|
|
2202
|
-
var _a
|
|
2203
|
-
return Math.max(max,
|
|
2204
|
-
},
|
|
2264
|
+
var _a;
|
|
2265
|
+
return Math.max(max, group.data.populationMax, (_a = group.data.userValue) !== null && _a !== void 0 ? _a : -Infinity);
|
|
2266
|
+
}, -Infinity);
|
|
2205
2267
|
const layout = {
|
|
2206
2268
|
width: undefined,
|
|
2207
2269
|
height: height,
|
|
@@ -2250,6 +2312,12 @@ const SummaryComparisonPlot = (props) => {
|
|
|
2250
2312
|
linewidth: 1,
|
|
2251
2313
|
},
|
|
2252
2314
|
yaxis: {
|
|
2315
|
+
title: {
|
|
2316
|
+
text: yAxisTitle,
|
|
2317
|
+
font: {
|
|
2318
|
+
size: 14,
|
|
2319
|
+
},
|
|
2320
|
+
},
|
|
2253
2321
|
mirror: "ticks",
|
|
2254
2322
|
gridcolor: "#efefef",
|
|
2255
2323
|
gridwidth: 0.2,
|
|
@@ -2323,12 +2391,26 @@ const SummaryComparisonPlotLegend = ({ comparedDataLabel, summarizedDataLabel, c
|
|
|
2323
2391
|
gap: "20px",
|
|
2324
2392
|
alignItems: "center",
|
|
2325
2393
|
flexDirection: "row",
|
|
2326
|
-
}, children: [jsxs("div", { style: { display: "flex", gap: "5px", alignItems: "center" }, children: [
|
|
2394
|
+
}, children: [jsxs("div", { style: { display: "flex", gap: "5px", alignItems: "center" }, children: [jsxs("div", { style: {
|
|
2395
|
+
position: "relative",
|
|
2327
2396
|
width: 13,
|
|
2328
|
-
height:
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2397
|
+
height: 20,
|
|
2398
|
+
display: "flex",
|
|
2399
|
+
alignItems: "center",
|
|
2400
|
+
justifyContent: "center",
|
|
2401
|
+
}, children: [jsx(Box, { sx: {
|
|
2402
|
+
position: "absolute",
|
|
2403
|
+
width: 3,
|
|
2404
|
+
height: 20,
|
|
2405
|
+
backgroundColor: color,
|
|
2406
|
+
} }), jsx(Box, { sx: {
|
|
2407
|
+
position: "relative",
|
|
2408
|
+
width: 10,
|
|
2409
|
+
height: 10,
|
|
2410
|
+
backgroundColor: color,
|
|
2411
|
+
borderRadius: "20px",
|
|
2412
|
+
border: `1px solid white`,
|
|
2413
|
+
} })] }), jsx("span", { children: comparedDataLabel })] }), jsxs("div", { style: { display: "flex", gap: "5px", alignItems: "center" }, children: [jsx(Box, { sx: { width: 30, height: 5, backgroundColor: color } }), jsx("span", { children: summarizedDataLabel })] })] }));
|
|
2332
2414
|
};
|
|
2333
2415
|
|
|
2334
2416
|
const Plot$1 = lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
|