td-plots 1.12.0 → 1.13.0

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/index.js CHANGED
@@ -543,7 +543,7 @@ var SettingsIcon = utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
543
543
  d: "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6"
544
544
  }), 'Settings');
545
545
 
546
- const Plot$7 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
546
+ const Plot$8 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
547
547
  const HistogramPlot = (props) => {
548
548
  var _a, _b, _c, _d;
549
549
  const { data, title, xAxisTitle, barColor = "rgb(72, 72, 74)", unselectedBarColor = "rgba(203, 195, 195, 0.88)", selectorsColor = "black", containerStyleOverrides, unselectedData = [], handleClickOrSelection = () => { }, onDeselect = () => { }, plotId, selectByBin = false, dateTickFormat, binSizeOverride, statsAnnotations = ["mean"], emptySelectedRange = false, d3FormatValueString = ".1f", showBinSizeControls = "always", onBinSizeCalculated, onBinSizeChange, showBinSizeControlValue = true, isMobile = false, settingsTitleStylingOverrides = {}, } = props;
@@ -1295,7 +1295,7 @@ const HistogramPlot = (props) => {
1295
1295
  const newBinSize = newValue;
1296
1296
  setBinSize(newBinSize);
1297
1297
  onBinSizeChange === null || onBinSizeChange === void 0 ? void 0 : onBinSizeChange(newBinSize);
1298
- }, colorOverride: barColor, valueLabelFormat: valueLabelFormat, titleStylingOverrides: settingsTitleStylingOverrides, disabledTooltipText: "Requires 10 or more data points" }) }) })] })), jsxRuntime.jsx(Plot$7, { data: plotlyData, layout: layout, config: config, onSelected: handleSelection, onClick: handleClick, onDeselect: () => {
1298
+ }, colorOverride: barColor, valueLabelFormat: valueLabelFormat, titleStylingOverrides: settingsTitleStylingOverrides, disabledTooltipText: "Requires 10 or more data points" }) }) })] })), jsxRuntime.jsx(Plot$8, { data: plotlyData, layout: layout, config: config, onSelected: handleSelection, onClick: handleClick, onDeselect: () => {
1299
1299
  onDeselect();
1300
1300
  setSelectedRange(null); // Remove selected box
1301
1301
  }, onUpdate: handlePlotUpdate, useResizeHandler: true, style: {
@@ -1306,7 +1306,7 @@ const HistogramPlot = (props) => {
1306
1306
  } }, `histogram-${plotId || "default"}`)] }) }) }));
1307
1307
  };
1308
1308
 
1309
- const Plot$6 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
1309
+ const Plot$7 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
1310
1310
  const RadialHistogramPlot = (props) => {
1311
1311
  const { data, barColor = "rgb(72, 72, 74)", unselectedBarColor = "rgba(203, 195, 195, 0.88)", selectorsColor = "black", onSelected, onClick, containerStyleOverrides, barWidth = 20, // Default bar width in degrees
1312
1312
  } = props;
@@ -1406,14 +1406,14 @@ const RadialHistogramPlot = (props) => {
1406
1406
  staticPlot: false,
1407
1407
  };
1408
1408
  const containerStyles = Object.assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
1409
- return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container radial-histogram-container", style: Object.assign({ "--selection-color": selectorsColor }, containerStyles), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx(Plot$6, { data: plotlyData, layout: layout, config: config, onSelected: onSelected, onClick: onClick, useResizeHandler: true, style: {
1409
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container radial-histogram-container", style: Object.assign({ "--selection-color": selectorsColor }, containerStyles), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx(Plot$7, { data: plotlyData, layout: layout, config: config, onSelected: onSelected, onClick: onClick, useResizeHandler: true, style: {
1410
1410
  width: "100%",
1411
1411
  height: "100%",
1412
1412
  display: "block",
1413
1413
  } }) }) }));
1414
1414
  };
1415
1415
 
1416
- const Plot$5 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
1416
+ const Plot$6 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
1417
1417
  const StatsDonut = (props) => {
1418
1418
  const { withCenterLabel = false, centerLabel, centerValue, showLegend = true, legendPosition = "right", containerStyle = {}, } = props;
1419
1419
  // Configure legend position based on prop
@@ -1461,7 +1461,7 @@ const StatsDonut = (props) => {
1461
1461
  },
1462
1462
  ]
1463
1463
  : [];
1464
- return (jsxRuntime.jsx("div", { style: Object.assign({ width: "100%", height: "100%", minHeight: "300px", display: "flex", justifyContent: "center", alignItems: "center" }, containerStyle), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx(Plot$5, { data: [
1464
+ return (jsxRuntime.jsx("div", { style: Object.assign({ width: "100%", height: "100%", minHeight: "300px", display: "flex", justifyContent: "center", alignItems: "center" }, containerStyle), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx(Plot$6, { data: [
1465
1465
  {
1466
1466
  type: "pie",
1467
1467
  values: props.values,
@@ -1494,7 +1494,7 @@ const StatsDonut = (props) => {
1494
1494
  }, useResizeHandler: true }) }) }));
1495
1495
  };
1496
1496
 
1497
- const Plot$4 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
1497
+ const Plot$5 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
1498
1498
  const BoxPlot = (props) => {
1499
1499
  const { data, width = 600, height = 400, title = "Box Plot", xAxisTitle, yAxisTitle, containerStyleOverrides, plotId = "boxplot", extraLayoutConfig = {}, } = props;
1500
1500
  // Ref for plot container
@@ -1547,7 +1547,7 @@ const BoxPlot = (props) => {
1547
1547
  position: "relative",
1548
1548
  width: "100%",
1549
1549
  height: "100%",
1550
- }, children: [jsxRuntime.jsx(Plot$4, { data: plotlyData, layout: layout, config: config, useResizeHandler: true,
1550
+ }, children: [jsxRuntime.jsx(Plot$5, { data: plotlyData, layout: layout, config: config, useResizeHandler: true,
1551
1551
  // onHover={handleHover}
1552
1552
  // onUnhover={handleUnhover}
1553
1553
  style: {
@@ -2077,7 +2077,7 @@ const SplitBoxPlot = (props) => {
2077
2077
  return (jsxRuntime.jsx("div", { style: Object.assign({}, containerStyles), children: jsxRuntime.jsx(BoxPlot, { data: boxPlotData, width: width, height: height, title: title, xAxisTitle: xAxisTitle, yAxisTitle: yAxisTitle, extraLayoutConfig: extraLayoutConfig, containerStyleOverrides: containerStyleOverrides, plotId: `${plotId}-boxplot` }) }));
2078
2078
  };
2079
2079
 
2080
- const Plot$3 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2080
+ const Plot$4 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2081
2081
  const SummaryComparisonPlot = (props) => {
2082
2082
  const { groups, height = 250, title = "", xAxisTitle, yAxisTitle, containerStyleOverrides, plotId = "summary-comparison-plot", tooltipPosition = "right", startXAxisAtZero = true, unit = "", xAnnotations = [], tooltipLabels = {}, d3FormatValueString = ".1f", } = props;
2083
2083
  // Ref for plot container
@@ -2352,7 +2352,7 @@ const SummaryComparisonPlot = (props) => {
2352
2352
  position: "relative",
2353
2353
  width: "100%",
2354
2354
  height: "100%",
2355
- }, children: [jsxRuntime.jsx(Plot$3, { data: plotlyData, layout: layout, config: config, useResizeHandler: true, onHover: handleHover, onUnhover: handleUnhover, style: {
2355
+ }, children: [jsxRuntime.jsx(Plot$4, { data: plotlyData, layout: layout, config: config, useResizeHandler: true, onHover: handleHover, onUnhover: handleUnhover, style: {
2356
2356
  width: "100%",
2357
2357
  height: `${height}px`,
2358
2358
  display: "block",
@@ -2407,7 +2407,7 @@ const SummaryComparisonPlotLegend = ({ comparedDataLabel, summarizedDataLabel, c
2407
2407
  } })] }), jsxRuntime.jsx("span", { children: comparedDataLabel })] }), jsxRuntime.jsxs("div", { style: { display: "flex", gap: "5px", alignItems: "center" }, children: [jsxRuntime.jsx(Box, { sx: { width: 30, height: 5, backgroundColor: color } }), jsxRuntime.jsx("span", { children: summarizedDataLabel })] })] }));
2408
2408
  };
2409
2409
 
2410
- const Plot$2 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2410
+ const Plot$3 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2411
2411
  // This component plots a line chart in the foreground with a histogram in the backgroun. The histogram
2412
2412
  // is used only for context, while the line is intended to have the focus. To that end, the line plot has hover interactions
2413
2413
  // while the histogram does not.
@@ -2623,17 +2623,17 @@ const LineWithHistogram = (props) => {
2623
2623
  position: "relative",
2624
2624
  width: "100%",
2625
2625
  height: "100%",
2626
- }, children: jsxRuntime.jsx(Plot$2, { data: plotlyData, layout: layout, config: config, useResizeHandler: true, style: {
2626
+ }, children: jsxRuntime.jsx(Plot$3, { data: plotlyData, layout: layout, config: config, useResizeHandler: true, style: {
2627
2627
  width: "100%",
2628
2628
  height: "100%",
2629
2629
  display: "block",
2630
2630
  transition: "opacity 0.15s ease-in-out",
2631
- }, revision: revision }, `lineplot-${plotId || "default"}`) }), jsxRuntime.jsx("div", { style: { display: "none" }, children: jsxRuntime.jsx(Plot$2, { data: histogramPlotlyData, layout: { width: 400, height: 300 }, onInitialized: handlePlotInitialized }, `hidden-histogram-${plotId || "default"}-${hiddenPlotKey}`) })] }) }));
2631
+ }, revision: revision }, `lineplot-${plotId || "default"}`) }), jsxRuntime.jsx("div", { style: { display: "none" }, children: jsxRuntime.jsx(Plot$3, { data: histogramPlotlyData, layout: { width: 400, height: 300 }, onInitialized: handlePlotInitialized }, `hidden-histogram-${plotId || "default"}-${hiddenPlotKey}`) })] }) }));
2632
2632
  };
2633
2633
 
2634
- const Plot$1 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2634
+ const Plot$2 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2635
2635
  const SPLIT = 0.33;
2636
- const GAP = 0.03;
2636
+ const GAP = 0.04;
2637
2637
  // Stacked subplots sharing a single x-axis: histogram on top (yaxis2), line on bottom (yaxis).
2638
2638
  // Because both traces use xaxis "x", hovermode "x unified" spans both panels simultaneously.
2639
2639
  // histogramData.x must be in the same domain as lineData.x for hover to be meaningful.
@@ -2753,7 +2753,7 @@ const LineOnHistogram = (props) => {
2753
2753
  scrollZoom: false,
2754
2754
  staticPlot: false,
2755
2755
  };
2756
- return (jsxRuntime.jsx("div", { style: Object.assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx(Plot$1, { data: plotlyData, layout: layout, config: config, useResizeHandler: true, style: {
2756
+ return (jsxRuntime.jsx("div", { style: Object.assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx(Plot$2, { data: plotlyData, layout: layout, config: config, useResizeHandler: true, style: {
2757
2757
  width: "100%",
2758
2758
  height: "100%",
2759
2759
  display: "block",
@@ -2761,7 +2761,7 @@ const LineOnHistogram = (props) => {
2761
2761
  }, revision: revision }, `lineplot-${plotId || "default"}`) }) }));
2762
2762
  };
2763
2763
 
2764
- const Plot = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2764
+ const Plot$1 = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
2765
2765
  const BarPlot = (props) => {
2766
2766
  var _a, _b;
2767
2767
  const { data, data2 = null, data2Selected = [], barWidth = 2, barColor = "rgb(205, 26, 154)", // Default bar color (red)
@@ -3176,7 +3176,7 @@ const BarPlot = (props) => {
3176
3176
  position: "relative",
3177
3177
  width: "100%",
3178
3178
  height: "100%",
3179
- }, children: jsxRuntime.jsx(Plot, { data: [...plotlyData, ...histogramSubplotData],
3179
+ }, children: jsxRuntime.jsx(Plot$1, { data: [...plotlyData, ...histogramSubplotData],
3180
3180
  // Type doesn't contain "mirror" prop but it works.
3181
3181
  //@ts-ignore
3182
3182
  layout: layout, config: config, useResizeHandler: true, style: {
@@ -3207,6 +3207,388 @@ const BarPlot = (props) => {
3207
3207
  }, children: [barGroupTooltipTitle, ": ", jsxRuntime.jsx("b", { children: barGroupTooltip.label })] }))] }));
3208
3208
  };
3209
3209
 
3210
+ const Plot = React.lazy(() => Promise.resolve().then(function () { return reactPlotlyWrapper$1; }));
3211
+ const StackedBarPlot = (props) => {
3212
+ const { data, histogramData = null, selectedHistogramData = [], barWidth = 2, barColor = "rgb(205, 26, 154)", // Default bar color (red)
3213
+ barColor2 = "rgba(100, 200, 255, 0.7)", // Default histogram bar color (blue)
3214
+ selectedHistogramDataColor = "rgba(255, 0, 0, 0.5)", // Default color for the histogram selection box (red)
3215
+ title = "", title2 = "", // Default title for histogram subplot
3216
+ xAxisTitle = "X Axis", yAxisTitle = "", xAxis2Title = "", yAxis2Title = "", xAccessor = (d) => d.x, yAccessor = (d) => d.y, containerStyleOverrides = {}, plotId = "bar-plot", xAnnotations = [], barHoverTemplate = "", // Default hover template for bars
3217
+ d3FormatValueString = ".1f", } = props;
3218
+ // Ref for plot container
3219
+ const containerRef = React.useRef(null);
3220
+ const plotMetaRef = React.useRef(null);
3221
+ // px above the top of the plot area — lands between x2 tick labels (~15px) and x2 title (~35px)
3222
+ const X_ANNOTATION_TOP_PX = 22;
3223
+ // Tracks the rendered plot area height so we can convert the shape's fixed pixel
3224
+ // center back into a paper y coordinate for the annotation.
3225
+ const [plotAreaHeight, setPlotAreaHeight] = React.useState(300);
3226
+ const capturePlotMeta = (_figure, graphDiv) => {
3227
+ var _a, _b, _c, _d, _e, _f;
3228
+ try {
3229
+ const m = (_a = graphDiv._fullLayout) === null || _a === void 0 ? void 0 : _a.margin;
3230
+ const r = (_c = (_b = graphDiv._fullLayout) === null || _b === void 0 ? void 0 : _b.xaxis) === null || _c === void 0 ? void 0 : _c.range;
3231
+ const h = (_d = graphDiv._fullLayout) === null || _d === void 0 ? void 0 : _d.height;
3232
+ if (m && r) {
3233
+ plotMetaRef.current = {
3234
+ xRange: r,
3235
+ margin: { l: m.l, r: m.r, t: m.t, b: m.b },
3236
+ 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,
3237
+ };
3238
+ if (h) {
3239
+ const newPlotH = h - m.t - m.b;
3240
+ if (newPlotH > 0)
3241
+ setPlotAreaHeight(newPlotH);
3242
+ }
3243
+ }
3244
+ }
3245
+ catch (_g) { }
3246
+ };
3247
+ const y2AxisPosition = 0.72; // Position of the secondary y-axis (histogram) as a fraction of the plot height
3248
+ const plotlyData = data.map((series, index) => {
3249
+ var _a;
3250
+ return ({
3251
+ x: series.data.map((point) => xAccessor(point)),
3252
+ y: series.data.map((point) => yAccessor(point)),
3253
+ customdata: series.data.map((point) => [xAccessor(point) + barWidth]),
3254
+ xaxis: index === 0 ? "x" : `x${index + 2}`, // x, x3, x4, ... (x2 reserved for histogram)
3255
+ yaxis: index === 0 ? "y" : `y${index + 1}`, // Assign y-axis for each series
3256
+ type: "bar",
3257
+ marker: {
3258
+ color: "white", // Use the provided bar color
3259
+ line: {
3260
+ color: (_a = series.color) !== null && _a !== void 0 ? _a : barColor,
3261
+ width: 2,
3262
+ },
3263
+ },
3264
+ width: barWidth, // width centered on the x value.
3265
+ hovertemplate: barHoverTemplate || "%{y}", // Use provided hover template or default to showing y value
3266
+ });
3267
+ });
3268
+ const histogramSubplotData = histogramData
3269
+ ? [
3270
+ {
3271
+ x: histogramData,
3272
+ type: "histogram",
3273
+ marker: {
3274
+ color: barColor2,
3275
+ line: {
3276
+ color: "white",
3277
+ width: 0.5,
3278
+ },
3279
+ },
3280
+ xaxis: "x2", // Use secondary x-axis for histogram
3281
+ yaxis: `y${data.length + 1}`, // Use secondary y-axis for histogram
3282
+ hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>", // Custom hover text
3283
+ },
3284
+ ]
3285
+ : [];
3286
+ const selectedHistogramShape = selectedHistogramData.length === 2 &&
3287
+ selectedHistogramData[0] < selectedHistogramData[1]
3288
+ ? [
3289
+ {
3290
+ type: "rect",
3291
+ x0: selectedHistogramData[0],
3292
+ x1: selectedHistogramData[1],
3293
+ y0: y2AxisPosition, // Start at the top of the histogram subplot
3294
+ y1: 1,
3295
+ yref: "paper",
3296
+ line: {
3297
+ width: 2,
3298
+ color: selectedHistogramDataColor,
3299
+ dash: "dot",
3300
+ },
3301
+ layer: "above", // Ensure the selection box is above the bars
3302
+ },
3303
+ ]
3304
+ : [];
3305
+ // Bar subplots fill the full height when there's no histogram; otherwise they share the bottom portion.
3306
+ const barAreaTop = histogramData ? y2AxisPosition : 1;
3307
+ // Title background shape (when histogramData exists)
3308
+ const titleBackgroundShapes = data.flatMap((series, index) => {
3309
+ var _a, _b;
3310
+ return [
3311
+ {
3312
+ type: "rect",
3313
+ xref: "paper",
3314
+ yref: "paper",
3315
+ x0: 0,
3316
+ y0: (barAreaTop / data.length) * (index + 1) - 0.08, // Position behind the title of each series
3317
+ x1: series.name.length * 0.014, // Approximate width based on title2 length
3318
+ y1: (barAreaTop / data.length) * (index + 1) - 0.02,
3319
+ fillcolor: "rgba(255, 255, 255, 0.5)",
3320
+ line: {
3321
+ color: "rgba(255, 255, 255, 0.5)",
3322
+ width: 0,
3323
+ },
3324
+ layer: "above",
3325
+ },
3326
+ {
3327
+ type: "rect",
3328
+ xref: "paper",
3329
+ yref: "paper",
3330
+ x0: 0,
3331
+ y0: (barAreaTop / data.length) * (index + 1) - 0.08, // Position behind the title of each series
3332
+ x1: 0.01,
3333
+ y1: (barAreaTop / data.length) * (index + 1) - 0.02,
3334
+ fillcolor: (_a = series.color) !== null && _a !== void 0 ? _a : "rgba(255, 255, 255, 0.5)",
3335
+ line: {
3336
+ color: (_b = series.color) !== null && _b !== void 0 ? _b : "rgba(255, 255, 255, 0.5)",
3337
+ width: 0,
3338
+ },
3339
+ layer: "above",
3340
+ },
3341
+ ];
3342
+ });
3343
+ // Add title background shape for histogram
3344
+ titleBackgroundShapes.push({
3345
+ type: "rect",
3346
+ xref: "paper",
3347
+ yref: "paper",
3348
+ x0: 0,
3349
+ y0: 0.96, // Position behind the primary title
3350
+ x1: 0.02 + title.length * 0.01, // Approximate width based on title length 0.3/
3351
+ y1: 1,
3352
+ fillcolor: "rgba(255, 255, 255, 0.5)",
3353
+ line: {
3354
+ color: "rgba(200, 200, 200, 0.5)",
3355
+ width: 0,
3356
+ },
3357
+ layer: "above",
3358
+ });
3359
+ // Title annotation
3360
+ const titleAnnotations = data.map((series, index) => {
3361
+ return {
3362
+ xref: "paper",
3363
+ yref: "paper",
3364
+ x: 0.01,
3365
+ xshift: 2,
3366
+ y: (barAreaTop / data.length) * (index + 1) - 0.05,
3367
+ xanchor: "left",
3368
+ yanchor: "middle",
3369
+ text: series.name,
3370
+ showarrow: false,
3371
+ font: {
3372
+ size: 16,
3373
+ color: "#333",
3374
+ weight: 500,
3375
+ },
3376
+ };
3377
+ });
3378
+ titleAnnotations.push({
3379
+ xref: "paper",
3380
+ yref: "paper",
3381
+ x: 0.01,
3382
+ y: 0.96,
3383
+ xshift: 2,
3384
+ xanchor: "left",
3385
+ yanchor: "middle",
3386
+ text: title2,
3387
+ showarrow: false,
3388
+ font: {
3389
+ size: 16,
3390
+ color: "#333",
3391
+ weight: 500,
3392
+ },
3393
+ });
3394
+ const plotlyYaxes = data.map((_series, index) => ({
3395
+ // title: {
3396
+ // text: yAxisTitle ?? "Count",
3397
+ // standoff: 15,
3398
+ // },
3399
+ domain: [
3400
+ (barAreaTop / data.length) * index,
3401
+ (barAreaTop / data.length) * (index + 1) - 0.02,
3402
+ ],
3403
+ hoverformat: d3FormatValueString,
3404
+ nticks: 3,
3405
+ automargin: true,
3406
+ showgrid: true,
3407
+ zeroline: false,
3408
+ showline: true,
3409
+ mirror: "ticks",
3410
+ gridcolor: "#efefef",
3411
+ gridwidth: 0.2,
3412
+ zerolinecolor: "#969696",
3413
+ zerolinewidth: 1,
3414
+ linecolor: "#bababa",
3415
+ linewidth: 1,
3416
+ fixedrange: true,
3417
+ ticksuffix: " ",
3418
+ }));
3419
+ if (histogramData) {
3420
+ plotlyYaxes.push({
3421
+ title: {
3422
+ text: yAxis2Title,
3423
+ standoff: 12,
3424
+ },
3425
+ domain: [y2AxisPosition, 1],
3426
+ automargin: true,
3427
+ showgrid: true,
3428
+ zeroline: false,
3429
+ showline: true,
3430
+ mirror: "ticks",
3431
+ gridcolor: "#efefef",
3432
+ gridwidth: 0.2,
3433
+ zerolinecolor: "#969696",
3434
+ zerolinewidth: 1,
3435
+ linecolor: "#bababa",
3436
+ linewidth: 1,
3437
+ fixedrange: true,
3438
+ ticksuffix: " ",
3439
+ });
3440
+ }
3441
+ const layout = Object.assign(Object.assign(Object.assign(Object.assign({ showlegend: false, autosize: true, width: undefined, height: undefined, margin: {
3442
+ l: 50,
3443
+ r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
3444
+ t: 40 + (title ? 50 : 0), // Add extra top margin if there is a title
3445
+ b: 70,
3446
+ pad: 4,
3447
+ }, xaxis: {
3448
+ title: {
3449
+ text: xAxisTitle,
3450
+ },
3451
+ anchor: "y", // Anchor to primary y-axis
3452
+ hoverformat: d3FormatValueString, // Format hover values using provided d3 format string
3453
+ showgrid: true,
3454
+ zeroline: false,
3455
+ showline: true,
3456
+ mirror: "ticks",
3457
+ gridcolor: "#efefef",
3458
+ gridwidth: 0.2,
3459
+ zerolinecolor: "#969696",
3460
+ zerolinewidth: 1,
3461
+ linecolor: "#bababa",
3462
+ linewidth: 1,
3463
+ fixedrange: true, // Disable zooming
3464
+ automargin: true, // Adjust margin if tick labels rotate
3465
+ ticklen: 8, // tick length in px.
3466
+ tickcolor: "white",
3467
+ tickformat: d3FormatValueString, // Format ticks using provided d3 format string
3468
+ rangemode: "tozero", // Ensure x-axis starts at zero
3469
+ } }, (histogramData && {
3470
+ xaxis2: {
3471
+ title: {
3472
+ text: xAxis2Title,
3473
+ standoff: 22,
3474
+ },
3475
+ side: "top",
3476
+ anchor: `y${data.length + 1}`, // Anchor to the secondary y-axis (histogram)
3477
+ showgrid: true,
3478
+ zeroline: false,
3479
+ showline: true,
3480
+ mirror: "ticks",
3481
+ showticklabels: true, // Show x-axis tick labels for histogram
3482
+ gridcolor: "#efefef",
3483
+ gridwidth: 0.2,
3484
+ zerolinecolor: "#969696",
3485
+ zerolinewidth: 1,
3486
+ linecolor: "#bababa",
3487
+ linewidth: 1,
3488
+ fixedrange: true,
3489
+ automargin: true,
3490
+ matches: "x", // Match the range of xaxis to keep them synchronized
3491
+ tickformat: d3FormatValueString, // Format ticks using provided d3 format string
3492
+ rangemode: "tozero",
3493
+ },
3494
+ })), plotlyYaxes.reduce((acc, yaxis, index) => {
3495
+ acc[`yaxis${index === 0 ? "" : index + 1}`] = yaxis;
3496
+ return acc;
3497
+ }, {})), data.slice(1).reduce((acc, _series, i) => {
3498
+ acc[`xaxis${i + 3}`] = {
3499
+ anchor: `y${i + 2}`,
3500
+ matches: "x",
3501
+ showticklabels: false,
3502
+ showgrid: true,
3503
+ zeroline: false,
3504
+ showline: true,
3505
+ mirror: "ticks",
3506
+ gridcolor: "#efefef",
3507
+ gridwidth: 0.2,
3508
+ zerolinecolor: "#969696",
3509
+ zerolinewidth: 1,
3510
+ linecolor: "#bababa",
3511
+ linewidth: 1,
3512
+ fixedrange: true,
3513
+ automargin: true,
3514
+ ticklen: 8,
3515
+ tickcolor: "white",
3516
+ tickformat: d3FormatValueString,
3517
+ rangemode: "tozero",
3518
+ };
3519
+ return acc;
3520
+ }, {})), { bargap: 0.03, shapes: [
3521
+ ...titleBackgroundShapes,
3522
+ ...selectedHistogramShape,
3523
+ ...xAnnotations.map((annotation) => ({
3524
+ type: "line",
3525
+ x0: annotation.x,
3526
+ x1: annotation.x,
3527
+ y0: 0,
3528
+ y1: 1 + (X_ANNOTATION_TOP_PX - 4) / plotAreaHeight,
3529
+ xref: "x",
3530
+ yref: "paper",
3531
+ line: {
3532
+ color: annotation.color || "rgba(255, 0, 0, 0.7)",
3533
+ width: 3,
3534
+ },
3535
+ })),
3536
+ ], annotations: [
3537
+ ...titleAnnotations,
3538
+ ...(yAxisTitle
3539
+ ? [
3540
+ {
3541
+ xref: "paper",
3542
+ yref: "paper",
3543
+ x: 0,
3544
+ xshift: -45,
3545
+ y: barAreaTop / 2,
3546
+ xanchor: "center",
3547
+ yanchor: "middle",
3548
+ text: yAxisTitle,
3549
+ showarrow: false,
3550
+ textangle: -90,
3551
+ font: { size: 13, color: "#444" },
3552
+ },
3553
+ ]
3554
+ : []),
3555
+ ...xAnnotations.map((annotation) => ({
3556
+ x: annotation.x,
3557
+ y: 1 + X_ANNOTATION_TOP_PX / plotAreaHeight,
3558
+ xref: "x",
3559
+ yref: "paper",
3560
+ text: annotation.text || "",
3561
+ showarrow: false,
3562
+ yanchor: "bottom",
3563
+ font: {
3564
+ color: annotation.color || "rgba(255, 0, 0, 0.7)",
3565
+ size: 12,
3566
+ },
3567
+ })),
3568
+ ] });
3569
+ const config = {
3570
+ responsive: true, // Make the plot responsive
3571
+ displayModeBar: false, // Hide the mode bar
3572
+ displaylogo: false, // Hide the Plotly logo
3573
+ scrollZoom: false, // Disable zooming with scroll
3574
+ staticPlot: false, // Enable interactivity
3575
+ };
3576
+ const containerStyles = Object.assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
3577
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: `plot-container histogram ${plotId}`, style: Object.assign({}, containerStyles), children: jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx(Loading, {}), children: jsxRuntime.jsx("div", { style: {
3578
+ position: "relative",
3579
+ width: "100%",
3580
+ height: "100%",
3581
+ }, children: jsxRuntime.jsx(Plot, { data: [...plotlyData, ...histogramSubplotData],
3582
+ // Type doesn't contain "mirror" prop but it works.
3583
+ //@ts-ignore
3584
+ layout: layout, config: config, useResizeHandler: true, style: {
3585
+ width: "100%",
3586
+ height: "100%",
3587
+ display: "block",
3588
+ transition: "opacity 0.15s ease-in-out",
3589
+ }, onInitialized: capturePlotMeta, onUpdate: capturePlotMeta }, `bar-${plotId || "default"}`) }) }) }));
3590
+ };
3591
+
3210
3592
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
3211
3593
 
3212
3594
  function getDefaultExportFromCjs (x) {
@@ -100698,6 +101080,7 @@ exports.LineWithHistogram = LineWithHistogram;
100698
101080
  exports.PairedComparisonsBoxPlot = PairedComparisonsBoxPlot;
100699
101081
  exports.RadialHistogramPlot = RadialHistogramPlot;
100700
101082
  exports.SplitBoxPlot = SplitBoxPlot;
101083
+ exports.StackedBarPlot = StackedBarPlot;
100701
101084
  exports.StatsDonut = StatsDonut;
100702
101085
  exports.SummaryComparisonPlot = SummaryComparisonPlot;
100703
101086
  exports.SummaryComparisonPlotLegend = SummaryComparisonPlotLegend;