td-plots 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Histogram.d.ts +1 -1
- package/dist/index.esm.js +103 -77
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +103 -77
- 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;
|
|
@@ -6100,6 +6077,8 @@ var HistogramPlot = function (props) {
|
|
|
6100
6077
|
var containerRef = React.useRef(null);
|
|
6101
6078
|
// Track any selections made in this plot so we can style the selection box.
|
|
6102
6079
|
var _o = React.useState(null), selectedRange = _o[0], setSelectedRange = _o[1];
|
|
6080
|
+
// Combine all data into one for later calculations
|
|
6081
|
+
var allData = tslib.__spreadArray(tslib.__spreadArray([], data, true), unselectedData, true);
|
|
6103
6082
|
// If all the data becomes selected, we should forget any old selections.
|
|
6104
6083
|
React.useEffect(function () {
|
|
6105
6084
|
if (unselectedData.length === 0) {
|
|
@@ -6112,6 +6091,8 @@ var HistogramPlot = function (props) {
|
|
|
6112
6091
|
// to access that information once the plot has been initialized so that we can prevent the
|
|
6113
6092
|
// axis range from changing during interaction. Dates use strings.
|
|
6114
6093
|
var _p = React.useState(undefined), fixedXAxisRange = _p[0], setFixedXAxisRange = _p[1];
|
|
6094
|
+
// track xbins too
|
|
6095
|
+
var _q = React.useState(undefined), binSize = _q[0], setBinSize = _q[1];
|
|
6115
6096
|
// Once the plot is drawn, record the initial axis range so we can keep it fixed.
|
|
6116
6097
|
// figure should be Readonly<Plotly.Figure> but react-plotly.js doesn't expose that type, so we use any.
|
|
6117
6098
|
var handlePlotUpdate = function (figure, graphDiv) {
|
|
@@ -6127,17 +6108,42 @@ var HistogramPlot = function (props) {
|
|
|
6127
6108
|
setFixedXAxisRange(range);
|
|
6128
6109
|
}
|
|
6129
6110
|
}
|
|
6111
|
+
if (!binSize) {
|
|
6112
|
+
// Get the bin size from the first trace. Both traces should have the same bin size.
|
|
6113
|
+
if (figure && figure.data && figure.data.length > 0 && figure.data[0].xbins && figure.data[0].xbins.size) {
|
|
6114
|
+
setBinSize(figure.data[0].xbins.size);
|
|
6115
|
+
}
|
|
6116
|
+
}
|
|
6130
6117
|
};
|
|
6118
|
+
// Track shift key state
|
|
6119
|
+
var isShiftPressed = React.useRef(false);
|
|
6120
|
+
// Add keyboard event listeners to track shift key
|
|
6121
|
+
React.useEffect(function () {
|
|
6122
|
+
var handleKeyDown = function (e) {
|
|
6123
|
+
if (e.key === 'Shift') {
|
|
6124
|
+
isShiftPressed.current = true;
|
|
6125
|
+
}
|
|
6126
|
+
};
|
|
6127
|
+
var handleKeyUp = function (e) {
|
|
6128
|
+
if (e.key === 'Shift') {
|
|
6129
|
+
isShiftPressed.current = false;
|
|
6130
|
+
}
|
|
6131
|
+
};
|
|
6132
|
+
// Add event listeners to document to catch shift key globally
|
|
6133
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
6134
|
+
document.addEventListener('keyup', handleKeyUp);
|
|
6135
|
+
// Cleanup
|
|
6136
|
+
return function () {
|
|
6137
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
6138
|
+
document.removeEventListener('keyup', handleKeyUp);
|
|
6139
|
+
};
|
|
6140
|
+
}, []);
|
|
6131
6141
|
// Create handler for click event that can use event data to update the plot if desired.
|
|
6132
6142
|
var handleClick = function (event) {
|
|
6143
|
+
var _a, _b, _c, _d;
|
|
6133
6144
|
if (!event || !event.points || event.points.length === 0) {
|
|
6134
6145
|
return;
|
|
6135
6146
|
}
|
|
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
6147
|
// Use the bin number to determine which bar was clicked and determine the range of the clicked bar.
|
|
6142
6148
|
if ("binNumber" in event.points[0] && typeof event.points[0].binNumber === 'number') {
|
|
6143
6149
|
// Get the index of the clicked bar with respect to the trace. So if
|
|
@@ -6153,40 +6159,48 @@ var HistogramPlot = function (props) {
|
|
|
6153
6159
|
var globalFirstBinStart = void 0;
|
|
6154
6160
|
if (isDateArray(data)) {
|
|
6155
6161
|
// Date bins are represented as strings (sometimes). We'll need to convert whatever plotly gives us to timestamps.
|
|
6156
|
-
globalFirstBinStart =
|
|
6157
|
-
minTraceValue = Math.min.apply(Math, data.map(function (d) { return d.getTime(); }));
|
|
6162
|
+
globalFirstBinStart = fixedXAxisRange ? new Date(fixedXAxisRange[0]).getTime() : new Date(event.points[0].data.xbins.start).getTime();
|
|
6163
|
+
minTraceValue = (event.points[0].curveNumber === 0) ? Math.min.apply(Math, data.map(function (d) { return d.getTime(); })) : Math.min.apply(Math, unselectedData.map(function (d) { return d.getTime(); }));
|
|
6158
6164
|
}
|
|
6159
6165
|
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
6166
|
// Get the min value of the trace and the beginning of the first bin (globally)
|
|
6166
|
-
minTraceValue = Math.min.apply(Math, data);
|
|
6167
|
-
globalFirstBinStart = event.points[0].data.xbins.start;
|
|
6167
|
+
minTraceValue = (event.points[0].curveNumber === 0) ? Math.min.apply(Math, data) : Math.min.apply(Math, unselectedData);
|
|
6168
|
+
globalFirstBinStart = fixedXAxisRange ? fixedXAxisRange[0] : event.points[0].data.xbins.start;
|
|
6168
6169
|
}
|
|
6169
6170
|
// Finally, we need to calculate the min and max values of the clicked bin.
|
|
6170
6171
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6171
6172
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6172
|
-
var binSize =
|
|
6173
|
-
|
|
6174
|
-
|
|
6173
|
+
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;
|
|
6174
|
+
var convertedBinSize = typeof size === 'string'
|
|
6175
|
+
? plotlyMToMilliseconds(size)
|
|
6176
|
+
: size;
|
|
6175
6177
|
// This minTraceValue is in the 0th bin of this trace. Find the index of this bin in the whole plot.
|
|
6176
|
-
var clickedBinGlobalIndex = clickedBinIndex + Math.floor((minTraceValue - globalFirstBinStart) /
|
|
6177
|
-
var
|
|
6178
|
-
globalFirstBinStart + clickedBinGlobalIndex *
|
|
6179
|
-
globalFirstBinStart + (clickedBinGlobalIndex + 1) *
|
|
6180
|
-
], minBinValue =
|
|
6178
|
+
var clickedBinGlobalIndex = clickedBinIndex + Math.floor((minTraceValue - globalFirstBinStart) / convertedBinSize);
|
|
6179
|
+
var _e = [
|
|
6180
|
+
globalFirstBinStart + clickedBinGlobalIndex * convertedBinSize,
|
|
6181
|
+
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize
|
|
6182
|
+
], minBinValue = _e[0], maxBinValue = _e[1];
|
|
6181
6183
|
if (isDateArray(data)) {
|
|
6182
6184
|
var minDate = new Date(minBinValue);
|
|
6183
6185
|
var maxDate = new Date(maxBinValue);
|
|
6184
|
-
handleClickOrSelection(minDate, maxDate);
|
|
6185
|
-
|
|
6186
|
+
handleClickOrSelection(minDate, maxDate, isShiftPressed.current);
|
|
6187
|
+
var newMinMax = [minDate, maxDate];
|
|
6188
|
+
if (isShiftPressed.current && selectedRange) {
|
|
6189
|
+
setSelectedRange(tslib.__spreadArray(tslib.__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
6190
|
+
}
|
|
6191
|
+
else {
|
|
6192
|
+
setSelectedRange([newMinMax]);
|
|
6193
|
+
}
|
|
6186
6194
|
}
|
|
6187
6195
|
else {
|
|
6188
|
-
handleClickOrSelection(minBinValue, maxBinValue);
|
|
6189
|
-
|
|
6196
|
+
handleClickOrSelection(minBinValue, maxBinValue, isShiftPressed.current);
|
|
6197
|
+
var newMinMax = [minBinValue, maxBinValue];
|
|
6198
|
+
if (isShiftPressed.current && selectedRange) {
|
|
6199
|
+
setSelectedRange(tslib.__spreadArray(tslib.__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
6200
|
+
}
|
|
6201
|
+
else {
|
|
6202
|
+
setSelectedRange([newMinMax]);
|
|
6203
|
+
}
|
|
6190
6204
|
}
|
|
6191
6205
|
}
|
|
6192
6206
|
};
|
|
@@ -6208,11 +6222,11 @@ var HistogramPlot = function (props) {
|
|
|
6208
6222
|
var lastBinMidPoint = new Date(event.points[event.points.length - 1].x).getTime();
|
|
6209
6223
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6210
6224
|
// 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 +
|
|
6225
|
+
var convertedBinSize = typeof binSize === 'string'
|
|
6226
|
+
? plotlyMToMilliseconds(binSize)
|
|
6227
|
+
: binSize;
|
|
6228
|
+
minValue = new Date(firstBinMidPoint - convertedBinSize / 2);
|
|
6229
|
+
maxValue = new Date(lastBinMidPoint + convertedBinSize / 2);
|
|
6216
6230
|
}
|
|
6217
6231
|
else {
|
|
6218
6232
|
// No bins selected, so the range should be empty.
|
|
@@ -6232,11 +6246,12 @@ var HistogramPlot = function (props) {
|
|
|
6232
6246
|
// Set the range based on the bins selected. Plotly will include a bin in event.points if
|
|
6233
6247
|
// at least half of it is selected.
|
|
6234
6248
|
if (event.points && event.points.length > 0) {
|
|
6235
|
-
|
|
6236
|
-
var
|
|
6237
|
-
var
|
|
6238
|
-
var
|
|
6239
|
-
var
|
|
6249
|
+
// Find the max and min midpoints. They may be from curve 0 or 1.
|
|
6250
|
+
var firstBinMidPoint = Math.min.apply(Math, event.points.map(function (p) { return p.x; }));
|
|
6251
|
+
var lastBinMidPoint = Math.max.apply(Math, event.points.map(function (p) { return p.x; }));
|
|
6252
|
+
var convertedBinSize = binSize;
|
|
6253
|
+
var roundedMinValue = firstBinMidPoint - convertedBinSize / 2;
|
|
6254
|
+
var roundedMaxValue = lastBinMidPoint + convertedBinSize / 2;
|
|
6240
6255
|
minValue = roundedMinValue;
|
|
6241
6256
|
maxValue = roundedMaxValue;
|
|
6242
6257
|
}
|
|
@@ -6255,12 +6270,24 @@ var HistogramPlot = function (props) {
|
|
|
6255
6270
|
if (minValue !== undefined && maxValue !== undefined) {
|
|
6256
6271
|
// Update selected range. Have to be strict about types.
|
|
6257
6272
|
if (typeof minValue === 'number' && typeof maxValue === 'number') {
|
|
6258
|
-
|
|
6273
|
+
var newMinMax = [minValue, maxValue];
|
|
6274
|
+
if (isShiftPressed.current && selectedRange) {
|
|
6275
|
+
setSelectedRange(tslib.__spreadArray(tslib.__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
6276
|
+
}
|
|
6277
|
+
else {
|
|
6278
|
+
setSelectedRange([newMinMax]);
|
|
6279
|
+
}
|
|
6259
6280
|
}
|
|
6260
6281
|
else if (minValue instanceof Date && maxValue instanceof Date) {
|
|
6261
|
-
|
|
6282
|
+
var newMinMax = [minValue, maxValue];
|
|
6283
|
+
if (isShiftPressed.current && selectedRange) {
|
|
6284
|
+
setSelectedRange(tslib.__spreadArray(tslib.__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
6285
|
+
}
|
|
6286
|
+
else {
|
|
6287
|
+
setSelectedRange([newMinMax]);
|
|
6288
|
+
}
|
|
6262
6289
|
}
|
|
6263
|
-
handleClickOrSelection(minValue, maxValue);
|
|
6290
|
+
handleClickOrSelection(minValue, maxValue, isShiftPressed.current);
|
|
6264
6291
|
}
|
|
6265
6292
|
};
|
|
6266
6293
|
// Create the selected range box
|
|
@@ -6271,20 +6298,20 @@ var HistogramPlot = function (props) {
|
|
|
6271
6298
|
return []; // Don't show the box if the entire dataset is selected.
|
|
6272
6299
|
// Create a multiply-like effect by using a semi-transparent dark overlay
|
|
6273
6300
|
var multiplyColor = 'rgba(29, 104, 185, 0.1)';
|
|
6274
|
-
return
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6301
|
+
return selectedRange.map(function (maxMin) { return ({
|
|
6302
|
+
type: 'rect',
|
|
6303
|
+
x0: isDateArray(maxMin) ? maxMin[0].getTime() : maxMin[0],
|
|
6304
|
+
x1: isDateArray(maxMin) ? maxMin[1].getTime() : maxMin[1],
|
|
6305
|
+
y0: 0,
|
|
6306
|
+
y1: 1,
|
|
6307
|
+
yref: 'paper',
|
|
6308
|
+
fillcolor: multiplyColor,
|
|
6309
|
+
line: {
|
|
6310
|
+
width: 1,
|
|
6311
|
+
color: multiplyColor
|
|
6312
|
+
},
|
|
6313
|
+
layer: 'above' // Ensure the selection box is above the bars
|
|
6314
|
+
}); });
|
|
6288
6315
|
}, [selectedRange, unselectedData]);
|
|
6289
6316
|
// Calculate the mean of the selected data using normalized data
|
|
6290
6317
|
var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
|
|
@@ -6303,7 +6330,6 @@ var HistogramPlot = function (props) {
|
|
|
6303
6330
|
}
|
|
6304
6331
|
}] : [];
|
|
6305
6332
|
// Draw mean line for all data
|
|
6306
|
-
var allData = tslib.__spreadArray(tslib.__spreadArray([], data, true), unselectedData, true);
|
|
6307
6333
|
var allDataMeanValue = (_c = calculateMean(allData)) !== null && _c !== void 0 ? _c : 0;
|
|
6308
6334
|
var allDataMeanLine = (statsAnnotations.includes('mean') && unselectedData.length > 0 && data.length > 0) ? [{
|
|
6309
6335
|
type: 'line',
|