td-plots 1.5.3 → 1.5.5
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 -3
- package/dist/index.esm.js +539 -171
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +539 -171
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -56,6 +56,319 @@ function styleInject(css, ref) {
|
|
|
56
56
|
var css_248z = ".plot-container{height:100%;max-width:100%;min-height:300px;overflow:hidden!important;position:relative;width:100%}.plot-container>div{flex:1;height:100%!important;width:100%!important}.plot-container .main-svg{max-height:100%!important;max-width:100%!important}.plot-container .main-svg,.plot-container .plotly-graph-div,.plot-container svg.main-svg[height],.plot-container svg.main-svg[width]{height:100%!important;width:100%!important}.plot-container .point{border-radius:5px!important;overflow:hidden!important}.plot-container .cursor-ns-resize{height:0;width:0}.plot-container .cursor-ew-resize{fill:var(--selection-color,blue)!important;stroke:var(--selection-color,blue)!important}.plot-container .selectionlayer>path{stroke:var(--selection-color,blue)!important;stroke-dasharray:0!important;stroke-width:1px!important;opacity:.5!important}.plot-container .zoomlayer>path{stroke-dasharray:0!important;stroke:var(--selection-color,blue)!important;fill:var(--selection-color,blue)!important}.radial-histogram-container{aspect-ratio:1}.loading-overlay{align-items:center;background-color:hsla(0,0%,100%,.8);display:flex;height:100%;justify-content:center;left:0;position:absolute;top:0;width:100%;z-index:300}";
|
|
57
57
|
styleInject(css_248z);
|
|
58
58
|
|
|
59
|
+
function formatDecimal(x) {
|
|
60
|
+
return Math.abs(x = Math.round(x)) >= 1e21
|
|
61
|
+
? x.toLocaleString("en").replace(/,/g, "")
|
|
62
|
+
: x.toString(10);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Computes the decimal coefficient and exponent of the specified number x with
|
|
66
|
+
// significant digits p, where x is positive and p is in [1, 21] or undefined.
|
|
67
|
+
// For example, formatDecimalParts(1.23) returns ["123", 0].
|
|
68
|
+
function formatDecimalParts(x, p) {
|
|
69
|
+
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
|
|
70
|
+
var i, coefficient = x.slice(0, i);
|
|
71
|
+
|
|
72
|
+
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
|
|
73
|
+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
|
|
74
|
+
return [
|
|
75
|
+
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
|
|
76
|
+
+x.slice(i + 1)
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function exponent(x) {
|
|
81
|
+
return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function formatGroup(grouping, thousands) {
|
|
85
|
+
return function(value, width) {
|
|
86
|
+
var i = value.length,
|
|
87
|
+
t = [],
|
|
88
|
+
j = 0,
|
|
89
|
+
g = grouping[0],
|
|
90
|
+
length = 0;
|
|
91
|
+
|
|
92
|
+
while (i > 0 && g > 0) {
|
|
93
|
+
if (length + g + 1 > width) g = Math.max(1, width - length);
|
|
94
|
+
t.push(value.substring(i -= g, i + g));
|
|
95
|
+
if ((length += g + 1) > width) break;
|
|
96
|
+
g = grouping[j = (j + 1) % grouping.length];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return t.reverse().join(thousands);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function formatNumerals(numerals) {
|
|
104
|
+
return function(value) {
|
|
105
|
+
return value.replace(/[0-9]/g, function(i) {
|
|
106
|
+
return numerals[+i];
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
|
|
112
|
+
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
|
|
113
|
+
|
|
114
|
+
function formatSpecifier(specifier) {
|
|
115
|
+
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
|
|
116
|
+
var match;
|
|
117
|
+
return new FormatSpecifier({
|
|
118
|
+
fill: match[1],
|
|
119
|
+
align: match[2],
|
|
120
|
+
sign: match[3],
|
|
121
|
+
symbol: match[4],
|
|
122
|
+
zero: match[5],
|
|
123
|
+
width: match[6],
|
|
124
|
+
comma: match[7],
|
|
125
|
+
precision: match[8] && match[8].slice(1),
|
|
126
|
+
trim: match[9],
|
|
127
|
+
type: match[10]
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
|
|
132
|
+
|
|
133
|
+
function FormatSpecifier(specifier) {
|
|
134
|
+
this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
|
|
135
|
+
this.align = specifier.align === undefined ? ">" : specifier.align + "";
|
|
136
|
+
this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
|
|
137
|
+
this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
|
|
138
|
+
this.zero = !!specifier.zero;
|
|
139
|
+
this.width = specifier.width === undefined ? undefined : +specifier.width;
|
|
140
|
+
this.comma = !!specifier.comma;
|
|
141
|
+
this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
|
|
142
|
+
this.trim = !!specifier.trim;
|
|
143
|
+
this.type = specifier.type === undefined ? "" : specifier.type + "";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
FormatSpecifier.prototype.toString = function() {
|
|
147
|
+
return this.fill
|
|
148
|
+
+ this.align
|
|
149
|
+
+ this.sign
|
|
150
|
+
+ this.symbol
|
|
151
|
+
+ (this.zero ? "0" : "")
|
|
152
|
+
+ (this.width === undefined ? "" : Math.max(1, this.width | 0))
|
|
153
|
+
+ (this.comma ? "," : "")
|
|
154
|
+
+ (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
|
|
155
|
+
+ (this.trim ? "~" : "")
|
|
156
|
+
+ this.type;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
|
|
160
|
+
function formatTrim(s) {
|
|
161
|
+
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
|
|
162
|
+
switch (s[i]) {
|
|
163
|
+
case ".": i0 = i1 = i; break;
|
|
164
|
+
case "0": if (i0 === 0) i0 = i; i1 = i; break;
|
|
165
|
+
default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
var prefixExponent;
|
|
172
|
+
|
|
173
|
+
function formatPrefixAuto(x, p) {
|
|
174
|
+
var d = formatDecimalParts(x, p);
|
|
175
|
+
if (!d) return x + "";
|
|
176
|
+
var coefficient = d[0],
|
|
177
|
+
exponent = d[1],
|
|
178
|
+
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
|
|
179
|
+
n = coefficient.length;
|
|
180
|
+
return i === n ? coefficient
|
|
181
|
+
: i > n ? coefficient + new Array(i - n + 1).join("0")
|
|
182
|
+
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
|
|
183
|
+
: "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function formatRounded(x, p) {
|
|
187
|
+
var d = formatDecimalParts(x, p);
|
|
188
|
+
if (!d) return x + "";
|
|
189
|
+
var coefficient = d[0],
|
|
190
|
+
exponent = d[1];
|
|
191
|
+
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
|
|
192
|
+
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
|
|
193
|
+
: coefficient + new Array(exponent - coefficient.length + 2).join("0");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var formatTypes = {
|
|
197
|
+
"%": (x, p) => (x * 100).toFixed(p),
|
|
198
|
+
"b": (x) => Math.round(x).toString(2),
|
|
199
|
+
"c": (x) => x + "",
|
|
200
|
+
"d": formatDecimal,
|
|
201
|
+
"e": (x, p) => x.toExponential(p),
|
|
202
|
+
"f": (x, p) => x.toFixed(p),
|
|
203
|
+
"g": (x, p) => x.toPrecision(p),
|
|
204
|
+
"o": (x) => Math.round(x).toString(8),
|
|
205
|
+
"p": (x, p) => formatRounded(x * 100, p),
|
|
206
|
+
"r": formatRounded,
|
|
207
|
+
"s": formatPrefixAuto,
|
|
208
|
+
"X": (x) => Math.round(x).toString(16).toUpperCase(),
|
|
209
|
+
"x": (x) => Math.round(x).toString(16)
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
function identity(x) {
|
|
213
|
+
return x;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
var map = Array.prototype.map,
|
|
217
|
+
prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
|
|
218
|
+
|
|
219
|
+
function formatLocale(locale) {
|
|
220
|
+
var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""),
|
|
221
|
+
currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
|
|
222
|
+
currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
|
|
223
|
+
decimal = locale.decimal === undefined ? "." : locale.decimal + "",
|
|
224
|
+
numerals = locale.numerals === undefined ? identity : formatNumerals(map.call(locale.numerals, String)),
|
|
225
|
+
percent = locale.percent === undefined ? "%" : locale.percent + "",
|
|
226
|
+
minus = locale.minus === undefined ? "−" : locale.minus + "",
|
|
227
|
+
nan = locale.nan === undefined ? "NaN" : locale.nan + "";
|
|
228
|
+
|
|
229
|
+
function newFormat(specifier) {
|
|
230
|
+
specifier = formatSpecifier(specifier);
|
|
231
|
+
|
|
232
|
+
var fill = specifier.fill,
|
|
233
|
+
align = specifier.align,
|
|
234
|
+
sign = specifier.sign,
|
|
235
|
+
symbol = specifier.symbol,
|
|
236
|
+
zero = specifier.zero,
|
|
237
|
+
width = specifier.width,
|
|
238
|
+
comma = specifier.comma,
|
|
239
|
+
precision = specifier.precision,
|
|
240
|
+
trim = specifier.trim,
|
|
241
|
+
type = specifier.type;
|
|
242
|
+
|
|
243
|
+
// The "n" type is an alias for ",g".
|
|
244
|
+
if (type === "n") comma = true, type = "g";
|
|
245
|
+
|
|
246
|
+
// The "" type, and any invalid type, is an alias for ".12~g".
|
|
247
|
+
else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";
|
|
248
|
+
|
|
249
|
+
// If zero fill is specified, padding goes after sign and before digits.
|
|
250
|
+
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
|
|
251
|
+
|
|
252
|
+
// Compute the prefix and suffix.
|
|
253
|
+
// For SI-prefix, the suffix is lazily computed.
|
|
254
|
+
var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
|
|
255
|
+
suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "";
|
|
256
|
+
|
|
257
|
+
// What format function should we use?
|
|
258
|
+
// Is this an integer type?
|
|
259
|
+
// Can this type generate exponential notation?
|
|
260
|
+
var formatType = formatTypes[type],
|
|
261
|
+
maybeSuffix = /[defgprs%]/.test(type);
|
|
262
|
+
|
|
263
|
+
// Set the default precision if not specified,
|
|
264
|
+
// or clamp the specified precision to the supported range.
|
|
265
|
+
// For significant precision, it must be in [1, 21].
|
|
266
|
+
// For fixed precision, it must be in [0, 20].
|
|
267
|
+
precision = precision === undefined ? 6
|
|
268
|
+
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
|
|
269
|
+
: Math.max(0, Math.min(20, precision));
|
|
270
|
+
|
|
271
|
+
function format(value) {
|
|
272
|
+
var valuePrefix = prefix,
|
|
273
|
+
valueSuffix = suffix,
|
|
274
|
+
i, n, c;
|
|
275
|
+
|
|
276
|
+
if (type === "c") {
|
|
277
|
+
valueSuffix = formatType(value) + valueSuffix;
|
|
278
|
+
value = "";
|
|
279
|
+
} else {
|
|
280
|
+
value = +value;
|
|
281
|
+
|
|
282
|
+
// Determine the sign. -0 is not less than 0, but 1 / -0 is!
|
|
283
|
+
var valueNegative = value < 0 || 1 / value < 0;
|
|
284
|
+
|
|
285
|
+
// Perform the initial formatting.
|
|
286
|
+
value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
|
|
287
|
+
|
|
288
|
+
// Trim insignificant zeros.
|
|
289
|
+
if (trim) value = formatTrim(value);
|
|
290
|
+
|
|
291
|
+
// If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
|
|
292
|
+
if (valueNegative && +value === 0 && sign !== "+") valueNegative = false;
|
|
293
|
+
|
|
294
|
+
// Compute the prefix and suffix.
|
|
295
|
+
valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
|
|
296
|
+
valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
|
|
297
|
+
|
|
298
|
+
// Break the formatted value into the integer “value” part that can be
|
|
299
|
+
// grouped, and fractional or exponential “suffix” part that is not.
|
|
300
|
+
if (maybeSuffix) {
|
|
301
|
+
i = -1, n = value.length;
|
|
302
|
+
while (++i < n) {
|
|
303
|
+
if (c = value.charCodeAt(i), 48 > c || c > 57) {
|
|
304
|
+
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
|
|
305
|
+
value = value.slice(0, i);
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// If the fill character is not "0", grouping is applied before padding.
|
|
313
|
+
if (comma && !zero) value = group(value, Infinity);
|
|
314
|
+
|
|
315
|
+
// Compute the padding.
|
|
316
|
+
var length = valuePrefix.length + value.length + valueSuffix.length,
|
|
317
|
+
padding = length < width ? new Array(width - length + 1).join(fill) : "";
|
|
318
|
+
|
|
319
|
+
// If the fill character is "0", grouping is applied after padding.
|
|
320
|
+
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
|
|
321
|
+
|
|
322
|
+
// Reconstruct the final output based on the desired alignment.
|
|
323
|
+
switch (align) {
|
|
324
|
+
case "<": value = valuePrefix + value + valueSuffix + padding; break;
|
|
325
|
+
case "=": value = valuePrefix + padding + value + valueSuffix; break;
|
|
326
|
+
case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
|
|
327
|
+
default: value = padding + valuePrefix + value + valueSuffix; break;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return numerals(value);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
format.toString = function() {
|
|
334
|
+
return specifier + "";
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
return format;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function formatPrefix(specifier, value) {
|
|
341
|
+
var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
|
|
342
|
+
e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
|
|
343
|
+
k = Math.pow(10, -e),
|
|
344
|
+
prefix = prefixes[8 + e / 3];
|
|
345
|
+
return function(value) {
|
|
346
|
+
return f(k * value) + prefix;
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
format: newFormat,
|
|
352
|
+
formatPrefix: formatPrefix
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
var locale;
|
|
357
|
+
var format;
|
|
358
|
+
|
|
359
|
+
defaultLocale({
|
|
360
|
+
thousands: ",",
|
|
361
|
+
grouping: [3],
|
|
362
|
+
currency: ["$", ""]
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
function defaultLocale(definition) {
|
|
366
|
+
locale = formatLocale(definition);
|
|
367
|
+
format = locale.format;
|
|
368
|
+
locale.formatPrefix;
|
|
369
|
+
return locale;
|
|
370
|
+
}
|
|
371
|
+
|
|
59
372
|
// Utility functions for our components
|
|
60
373
|
var ONEAVGMONTH = 2629800000; // Average month length in ms, copied from plotly constants in plotly.js/src/constants/numerical.js
|
|
61
374
|
// Type guard to check if array contains only numbers
|
|
@@ -6072,11 +6385,17 @@ var Loading = function () {
|
|
|
6072
6385
|
var Plot$2 = React.lazy(function () { return import('react-plotly.js'); });
|
|
6073
6386
|
var HistogramPlot = function (props) {
|
|
6074
6387
|
var _a, _b, _c, _d;
|
|
6075
|
-
var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _e = props.barColor, barColor = _e === void 0 ?
|
|
6388
|
+
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, _p = props.d3FormatValueString, d3FormatValueString = _p === void 0 ? ".1f" : _p;
|
|
6076
6389
|
// Ref for plot container
|
|
6077
6390
|
var containerRef = React.useRef(null);
|
|
6078
6391
|
// Track any selections made in this plot so we can style the selection box.
|
|
6079
|
-
var
|
|
6392
|
+
var _q = React.useState(null), selectedRange = _q[0], setSelectedRange = _q[1];
|
|
6393
|
+
// If the parent component wants to clear the selection, reset selectedRange to null.
|
|
6394
|
+
React.useEffect(function () {
|
|
6395
|
+
if (emptySelectedRange) {
|
|
6396
|
+
setSelectedRange(null);
|
|
6397
|
+
}
|
|
6398
|
+
}, [emptySelectedRange]);
|
|
6080
6399
|
// Combine all data into one for later calculations
|
|
6081
6400
|
var allData = tslib.__spreadArray(tslib.__spreadArray([], data, true), unselectedData, true);
|
|
6082
6401
|
// If all the data becomes selected, we should forget any old selections.
|
|
@@ -6086,13 +6405,15 @@ var HistogramPlot = function (props) {
|
|
|
6086
6405
|
}
|
|
6087
6406
|
}, [unselectedData]);
|
|
6088
6407
|
// Set the bins based on the entire data set.
|
|
6089
|
-
var nBins =
|
|
6408
|
+
var nBins = data.length + unselectedData.length >= 10
|
|
6409
|
+
? Math.ceil(Math.sqrt(data.length + unselectedData.length))
|
|
6410
|
+
: 0;
|
|
6090
6411
|
// Plotly determines "nice" bins which consequently means it internally decides the axis range. We need
|
|
6091
6412
|
// to access that information once the plot has been initialized so that we can prevent the
|
|
6092
6413
|
// axis range from changing during interaction. Dates use strings.
|
|
6093
|
-
var
|
|
6414
|
+
var _r = React.useState(undefined), fixedXAxisRange = _r[0], setFixedXAxisRange = _r[1];
|
|
6094
6415
|
// track xbins too
|
|
6095
|
-
var
|
|
6416
|
+
var _s = React.useState(undefined), binSize = _s[0], setBinSize = _s[1];
|
|
6096
6417
|
// Once the plot is drawn, record the initial axis range so we can keep it fixed.
|
|
6097
6418
|
// figure should be Readonly<Plotly.Figure> but react-plotly.js doesn't expose that type, so we use any.
|
|
6098
6419
|
var handlePlotUpdate = function (figure, graphDiv) {
|
|
@@ -6110,7 +6431,11 @@ var HistogramPlot = function (props) {
|
|
|
6110
6431
|
}
|
|
6111
6432
|
if (!binSize) {
|
|
6112
6433
|
// Get the bin size from the first trace. Both traces should have the same bin size.
|
|
6113
|
-
if (figure &&
|
|
6434
|
+
if (figure &&
|
|
6435
|
+
figure.data &&
|
|
6436
|
+
figure.data.length > 0 &&
|
|
6437
|
+
figure.data[0].xbins &&
|
|
6438
|
+
figure.data[0].xbins.size) {
|
|
6114
6439
|
setBinSize(figure.data[0].xbins.size);
|
|
6115
6440
|
}
|
|
6116
6441
|
}
|
|
@@ -6120,22 +6445,22 @@ var HistogramPlot = function (props) {
|
|
|
6120
6445
|
// Add keyboard event listeners to track shift key
|
|
6121
6446
|
React.useEffect(function () {
|
|
6122
6447
|
var handleKeyDown = function (e) {
|
|
6123
|
-
if (e.key ===
|
|
6448
|
+
if (e.key === "Shift") {
|
|
6124
6449
|
isShiftPressed.current = true;
|
|
6125
6450
|
}
|
|
6126
6451
|
};
|
|
6127
6452
|
var handleKeyUp = function (e) {
|
|
6128
|
-
if (e.key ===
|
|
6453
|
+
if (e.key === "Shift") {
|
|
6129
6454
|
isShiftPressed.current = false;
|
|
6130
6455
|
}
|
|
6131
6456
|
};
|
|
6132
6457
|
// Add event listeners to document to catch shift key globally
|
|
6133
|
-
document.addEventListener(
|
|
6134
|
-
document.addEventListener(
|
|
6458
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
6459
|
+
document.addEventListener("keyup", handleKeyUp);
|
|
6135
6460
|
// Cleanup
|
|
6136
6461
|
return function () {
|
|
6137
|
-
document.removeEventListener(
|
|
6138
|
-
document.removeEventListener(
|
|
6462
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
6463
|
+
document.removeEventListener("keyup", handleKeyUp);
|
|
6139
6464
|
};
|
|
6140
6465
|
}, []);
|
|
6141
6466
|
// Create handler for click event that can use event data to update the plot if desired.
|
|
@@ -6145,11 +6470,12 @@ var HistogramPlot = function (props) {
|
|
|
6145
6470
|
return;
|
|
6146
6471
|
}
|
|
6147
6472
|
// Use the bin number to determine which bar was clicked and determine the range of the clicked bar.
|
|
6148
|
-
if ("binNumber" in event.points[0] &&
|
|
6473
|
+
if ("binNumber" in event.points[0] &&
|
|
6474
|
+
typeof event.points[0].binNumber === "number") {
|
|
6149
6475
|
// Get the index of the clicked bar with respect to the trace. So if
|
|
6150
6476
|
// my trace has only one bar (0, 1] but another trace has bars (-1, 0], (0, 1], (1, 2], etc.
|
|
6151
6477
|
// then when I click on (0, 1] in my trace the index will be 0, even thought it would be
|
|
6152
|
-
// the second bar in the other trace. Because of this, we can't use data.xbins to
|
|
6478
|
+
// the second bar in the other trace. Because of this, we can't use data.xbins to
|
|
6153
6479
|
// find the clicked bar, because its start and end values are based on all traces, not just the clicked trace.
|
|
6154
6480
|
var clickedBinIndex = event.points[0].binNumber;
|
|
6155
6481
|
// Handle dates and numbers separately
|
|
@@ -6159,26 +6485,35 @@ var HistogramPlot = function (props) {
|
|
|
6159
6485
|
var globalFirstBinStart = void 0;
|
|
6160
6486
|
if (isDateArray(data)) {
|
|
6161
6487
|
// Date bins are represented as strings (sometimes). We'll need to convert whatever plotly gives us to timestamps.
|
|
6162
|
-
globalFirstBinStart = fixedXAxisRange
|
|
6163
|
-
|
|
6488
|
+
globalFirstBinStart = fixedXAxisRange
|
|
6489
|
+
? new Date(fixedXAxisRange[0]).getTime()
|
|
6490
|
+
: new Date(event.points[0].data.xbins.start).getTime();
|
|
6491
|
+
minTraceValue =
|
|
6492
|
+
event.points[0].curveNumber === 0
|
|
6493
|
+
? Math.min.apply(Math, data.map(function (d) { return d.getTime(); })) : Math.min.apply(Math, unselectedData.map(function (d) { return d.getTime(); }));
|
|
6164
6494
|
}
|
|
6165
6495
|
else {
|
|
6166
6496
|
// Get the min value of the trace and the beginning of the first bin (globally)
|
|
6167
|
-
minTraceValue =
|
|
6168
|
-
|
|
6497
|
+
minTraceValue =
|
|
6498
|
+
event.points[0].curveNumber === 0
|
|
6499
|
+
? Math.min.apply(Math, data) : Math.min.apply(Math, unselectedData);
|
|
6500
|
+
globalFirstBinStart = fixedXAxisRange
|
|
6501
|
+
? fixedXAxisRange[0]
|
|
6502
|
+
: event.points[0].data.xbins.start;
|
|
6169
6503
|
}
|
|
6170
6504
|
// Finally, we need to calculate the min and max values of the clicked bin.
|
|
6171
6505
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6172
6506
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6173
6507
|
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 ===
|
|
6508
|
+
var convertedBinSize = typeof size === "string"
|
|
6175
6509
|
? plotlyMToMilliseconds(size)
|
|
6176
6510
|
: size;
|
|
6177
6511
|
// This minTraceValue is in the 0th bin of this trace. Find the index of this bin in the whole plot.
|
|
6178
|
-
var clickedBinGlobalIndex = clickedBinIndex +
|
|
6512
|
+
var clickedBinGlobalIndex = clickedBinIndex +
|
|
6513
|
+
Math.floor((minTraceValue - globalFirstBinStart) / convertedBinSize);
|
|
6179
6514
|
var _e = [
|
|
6180
6515
|
globalFirstBinStart + clickedBinGlobalIndex * convertedBinSize,
|
|
6181
|
-
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize
|
|
6516
|
+
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize,
|
|
6182
6517
|
], minBinValue = _e[0], maxBinValue = _e[1];
|
|
6183
6518
|
if (isDateArray(data)) {
|
|
6184
6519
|
var minDate = new Date(minBinValue);
|
|
@@ -6211,7 +6546,8 @@ var HistogramPlot = function (props) {
|
|
|
6211
6546
|
}
|
|
6212
6547
|
var minValue;
|
|
6213
6548
|
var maxValue;
|
|
6214
|
-
if (typeof event.range.x[0] ===
|
|
6549
|
+
if (typeof event.range.x[0] === "string" &&
|
|
6550
|
+
typeof event.range.x[1] === "string") {
|
|
6215
6551
|
// Then we are must be dealing with dates
|
|
6216
6552
|
if (selectByBin) {
|
|
6217
6553
|
// Set selected range to include the whole bin if at least half the bin is within the explicit range
|
|
@@ -6222,7 +6558,7 @@ var HistogramPlot = function (props) {
|
|
|
6222
6558
|
var lastBinMidPoint = new Date(event.points[event.points.length - 1].x).getTime();
|
|
6223
6559
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6224
6560
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6225
|
-
var convertedBinSize = typeof binSize ===
|
|
6561
|
+
var convertedBinSize = typeof binSize === "string"
|
|
6226
6562
|
? plotlyMToMilliseconds(binSize)
|
|
6227
6563
|
: binSize;
|
|
6228
6564
|
minValue = new Date(firstBinMidPoint - convertedBinSize / 2);
|
|
@@ -6269,7 +6605,7 @@ var HistogramPlot = function (props) {
|
|
|
6269
6605
|
}
|
|
6270
6606
|
if (minValue !== undefined && maxValue !== undefined) {
|
|
6271
6607
|
// Update selected range. Have to be strict about types.
|
|
6272
|
-
if (typeof minValue ===
|
|
6608
|
+
if (typeof minValue === "number" && typeof maxValue === "number") {
|
|
6273
6609
|
var newMinMax = [minValue, maxValue];
|
|
6274
6610
|
if (isShiftPressed.current && selectedRange) {
|
|
6275
6611
|
setSelectedRange(tslib.__spreadArray(tslib.__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
@@ -6297,128 +6633,146 @@ var HistogramPlot = function (props) {
|
|
|
6297
6633
|
if (unselectedData.length === 0)
|
|
6298
6634
|
return []; // Don't show the box if the entire dataset is selected.
|
|
6299
6635
|
// Create a multiply-like effect by using a semi-transparent dark overlay
|
|
6300
|
-
var multiplyColor =
|
|
6636
|
+
var multiplyColor = "rgba(29, 104, 185, 0.1)";
|
|
6301
6637
|
return selectedRange.map(function (maxMin) { return ({
|
|
6302
|
-
type:
|
|
6638
|
+
type: "rect",
|
|
6303
6639
|
x0: isDateArray(maxMin) ? maxMin[0].getTime() : maxMin[0],
|
|
6304
6640
|
x1: isDateArray(maxMin) ? maxMin[1].getTime() : maxMin[1],
|
|
6305
6641
|
y0: 0,
|
|
6306
6642
|
y1: 1,
|
|
6307
|
-
yref:
|
|
6643
|
+
yref: "paper",
|
|
6308
6644
|
fillcolor: multiplyColor,
|
|
6309
6645
|
line: {
|
|
6310
6646
|
width: 1,
|
|
6311
|
-
color: multiplyColor
|
|
6647
|
+
color: multiplyColor,
|
|
6312
6648
|
},
|
|
6313
|
-
layer:
|
|
6649
|
+
layer: "above", // Ensure the selection box is above the bars
|
|
6314
6650
|
}); });
|
|
6315
6651
|
}, [selectedRange, unselectedData]);
|
|
6316
6652
|
// Calculate the mean of the selected data using normalized data
|
|
6317
6653
|
var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
|
|
6318
6654
|
var stdevValue = (_b = calculateStandardDeviation(data)) !== null && _b !== void 0 ? _b : 0;
|
|
6319
6655
|
var meanLineRadius = 0.01; // distance from the top of the y axis to the top/bottom end of the mean line
|
|
6320
|
-
var meanLine =
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6656
|
+
var meanLine = statsAnnotations.includes("mean") && data.length > 0
|
|
6657
|
+
? [
|
|
6658
|
+
{
|
|
6659
|
+
type: "line",
|
|
6660
|
+
x0: meanValue,
|
|
6661
|
+
y0: 1 - meanLineRadius,
|
|
6662
|
+
x1: meanValue,
|
|
6663
|
+
yref: "paper",
|
|
6664
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6665
|
+
line: {
|
|
6666
|
+
color: barColor,
|
|
6667
|
+
width: 1.5,
|
|
6668
|
+
},
|
|
6669
|
+
},
|
|
6670
|
+
]
|
|
6671
|
+
: [];
|
|
6332
6672
|
// Draw mean line for all data
|
|
6333
6673
|
var allDataMeanValue = (_c = calculateMean(allData)) !== null && _c !== void 0 ? _c : 0;
|
|
6334
|
-
var allDataMeanLine =
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6674
|
+
var allDataMeanLine = statsAnnotations.includes("mean") &&
|
|
6675
|
+
unselectedData.length > 0 &&
|
|
6676
|
+
data.length > 0
|
|
6677
|
+
? [
|
|
6678
|
+
{
|
|
6679
|
+
type: "line",
|
|
6680
|
+
x0: allDataMeanValue,
|
|
6681
|
+
y0: 1 - meanLineRadius,
|
|
6682
|
+
x1: allDataMeanValue,
|
|
6683
|
+
yref: "paper",
|
|
6684
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6685
|
+
line: {
|
|
6686
|
+
color: unselectedBarColor,
|
|
6687
|
+
width: 1.5,
|
|
6688
|
+
},
|
|
6689
|
+
},
|
|
6690
|
+
]
|
|
6691
|
+
: [];
|
|
6692
|
+
var stdevLines = statsAnnotations.includes("stdev") && data.length > 0
|
|
6693
|
+
? [
|
|
6694
|
+
{
|
|
6695
|
+
type: "line",
|
|
6696
|
+
x0: meanValue - stdevValue,
|
|
6697
|
+
y0: 1 - meanLineRadius,
|
|
6698
|
+
x1: meanValue - stdevValue,
|
|
6699
|
+
yref: "paper",
|
|
6700
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6701
|
+
line: {
|
|
6702
|
+
color: barColor,
|
|
6703
|
+
width: 1.5,
|
|
6704
|
+
dash: "dot",
|
|
6705
|
+
},
|
|
6706
|
+
},
|
|
6707
|
+
{
|
|
6708
|
+
type: "line",
|
|
6709
|
+
x0: meanValue + stdevValue,
|
|
6710
|
+
y0: 1 - meanLineRadius,
|
|
6711
|
+
x1: meanValue + stdevValue,
|
|
6712
|
+
yref: "paper",
|
|
6713
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6714
|
+
line: {
|
|
6715
|
+
color: barColor,
|
|
6716
|
+
width: 1.5,
|
|
6717
|
+
dash: "dot",
|
|
6718
|
+
},
|
|
6719
|
+
},
|
|
6720
|
+
]
|
|
6372
6721
|
: [];
|
|
6373
6722
|
var allDataStdevValue = (_d = calculateStandardDeviation(allData)) !== null && _d !== void 0 ? _d : 0;
|
|
6374
|
-
var allDataStdevLines =
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6723
|
+
var allDataStdevLines = statsAnnotations.includes("stdev") &&
|
|
6724
|
+
unselectedData.length > 0 &&
|
|
6725
|
+
data.length > 0
|
|
6726
|
+
? [
|
|
6727
|
+
{
|
|
6728
|
+
type: "line",
|
|
6729
|
+
x0: allDataMeanValue - allDataStdevValue,
|
|
6730
|
+
y0: 1 - meanLineRadius,
|
|
6731
|
+
x1: allDataMeanValue - allDataStdevValue,
|
|
6732
|
+
yref: "paper",
|
|
6733
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6734
|
+
line: {
|
|
6735
|
+
color: unselectedBarColor,
|
|
6736
|
+
width: 1.5,
|
|
6737
|
+
dash: "dot",
|
|
6738
|
+
},
|
|
6739
|
+
},
|
|
6740
|
+
{
|
|
6741
|
+
type: "line",
|
|
6742
|
+
x0: allDataMeanValue + allDataStdevValue,
|
|
6743
|
+
y0: 1 - meanLineRadius,
|
|
6744
|
+
x1: allDataMeanValue + allDataStdevValue,
|
|
6745
|
+
yref: "paper",
|
|
6746
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6747
|
+
line: {
|
|
6748
|
+
color: unselectedBarColor,
|
|
6749
|
+
width: 1.5,
|
|
6750
|
+
dash: "dot",
|
|
6751
|
+
},
|
|
6752
|
+
},
|
|
6753
|
+
]
|
|
6400
6754
|
: [];
|
|
6401
|
-
// If binSizeOverride is provided, use it to set the bin size and range explicitly.
|
|
6755
|
+
// If binSizeOverride is provided, use it to set the bin size and range explicitly.
|
|
6402
6756
|
// Plotly does a better job of setting bins and ending them at nice numbers, so only use
|
|
6403
6757
|
// this prop when necessary.
|
|
6404
|
-
var xBins =
|
|
6405
|
-
?
|
|
6758
|
+
var xBins = binSizeOverride && allData.length > 0
|
|
6759
|
+
? isDateArray(allData)
|
|
6406
6760
|
? {
|
|
6407
6761
|
start: roundToPrevDay(Math.min.apply(Math, allData.map(function (d) { return d.getTime(); }))), // Find a nice round number as a starting point.
|
|
6408
6762
|
end: roundToNextDay(Math.max.apply(Math, allData.map(function (d) { return d.getTime(); }))),
|
|
6409
|
-
size: binSizeOverride // bin size in milliseconds
|
|
6763
|
+
size: binSizeOverride, // bin size in milliseconds
|
|
6410
6764
|
}
|
|
6411
6765
|
: isNumberArray(allData)
|
|
6412
6766
|
? {
|
|
6413
6767
|
start: Math.floor(Math.min.apply(Math, allData)),
|
|
6414
6768
|
end: Math.ceil(Math.max.apply(Math, allData)),
|
|
6415
|
-
size: binSizeOverride
|
|
6769
|
+
size: binSizeOverride,
|
|
6416
6770
|
}
|
|
6417
|
-
: undefined
|
|
6771
|
+
: undefined
|
|
6418
6772
|
: undefined;
|
|
6419
6773
|
var unselectedTrace = {
|
|
6420
6774
|
x: unselectedData,
|
|
6421
|
-
type:
|
|
6775
|
+
type: "histogram",
|
|
6422
6776
|
autobinx: false,
|
|
6423
6777
|
xbins: xBins,
|
|
6424
6778
|
// nbinsx is valid but not included in the type definition
|
|
@@ -6431,59 +6785,73 @@ var HistogramPlot = function (props) {
|
|
|
6431
6785
|
width: 0.5,
|
|
6432
6786
|
},
|
|
6433
6787
|
},
|
|
6434
|
-
hovertemplate:
|
|
6788
|
+
hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>",
|
|
6435
6789
|
};
|
|
6436
|
-
var meanAnnotation =
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6790
|
+
var meanAnnotation = statsAnnotations.includes("mean") && meanLine && data.length > 0
|
|
6791
|
+
? [
|
|
6792
|
+
{
|
|
6793
|
+
x: meanValue,
|
|
6794
|
+
y: 1 + meanLineRadius + 0.04, // Position above the mean line. Value set with respect to the paper coordinates.
|
|
6795
|
+
yref: "paper",
|
|
6796
|
+
text: "<span style=\"font-weight:300\">AVG </span><span style=\"font-weight:600\">".concat(isDateArray(data)
|
|
6797
|
+
? new Date(meanValue).toLocaleDateString("en-US", {
|
|
6798
|
+
month: "2-digit",
|
|
6799
|
+
day: "2-digit",
|
|
6800
|
+
year: "2-digit",
|
|
6801
|
+
})
|
|
6802
|
+
: format(d3FormatValueString)(meanValue), "</span>"),
|
|
6803
|
+
xanchor: "center",
|
|
6804
|
+
yanchor: "bottom",
|
|
6805
|
+
showarrow: false,
|
|
6806
|
+
font: {
|
|
6807
|
+
color: barColor,
|
|
6808
|
+
size: 12,
|
|
6809
|
+
},
|
|
6451
6810
|
},
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6811
|
+
]
|
|
6812
|
+
: [];
|
|
6813
|
+
var stdevAnnotation = statsAnnotations.includes("stdev") && stdevLines && data.length > 0
|
|
6814
|
+
? [
|
|
6815
|
+
{
|
|
6816
|
+
x: meanValue, // Draw above the mean annotation
|
|
6817
|
+
y: 1 +
|
|
6818
|
+
meanLineRadius +
|
|
6819
|
+
(statsAnnotations.includes("mean") ? 0.11 : 0.04),
|
|
6820
|
+
yref: "paper",
|
|
6821
|
+
text: "<span style=\"font-weight:300\">\u03C3 </span><span style=\"font-weight:600\">±".concat(isDateArray(data)
|
|
6822
|
+
? new Date(stdevValue).toLocaleDateString("en-US", {
|
|
6823
|
+
month: "2-digit",
|
|
6824
|
+
day: "2-digit",
|
|
6825
|
+
year: "2-digit",
|
|
6826
|
+
})
|
|
6827
|
+
: format(d3FormatValueString)(stdevValue), "</span>"),
|
|
6828
|
+
xanchor: "center",
|
|
6829
|
+
yanchor: "bottom",
|
|
6830
|
+
showarrow: false,
|
|
6831
|
+
font: {
|
|
6832
|
+
color: barColor,
|
|
6833
|
+
size: 12,
|
|
6834
|
+
},
|
|
6468
6835
|
},
|
|
6469
|
-
|
|
6836
|
+
]
|
|
6837
|
+
: [];
|
|
6470
6838
|
var plotlyData = [
|
|
6471
6839
|
{
|
|
6472
6840
|
x: data,
|
|
6473
|
-
type:
|
|
6841
|
+
type: "histogram",
|
|
6474
6842
|
autobinx: false,
|
|
6475
6843
|
xbins: xBins,
|
|
6476
6844
|
// nbinsx is valid but not included in the type definition
|
|
6477
6845
|
//@ts-ignore
|
|
6478
6846
|
nbinsx: nBins, // Maximum number of bins. Plotly may adjust to make bins "nicer".
|
|
6479
6847
|
marker: {
|
|
6480
|
-
color: barColor !== null && barColor !== void 0 ? barColor :
|
|
6848
|
+
color: barColor !== null && barColor !== void 0 ? barColor : "blue",
|
|
6481
6849
|
line: {
|
|
6482
6850
|
color: "white",
|
|
6483
6851
|
width: 0.5,
|
|
6484
6852
|
},
|
|
6485
6853
|
},
|
|
6486
|
-
hovertemplate:
|
|
6854
|
+
hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>", // Custom hover text
|
|
6487
6855
|
},
|
|
6488
6856
|
unselectedTrace,
|
|
6489
6857
|
];
|
|
@@ -6491,63 +6859,63 @@ var HistogramPlot = function (props) {
|
|
|
6491
6859
|
title: {
|
|
6492
6860
|
text: title,
|
|
6493
6861
|
},
|
|
6494
|
-
barmode:
|
|
6862
|
+
barmode: "stack", // Stack unselected bars on top of selected bars
|
|
6495
6863
|
showlegend: false,
|
|
6496
6864
|
autosize: true,
|
|
6497
6865
|
width: undefined, // Let autosize handle width
|
|
6498
6866
|
height: undefined, // Let autosize handle height
|
|
6499
6867
|
margin: {
|
|
6500
6868
|
l: 50,
|
|
6501
|
-
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
6869
|
+
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
6502
6870
|
t: 40 + (title ? 50 : 0), // Add extra top margin if there is a title
|
|
6503
6871
|
b: 50,
|
|
6504
|
-
pad: 4
|
|
6872
|
+
pad: 4,
|
|
6505
6873
|
},
|
|
6506
6874
|
xaxis: {
|
|
6507
6875
|
title: {
|
|
6508
|
-
text: xAxisTitle
|
|
6876
|
+
text: xAxisTitle,
|
|
6509
6877
|
},
|
|
6510
6878
|
range: fixedXAxisRange, // Fixed range prevents axis shifting during interaction or data updates
|
|
6511
6879
|
showgrid: true,
|
|
6512
6880
|
zeroline: false,
|
|
6513
6881
|
showline: true,
|
|
6514
|
-
mirror:
|
|
6515
|
-
gridcolor:
|
|
6882
|
+
mirror: "ticks",
|
|
6883
|
+
gridcolor: "#efefef",
|
|
6516
6884
|
gridwidth: 0.2,
|
|
6517
|
-
zerolinecolor:
|
|
6885
|
+
zerolinecolor: "#969696",
|
|
6518
6886
|
zerolinewidth: 1,
|
|
6519
|
-
linecolor:
|
|
6887
|
+
linecolor: "#bababa",
|
|
6520
6888
|
linewidth: 1,
|
|
6521
6889
|
fixedrange: true, // Disable zooming
|
|
6522
|
-
ticklabelposition:
|
|
6523
|
-
tickformat: isDateArray(data) ? dateTickFormat :
|
|
6890
|
+
ticklabelposition: "outside",
|
|
6891
|
+
tickformat: isDateArray(data) ? dateTickFormat : d3FormatValueString, // Format ticks for dates
|
|
6524
6892
|
automargin: true, // Adjust margin if tick labels rotate
|
|
6525
|
-
hoverformat:
|
|
6893
|
+
hoverformat: isNumberArray(allData) ? d3FormatValueString : undefined,
|
|
6526
6894
|
},
|
|
6527
6895
|
yaxis: {
|
|
6528
6896
|
title: {
|
|
6529
|
-
text:
|
|
6897
|
+
text: "Count",
|
|
6530
6898
|
standoff: 12, // Add space between title and axis
|
|
6531
6899
|
},
|
|
6532
6900
|
automargin: true, // Required for standoff to work properly
|
|
6533
6901
|
showgrid: true,
|
|
6534
6902
|
zeroline: false,
|
|
6535
6903
|
showline: true,
|
|
6536
|
-
mirror:
|
|
6537
|
-
gridcolor:
|
|
6904
|
+
mirror: "ticks",
|
|
6905
|
+
gridcolor: "#efefef",
|
|
6538
6906
|
gridwidth: 0.2,
|
|
6539
|
-
zerolinecolor:
|
|
6907
|
+
zerolinecolor: "#969696",
|
|
6540
6908
|
zerolinewidth: 1,
|
|
6541
|
-
linecolor:
|
|
6909
|
+
linecolor: "#bababa",
|
|
6542
6910
|
linewidth: 1,
|
|
6543
6911
|
fixedrange: true, // Disable zooming
|
|
6544
|
-
ticksuffix:
|
|
6912
|
+
ticksuffix: " ", // Add space between y axis and ticks
|
|
6545
6913
|
},
|
|
6546
6914
|
bargap: 0.03, // Gap between bars
|
|
6547
|
-
dragmode:
|
|
6548
|
-
selectdirection:
|
|
6915
|
+
dragmode: "select", // Enable drag to select
|
|
6916
|
+
selectdirection: "h", // User can select in horizontal direction only
|
|
6549
6917
|
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
|
|
6550
|
-
annotations: tslib.__spreadArray(tslib.__spreadArray([], meanAnnotation, true), stdevAnnotation, true)
|
|
6918
|
+
annotations: tslib.__spreadArray(tslib.__spreadArray([], meanAnnotation, true), stdevAnnotation, true),
|
|
6551
6919
|
};
|
|
6552
6920
|
var config = {
|
|
6553
6921
|
responsive: true, // Make the plot responsive
|
|
@@ -6557,14 +6925,14 @@ var HistogramPlot = function (props) {
|
|
|
6557
6925
|
staticPlot: false, // Enable interactivity
|
|
6558
6926
|
};
|
|
6559
6927
|
var containerStyles = tslib.__assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
6560
|
-
return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container ".concat(plotId), style: tslib.__assign({
|
|
6928
|
+
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 () {
|
|
6561
6929
|
onDeselect();
|
|
6562
6930
|
setSelectedRange(null); // Remove selected box
|
|
6563
6931
|
}, onUpdate: handlePlotUpdate, useResizeHandler: true, style: {
|
|
6564
6932
|
width: "100%",
|
|
6565
6933
|
height: "100%",
|
|
6566
|
-
display: "block"
|
|
6567
|
-
} }, "histogram-".concat(plotId ||
|
|
6934
|
+
display: "block",
|
|
6935
|
+
} }, "histogram-".concat(plotId || "default")) }) }) }));
|
|
6568
6936
|
};
|
|
6569
6937
|
|
|
6570
6938
|
var Plot$1 = React.lazy(function () { return import('react-plotly.js'); });
|