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