td-plots 1.5.3 → 1.5.4
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/Histogram.d.ts +4 -3
- package/dist/index.esm.js +228 -170
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +228 -170
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import
|
|
3
|
-
export type HistogramStatsAnnotation =
|
|
1
|
+
import React from "react";
|
|
2
|
+
import "./plotStyles.scss";
|
|
3
|
+
export type HistogramStatsAnnotation = "mean" | "stdev";
|
|
4
4
|
export type HistogramPlotProps = {
|
|
5
5
|
data: number[] | Date[];
|
|
6
6
|
unselectedData?: number[] | Date[];
|
|
@@ -17,6 +17,7 @@ export type HistogramPlotProps = {
|
|
|
17
17
|
dateTickFormat?: string;
|
|
18
18
|
binSizeOverride?: number;
|
|
19
19
|
statsAnnotations?: HistogramStatsAnnotation[];
|
|
20
|
+
emptySelectedRange?: boolean;
|
|
20
21
|
};
|
|
21
22
|
export declare const HistogramPlot: (props: HistogramPlotProps) => import("react/jsx-runtime").JSX.Element;
|
|
22
23
|
export default HistogramPlot;
|
package/dist/index.esm.js
CHANGED
|
@@ -6052,11 +6052,17 @@ var Loading = function () {
|
|
|
6052
6052
|
var Plot$2 = lazy(function () { return import('react-plotly.js'); });
|
|
6053
6053
|
var HistogramPlot = function (props) {
|
|
6054
6054
|
var _a, _b, _c, _d;
|
|
6055
|
-
var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _e = props.barColor, barColor = _e === void 0 ?
|
|
6055
|
+
var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _e = props.barColor, barColor = _e === void 0 ? "rgb(72, 72, 74)" : _e, _f = props.unselectedBarColor, unselectedBarColor = _f === void 0 ? "rgba(203, 195, 195, 0.88)" : _f, _g = props.selectorsColor, selectorsColor = _g === void 0 ? "black" : _g, containerStyleOverrides = props.containerStyleOverrides, _h = props.unselectedData, unselectedData = _h === void 0 ? [] : _h, _j = props.handleClickOrSelection, handleClickOrSelection = _j === void 0 ? function () { } : _j, _k = props.onDeselect, onDeselect = _k === void 0 ? function () { } : _k, plotId = props.plotId, _l = props.selectByBin, selectByBin = _l === void 0 ? false : _l, dateTickFormat = props.dateTickFormat, binSizeOverride = props.binSizeOverride, _m = props.statsAnnotations, statsAnnotations = _m === void 0 ? ["mean"] : _m, _o = props.emptySelectedRange, emptySelectedRange = _o === void 0 ? false : _o;
|
|
6056
6056
|
// Ref for plot container
|
|
6057
6057
|
var containerRef = useRef(null);
|
|
6058
6058
|
// Track any selections made in this plot so we can style the selection box.
|
|
6059
|
-
var
|
|
6059
|
+
var _p = useState(null), selectedRange = _p[0], setSelectedRange = _p[1];
|
|
6060
|
+
// If the parent component wants to clear the selection, reset selectedRange to null.
|
|
6061
|
+
useEffect(function () {
|
|
6062
|
+
if (emptySelectedRange) {
|
|
6063
|
+
setSelectedRange(null);
|
|
6064
|
+
}
|
|
6065
|
+
}, [emptySelectedRange]);
|
|
6060
6066
|
// Combine all data into one for later calculations
|
|
6061
6067
|
var allData = __spreadArray(__spreadArray([], data, true), unselectedData, true);
|
|
6062
6068
|
// If all the data becomes selected, we should forget any old selections.
|
|
@@ -6066,13 +6072,15 @@ var HistogramPlot = function (props) {
|
|
|
6066
6072
|
}
|
|
6067
6073
|
}, [unselectedData]);
|
|
6068
6074
|
// Set the bins based on the entire data set.
|
|
6069
|
-
var nBins =
|
|
6075
|
+
var nBins = data.length + unselectedData.length >= 10
|
|
6076
|
+
? Math.ceil(Math.sqrt(data.length + unselectedData.length))
|
|
6077
|
+
: 0;
|
|
6070
6078
|
// Plotly determines "nice" bins which consequently means it internally decides the axis range. We need
|
|
6071
6079
|
// to access that information once the plot has been initialized so that we can prevent the
|
|
6072
6080
|
// axis range from changing during interaction. Dates use strings.
|
|
6073
|
-
var
|
|
6081
|
+
var _q = useState(undefined), fixedXAxisRange = _q[0], setFixedXAxisRange = _q[1];
|
|
6074
6082
|
// track xbins too
|
|
6075
|
-
var
|
|
6083
|
+
var _r = useState(undefined), binSize = _r[0], setBinSize = _r[1];
|
|
6076
6084
|
// Once the plot is drawn, record the initial axis range so we can keep it fixed.
|
|
6077
6085
|
// figure should be Readonly<Plotly.Figure> but react-plotly.js doesn't expose that type, so we use any.
|
|
6078
6086
|
var handlePlotUpdate = function (figure, graphDiv) {
|
|
@@ -6090,7 +6098,11 @@ var HistogramPlot = function (props) {
|
|
|
6090
6098
|
}
|
|
6091
6099
|
if (!binSize) {
|
|
6092
6100
|
// Get the bin size from the first trace. Both traces should have the same bin size.
|
|
6093
|
-
if (figure &&
|
|
6101
|
+
if (figure &&
|
|
6102
|
+
figure.data &&
|
|
6103
|
+
figure.data.length > 0 &&
|
|
6104
|
+
figure.data[0].xbins &&
|
|
6105
|
+
figure.data[0].xbins.size) {
|
|
6094
6106
|
setBinSize(figure.data[0].xbins.size);
|
|
6095
6107
|
}
|
|
6096
6108
|
}
|
|
@@ -6100,22 +6112,22 @@ var HistogramPlot = function (props) {
|
|
|
6100
6112
|
// Add keyboard event listeners to track shift key
|
|
6101
6113
|
useEffect(function () {
|
|
6102
6114
|
var handleKeyDown = function (e) {
|
|
6103
|
-
if (e.key ===
|
|
6115
|
+
if (e.key === "Shift") {
|
|
6104
6116
|
isShiftPressed.current = true;
|
|
6105
6117
|
}
|
|
6106
6118
|
};
|
|
6107
6119
|
var handleKeyUp = function (e) {
|
|
6108
|
-
if (e.key ===
|
|
6120
|
+
if (e.key === "Shift") {
|
|
6109
6121
|
isShiftPressed.current = false;
|
|
6110
6122
|
}
|
|
6111
6123
|
};
|
|
6112
6124
|
// Add event listeners to document to catch shift key globally
|
|
6113
|
-
document.addEventListener(
|
|
6114
|
-
document.addEventListener(
|
|
6125
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
6126
|
+
document.addEventListener("keyup", handleKeyUp);
|
|
6115
6127
|
// Cleanup
|
|
6116
6128
|
return function () {
|
|
6117
|
-
document.removeEventListener(
|
|
6118
|
-
document.removeEventListener(
|
|
6129
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
6130
|
+
document.removeEventListener("keyup", handleKeyUp);
|
|
6119
6131
|
};
|
|
6120
6132
|
}, []);
|
|
6121
6133
|
// Create handler for click event that can use event data to update the plot if desired.
|
|
@@ -6125,11 +6137,12 @@ var HistogramPlot = function (props) {
|
|
|
6125
6137
|
return;
|
|
6126
6138
|
}
|
|
6127
6139
|
// Use the bin number to determine which bar was clicked and determine the range of the clicked bar.
|
|
6128
|
-
if ("binNumber" in event.points[0] &&
|
|
6140
|
+
if ("binNumber" in event.points[0] &&
|
|
6141
|
+
typeof event.points[0].binNumber === "number") {
|
|
6129
6142
|
// Get the index of the clicked bar with respect to the trace. So if
|
|
6130
6143
|
// my trace has only one bar (0, 1] but another trace has bars (-1, 0], (0, 1], (1, 2], etc.
|
|
6131
6144
|
// then when I click on (0, 1] in my trace the index will be 0, even thought it would be
|
|
6132
|
-
// the second bar in the other trace. Because of this, we can't use data.xbins to
|
|
6145
|
+
// the second bar in the other trace. Because of this, we can't use data.xbins to
|
|
6133
6146
|
// find the clicked bar, because its start and end values are based on all traces, not just the clicked trace.
|
|
6134
6147
|
var clickedBinIndex = event.points[0].binNumber;
|
|
6135
6148
|
// Handle dates and numbers separately
|
|
@@ -6139,26 +6152,35 @@ var HistogramPlot = function (props) {
|
|
|
6139
6152
|
var globalFirstBinStart = void 0;
|
|
6140
6153
|
if (isDateArray(data)) {
|
|
6141
6154
|
// Date bins are represented as strings (sometimes). We'll need to convert whatever plotly gives us to timestamps.
|
|
6142
|
-
globalFirstBinStart = fixedXAxisRange
|
|
6143
|
-
|
|
6155
|
+
globalFirstBinStart = fixedXAxisRange
|
|
6156
|
+
? new Date(fixedXAxisRange[0]).getTime()
|
|
6157
|
+
: new Date(event.points[0].data.xbins.start).getTime();
|
|
6158
|
+
minTraceValue =
|
|
6159
|
+
event.points[0].curveNumber === 0
|
|
6160
|
+
? Math.min.apply(Math, data.map(function (d) { return d.getTime(); })) : Math.min.apply(Math, unselectedData.map(function (d) { return d.getTime(); }));
|
|
6144
6161
|
}
|
|
6145
6162
|
else {
|
|
6146
6163
|
// Get the min value of the trace and the beginning of the first bin (globally)
|
|
6147
|
-
minTraceValue =
|
|
6148
|
-
|
|
6164
|
+
minTraceValue =
|
|
6165
|
+
event.points[0].curveNumber === 0
|
|
6166
|
+
? Math.min.apply(Math, data) : Math.min.apply(Math, unselectedData);
|
|
6167
|
+
globalFirstBinStart = fixedXAxisRange
|
|
6168
|
+
? fixedXAxisRange[0]
|
|
6169
|
+
: event.points[0].data.xbins.start;
|
|
6149
6170
|
}
|
|
6150
6171
|
// Finally, we need to calculate the min and max values of the clicked bin.
|
|
6151
6172
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6152
6173
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6153
6174
|
var size = binSize !== null && binSize !== void 0 ? binSize : (_d = (_c = (_b = (_a = event.points) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.xbins) === null || _d === void 0 ? void 0 : _d.size;
|
|
6154
|
-
var convertedBinSize = typeof size ===
|
|
6175
|
+
var convertedBinSize = typeof size === "string"
|
|
6155
6176
|
? plotlyMToMilliseconds(size)
|
|
6156
6177
|
: size;
|
|
6157
6178
|
// This minTraceValue is in the 0th bin of this trace. Find the index of this bin in the whole plot.
|
|
6158
|
-
var clickedBinGlobalIndex = clickedBinIndex +
|
|
6179
|
+
var clickedBinGlobalIndex = clickedBinIndex +
|
|
6180
|
+
Math.floor((minTraceValue - globalFirstBinStart) / convertedBinSize);
|
|
6159
6181
|
var _e = [
|
|
6160
6182
|
globalFirstBinStart + clickedBinGlobalIndex * convertedBinSize,
|
|
6161
|
-
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize
|
|
6183
|
+
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize,
|
|
6162
6184
|
], minBinValue = _e[0], maxBinValue = _e[1];
|
|
6163
6185
|
if (isDateArray(data)) {
|
|
6164
6186
|
var minDate = new Date(minBinValue);
|
|
@@ -6191,7 +6213,8 @@ var HistogramPlot = function (props) {
|
|
|
6191
6213
|
}
|
|
6192
6214
|
var minValue;
|
|
6193
6215
|
var maxValue;
|
|
6194
|
-
if (typeof event.range.x[0] ===
|
|
6216
|
+
if (typeof event.range.x[0] === "string" &&
|
|
6217
|
+
typeof event.range.x[1] === "string") {
|
|
6195
6218
|
// Then we are must be dealing with dates
|
|
6196
6219
|
if (selectByBin) {
|
|
6197
6220
|
// Set selected range to include the whole bin if at least half the bin is within the explicit range
|
|
@@ -6202,7 +6225,7 @@ var HistogramPlot = function (props) {
|
|
|
6202
6225
|
var lastBinMidPoint = new Date(event.points[event.points.length - 1].x).getTime();
|
|
6203
6226
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6204
6227
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6205
|
-
var convertedBinSize = typeof binSize ===
|
|
6228
|
+
var convertedBinSize = typeof binSize === "string"
|
|
6206
6229
|
? plotlyMToMilliseconds(binSize)
|
|
6207
6230
|
: binSize;
|
|
6208
6231
|
minValue = new Date(firstBinMidPoint - convertedBinSize / 2);
|
|
@@ -6249,7 +6272,7 @@ var HistogramPlot = function (props) {
|
|
|
6249
6272
|
}
|
|
6250
6273
|
if (minValue !== undefined && maxValue !== undefined) {
|
|
6251
6274
|
// Update selected range. Have to be strict about types.
|
|
6252
|
-
if (typeof minValue ===
|
|
6275
|
+
if (typeof minValue === "number" && typeof maxValue === "number") {
|
|
6253
6276
|
var newMinMax = [minValue, maxValue];
|
|
6254
6277
|
if (isShiftPressed.current && selectedRange) {
|
|
6255
6278
|
setSelectedRange(__spreadArray(__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
@@ -6277,128 +6300,146 @@ var HistogramPlot = function (props) {
|
|
|
6277
6300
|
if (unselectedData.length === 0)
|
|
6278
6301
|
return []; // Don't show the box if the entire dataset is selected.
|
|
6279
6302
|
// Create a multiply-like effect by using a semi-transparent dark overlay
|
|
6280
|
-
var multiplyColor =
|
|
6303
|
+
var multiplyColor = "rgba(29, 104, 185, 0.1)";
|
|
6281
6304
|
return selectedRange.map(function (maxMin) { return ({
|
|
6282
|
-
type:
|
|
6305
|
+
type: "rect",
|
|
6283
6306
|
x0: isDateArray(maxMin) ? maxMin[0].getTime() : maxMin[0],
|
|
6284
6307
|
x1: isDateArray(maxMin) ? maxMin[1].getTime() : maxMin[1],
|
|
6285
6308
|
y0: 0,
|
|
6286
6309
|
y1: 1,
|
|
6287
|
-
yref:
|
|
6310
|
+
yref: "paper",
|
|
6288
6311
|
fillcolor: multiplyColor,
|
|
6289
6312
|
line: {
|
|
6290
6313
|
width: 1,
|
|
6291
|
-
color: multiplyColor
|
|
6314
|
+
color: multiplyColor,
|
|
6292
6315
|
},
|
|
6293
|
-
layer:
|
|
6316
|
+
layer: "above", // Ensure the selection box is above the bars
|
|
6294
6317
|
}); });
|
|
6295
6318
|
}, [selectedRange, unselectedData]);
|
|
6296
6319
|
// Calculate the mean of the selected data using normalized data
|
|
6297
6320
|
var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
|
|
6298
6321
|
var stdevValue = (_b = calculateStandardDeviation(data)) !== null && _b !== void 0 ? _b : 0;
|
|
6299
6322
|
var meanLineRadius = 0.01; // distance from the top of the y axis to the top/bottom end of the mean line
|
|
6300
|
-
var meanLine =
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6323
|
+
var meanLine = statsAnnotations.includes("mean") && data.length > 0
|
|
6324
|
+
? [
|
|
6325
|
+
{
|
|
6326
|
+
type: "line",
|
|
6327
|
+
x0: meanValue,
|
|
6328
|
+
y0: 1 - meanLineRadius,
|
|
6329
|
+
x1: meanValue,
|
|
6330
|
+
yref: "paper",
|
|
6331
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6332
|
+
line: {
|
|
6333
|
+
color: barColor,
|
|
6334
|
+
width: 1.5,
|
|
6335
|
+
},
|
|
6336
|
+
},
|
|
6337
|
+
]
|
|
6338
|
+
: [];
|
|
6312
6339
|
// Draw mean line for all data
|
|
6313
6340
|
var allDataMeanValue = (_c = calculateMean(allData)) !== null && _c !== void 0 ? _c : 0;
|
|
6314
|
-
var allDataMeanLine =
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6341
|
+
var allDataMeanLine = statsAnnotations.includes("mean") &&
|
|
6342
|
+
unselectedData.length > 0 &&
|
|
6343
|
+
data.length > 0
|
|
6344
|
+
? [
|
|
6345
|
+
{
|
|
6346
|
+
type: "line",
|
|
6347
|
+
x0: allDataMeanValue,
|
|
6348
|
+
y0: 1 - meanLineRadius,
|
|
6349
|
+
x1: allDataMeanValue,
|
|
6350
|
+
yref: "paper",
|
|
6351
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6352
|
+
line: {
|
|
6353
|
+
color: unselectedBarColor,
|
|
6354
|
+
width: 1.5,
|
|
6355
|
+
},
|
|
6356
|
+
},
|
|
6357
|
+
]
|
|
6358
|
+
: [];
|
|
6359
|
+
var stdevLines = statsAnnotations.includes("stdev") && data.length > 0
|
|
6360
|
+
? [
|
|
6361
|
+
{
|
|
6362
|
+
type: "line",
|
|
6363
|
+
x0: meanValue - stdevValue,
|
|
6364
|
+
y0: 1 - meanLineRadius,
|
|
6365
|
+
x1: meanValue - stdevValue,
|
|
6366
|
+
yref: "paper",
|
|
6367
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6368
|
+
line: {
|
|
6369
|
+
color: barColor,
|
|
6370
|
+
width: 1.5,
|
|
6371
|
+
dash: "dot",
|
|
6372
|
+
},
|
|
6373
|
+
},
|
|
6374
|
+
{
|
|
6375
|
+
type: "line",
|
|
6376
|
+
x0: meanValue + stdevValue,
|
|
6377
|
+
y0: 1 - meanLineRadius,
|
|
6378
|
+
x1: meanValue + stdevValue,
|
|
6379
|
+
yref: "paper",
|
|
6380
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6381
|
+
line: {
|
|
6382
|
+
color: barColor,
|
|
6383
|
+
width: 1.5,
|
|
6384
|
+
dash: "dot",
|
|
6385
|
+
},
|
|
6386
|
+
},
|
|
6387
|
+
]
|
|
6352
6388
|
: [];
|
|
6353
6389
|
var allDataStdevValue = (_d = calculateStandardDeviation(allData)) !== null && _d !== void 0 ? _d : 0;
|
|
6354
|
-
var allDataStdevLines =
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6390
|
+
var allDataStdevLines = statsAnnotations.includes("stdev") &&
|
|
6391
|
+
unselectedData.length > 0 &&
|
|
6392
|
+
data.length > 0
|
|
6393
|
+
? [
|
|
6394
|
+
{
|
|
6395
|
+
type: "line",
|
|
6396
|
+
x0: allDataMeanValue - allDataStdevValue,
|
|
6397
|
+
y0: 1 - meanLineRadius,
|
|
6398
|
+
x1: allDataMeanValue - allDataStdevValue,
|
|
6399
|
+
yref: "paper",
|
|
6400
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6401
|
+
line: {
|
|
6402
|
+
color: unselectedBarColor,
|
|
6403
|
+
width: 1.5,
|
|
6404
|
+
dash: "dot",
|
|
6405
|
+
},
|
|
6406
|
+
},
|
|
6407
|
+
{
|
|
6408
|
+
type: "line",
|
|
6409
|
+
x0: allDataMeanValue + allDataStdevValue,
|
|
6410
|
+
y0: 1 - meanLineRadius,
|
|
6411
|
+
x1: allDataMeanValue + allDataStdevValue,
|
|
6412
|
+
yref: "paper",
|
|
6413
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6414
|
+
line: {
|
|
6415
|
+
color: unselectedBarColor,
|
|
6416
|
+
width: 1.5,
|
|
6417
|
+
dash: "dot",
|
|
6418
|
+
},
|
|
6419
|
+
},
|
|
6420
|
+
]
|
|
6380
6421
|
: [];
|
|
6381
|
-
// If binSizeOverride is provided, use it to set the bin size and range explicitly.
|
|
6422
|
+
// If binSizeOverride is provided, use it to set the bin size and range explicitly.
|
|
6382
6423
|
// Plotly does a better job of setting bins and ending them at nice numbers, so only use
|
|
6383
6424
|
// this prop when necessary.
|
|
6384
|
-
var xBins =
|
|
6385
|
-
?
|
|
6425
|
+
var xBins = binSizeOverride && allData.length > 0
|
|
6426
|
+
? isDateArray(allData)
|
|
6386
6427
|
? {
|
|
6387
6428
|
start: roundToPrevDay(Math.min.apply(Math, allData.map(function (d) { return d.getTime(); }))), // Find a nice round number as a starting point.
|
|
6388
6429
|
end: roundToNextDay(Math.max.apply(Math, allData.map(function (d) { return d.getTime(); }))),
|
|
6389
|
-
size: binSizeOverride // bin size in milliseconds
|
|
6430
|
+
size: binSizeOverride, // bin size in milliseconds
|
|
6390
6431
|
}
|
|
6391
6432
|
: isNumberArray(allData)
|
|
6392
6433
|
? {
|
|
6393
6434
|
start: Math.floor(Math.min.apply(Math, allData)),
|
|
6394
6435
|
end: Math.ceil(Math.max.apply(Math, allData)),
|
|
6395
|
-
size: binSizeOverride
|
|
6436
|
+
size: binSizeOverride,
|
|
6396
6437
|
}
|
|
6397
|
-
: undefined
|
|
6438
|
+
: undefined
|
|
6398
6439
|
: undefined;
|
|
6399
6440
|
var unselectedTrace = {
|
|
6400
6441
|
x: unselectedData,
|
|
6401
|
-
type:
|
|
6442
|
+
type: "histogram",
|
|
6402
6443
|
autobinx: false,
|
|
6403
6444
|
xbins: xBins,
|
|
6404
6445
|
// nbinsx is valid but not included in the type definition
|
|
@@ -6411,59 +6452,73 @@ var HistogramPlot = function (props) {
|
|
|
6411
6452
|
width: 0.5,
|
|
6412
6453
|
},
|
|
6413
6454
|
},
|
|
6414
|
-
hovertemplate:
|
|
6455
|
+
hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>",
|
|
6415
6456
|
};
|
|
6416
|
-
var meanAnnotation =
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6457
|
+
var meanAnnotation = statsAnnotations.includes("mean") && meanLine && data.length > 0
|
|
6458
|
+
? [
|
|
6459
|
+
{
|
|
6460
|
+
x: meanValue,
|
|
6461
|
+
y: 1 + meanLineRadius + 0.04, // Position above the mean line. Value set with respect to the paper coordinates.
|
|
6462
|
+
yref: "paper",
|
|
6463
|
+
text: "<span style=\"font-weight:300\">AVG </span><span style=\"font-weight:600\">".concat(isDateArray(data)
|
|
6464
|
+
? new Date(meanValue).toLocaleDateString("en-US", {
|
|
6465
|
+
month: "2-digit",
|
|
6466
|
+
day: "2-digit",
|
|
6467
|
+
year: "2-digit",
|
|
6468
|
+
})
|
|
6469
|
+
: meanValue.toFixed(2), "</span>"),
|
|
6470
|
+
xanchor: "center",
|
|
6471
|
+
yanchor: "bottom",
|
|
6472
|
+
showarrow: false,
|
|
6473
|
+
font: {
|
|
6474
|
+
color: barColor,
|
|
6475
|
+
size: 12,
|
|
6476
|
+
},
|
|
6431
6477
|
},
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6478
|
+
]
|
|
6479
|
+
: [];
|
|
6480
|
+
var stdevAnnotation = statsAnnotations.includes("stdev") && stdevLines && data.length > 0
|
|
6481
|
+
? [
|
|
6482
|
+
{
|
|
6483
|
+
x: meanValue, // Draw above the mean annotation
|
|
6484
|
+
y: 1 +
|
|
6485
|
+
meanLineRadius +
|
|
6486
|
+
(statsAnnotations.includes("mean") ? 0.11 : 0.04),
|
|
6487
|
+
yref: "paper",
|
|
6488
|
+
text: "<span style=\"font-weight:300\">\u03C3 </span><span style=\"font-weight:600\">±".concat(isDateArray(data)
|
|
6489
|
+
? new Date(stdevValue).toLocaleDateString("en-US", {
|
|
6490
|
+
month: "2-digit",
|
|
6491
|
+
day: "2-digit",
|
|
6492
|
+
year: "2-digit",
|
|
6493
|
+
})
|
|
6494
|
+
: stdevValue.toFixed(2), "</span>"),
|
|
6495
|
+
xanchor: "center",
|
|
6496
|
+
yanchor: "bottom",
|
|
6497
|
+
showarrow: false,
|
|
6498
|
+
font: {
|
|
6499
|
+
color: barColor,
|
|
6500
|
+
size: 12,
|
|
6501
|
+
},
|
|
6448
6502
|
},
|
|
6449
|
-
|
|
6503
|
+
]
|
|
6504
|
+
: [];
|
|
6450
6505
|
var plotlyData = [
|
|
6451
6506
|
{
|
|
6452
6507
|
x: data,
|
|
6453
|
-
type:
|
|
6508
|
+
type: "histogram",
|
|
6454
6509
|
autobinx: false,
|
|
6455
6510
|
xbins: xBins,
|
|
6456
6511
|
// nbinsx is valid but not included in the type definition
|
|
6457
6512
|
//@ts-ignore
|
|
6458
6513
|
nbinsx: nBins, // Maximum number of bins. Plotly may adjust to make bins "nicer".
|
|
6459
6514
|
marker: {
|
|
6460
|
-
color: barColor !== null && barColor !== void 0 ? barColor :
|
|
6515
|
+
color: barColor !== null && barColor !== void 0 ? barColor : "blue",
|
|
6461
6516
|
line: {
|
|
6462
6517
|
color: "white",
|
|
6463
6518
|
width: 0.5,
|
|
6464
6519
|
},
|
|
6465
6520
|
},
|
|
6466
|
-
hovertemplate:
|
|
6521
|
+
hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>", // Custom hover text
|
|
6467
6522
|
},
|
|
6468
6523
|
unselectedTrace,
|
|
6469
6524
|
];
|
|
@@ -6471,63 +6526,66 @@ var HistogramPlot = function (props) {
|
|
|
6471
6526
|
title: {
|
|
6472
6527
|
text: title,
|
|
6473
6528
|
},
|
|
6474
|
-
barmode:
|
|
6529
|
+
barmode: "stack", // Stack unselected bars on top of selected bars
|
|
6475
6530
|
showlegend: false,
|
|
6476
6531
|
autosize: true,
|
|
6477
6532
|
width: undefined, // Let autosize handle width
|
|
6478
6533
|
height: undefined, // Let autosize handle height
|
|
6479
6534
|
margin: {
|
|
6480
6535
|
l: 50,
|
|
6481
|
-
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
6536
|
+
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
6482
6537
|
t: 40 + (title ? 50 : 0), // Add extra top margin if there is a title
|
|
6483
6538
|
b: 50,
|
|
6484
|
-
pad: 4
|
|
6539
|
+
pad: 4,
|
|
6485
6540
|
},
|
|
6486
6541
|
xaxis: {
|
|
6487
6542
|
title: {
|
|
6488
|
-
text: xAxisTitle
|
|
6543
|
+
text: xAxisTitle,
|
|
6489
6544
|
},
|
|
6490
6545
|
range: fixedXAxisRange, // Fixed range prevents axis shifting during interaction or data updates
|
|
6491
6546
|
showgrid: true,
|
|
6492
6547
|
zeroline: false,
|
|
6493
6548
|
showline: true,
|
|
6494
|
-
mirror:
|
|
6495
|
-
gridcolor:
|
|
6549
|
+
mirror: "ticks",
|
|
6550
|
+
gridcolor: "#efefef",
|
|
6496
6551
|
gridwidth: 0.2,
|
|
6497
|
-
zerolinecolor:
|
|
6552
|
+
zerolinecolor: "#969696",
|
|
6498
6553
|
zerolinewidth: 1,
|
|
6499
|
-
linecolor:
|
|
6554
|
+
linecolor: "#bababa",
|
|
6500
6555
|
linewidth: 1,
|
|
6501
6556
|
fixedrange: true, // Disable zooming
|
|
6502
|
-
ticklabelposition:
|
|
6557
|
+
ticklabelposition: "outside",
|
|
6503
6558
|
tickformat: isDateArray(data) ? dateTickFormat : undefined, // Format ticks for dates
|
|
6504
6559
|
automargin: true, // Adjust margin if tick labels rotate
|
|
6505
|
-
hoverformat:
|
|
6560
|
+
hoverformat: isNumberArray(allData) &&
|
|
6561
|
+
Math.max.apply(Math, allData) - Math.min.apply(Math, allData) > 3
|
|
6562
|
+
? ".1~f"
|
|
6563
|
+
: undefined,
|
|
6506
6564
|
},
|
|
6507
6565
|
yaxis: {
|
|
6508
6566
|
title: {
|
|
6509
|
-
text:
|
|
6567
|
+
text: "Count",
|
|
6510
6568
|
standoff: 12, // Add space between title and axis
|
|
6511
6569
|
},
|
|
6512
6570
|
automargin: true, // Required for standoff to work properly
|
|
6513
6571
|
showgrid: true,
|
|
6514
6572
|
zeroline: false,
|
|
6515
6573
|
showline: true,
|
|
6516
|
-
mirror:
|
|
6517
|
-
gridcolor:
|
|
6574
|
+
mirror: "ticks",
|
|
6575
|
+
gridcolor: "#efefef",
|
|
6518
6576
|
gridwidth: 0.2,
|
|
6519
|
-
zerolinecolor:
|
|
6577
|
+
zerolinecolor: "#969696",
|
|
6520
6578
|
zerolinewidth: 1,
|
|
6521
|
-
linecolor:
|
|
6579
|
+
linecolor: "#bababa",
|
|
6522
6580
|
linewidth: 1,
|
|
6523
6581
|
fixedrange: true, // Disable zooming
|
|
6524
|
-
ticksuffix:
|
|
6582
|
+
ticksuffix: " ", // Add space between y axis and ticks
|
|
6525
6583
|
},
|
|
6526
6584
|
bargap: 0.03, // Gap between bars
|
|
6527
|
-
dragmode:
|
|
6528
|
-
selectdirection:
|
|
6585
|
+
dragmode: "select", // Enable drag to select
|
|
6586
|
+
selectdirection: "h", // User can select in horizontal direction only
|
|
6529
6587
|
shapes: __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], allDataMeanLine, true), meanLine, true), selectedRangeBox, true), stdevLines, true), allDataStdevLines, true), // Add the mean line and selection box
|
|
6530
|
-
annotations: __spreadArray(__spreadArray([], meanAnnotation, true), stdevAnnotation, true)
|
|
6588
|
+
annotations: __spreadArray(__spreadArray([], meanAnnotation, true), stdevAnnotation, true),
|
|
6531
6589
|
};
|
|
6532
6590
|
var config = {
|
|
6533
6591
|
responsive: true, // Make the plot responsive
|
|
@@ -6537,14 +6595,14 @@ var HistogramPlot = function (props) {
|
|
|
6537
6595
|
staticPlot: false, // Enable interactivity
|
|
6538
6596
|
};
|
|
6539
6597
|
var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
6540
|
-
return (jsx("div", { ref: containerRef, className: "plot-container ".concat(plotId), style: __assign({
|
|
6598
|
+
return (jsx("div", { ref: containerRef, className: "plot-container ".concat(plotId), style: __assign({ "--selection-color": selectorsColor }, containerStyles), children: jsx(Suspense, { fallback: jsx(Loading, {}), children: jsx(Fragment, { children: jsx(Plot$2, { data: plotlyData, layout: layout, config: config, onSelected: handleSelection, onClick: handleClick, onDeselect: function () {
|
|
6541
6599
|
onDeselect();
|
|
6542
6600
|
setSelectedRange(null); // Remove selected box
|
|
6543
6601
|
}, onUpdate: handlePlotUpdate, useResizeHandler: true, style: {
|
|
6544
6602
|
width: "100%",
|
|
6545
6603
|
height: "100%",
|
|
6546
|
-
display: "block"
|
|
6547
|
-
} }, "histogram-".concat(plotId ||
|
|
6604
|
+
display: "block",
|
|
6605
|
+
} }, "histogram-".concat(plotId || "default")) }) }) }));
|
|
6548
6606
|
};
|
|
6549
6607
|
|
|
6550
6608
|
var Plot$1 = lazy(function () { return import('react-plotly.js'); });
|