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.esm.js
CHANGED
|
@@ -36,6 +36,319 @@ function styleInject(css, ref) {
|
|
|
36
36
|
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}";
|
|
37
37
|
styleInject(css_248z);
|
|
38
38
|
|
|
39
|
+
function formatDecimal(x) {
|
|
40
|
+
return Math.abs(x = Math.round(x)) >= 1e21
|
|
41
|
+
? x.toLocaleString("en").replace(/,/g, "")
|
|
42
|
+
: x.toString(10);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Computes the decimal coefficient and exponent of the specified number x with
|
|
46
|
+
// significant digits p, where x is positive and p is in [1, 21] or undefined.
|
|
47
|
+
// For example, formatDecimalParts(1.23) returns ["123", 0].
|
|
48
|
+
function formatDecimalParts(x, p) {
|
|
49
|
+
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
|
|
50
|
+
var i, coefficient = x.slice(0, i);
|
|
51
|
+
|
|
52
|
+
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
|
|
53
|
+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
|
|
54
|
+
return [
|
|
55
|
+
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
|
|
56
|
+
+x.slice(i + 1)
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function exponent(x) {
|
|
61
|
+
return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function formatGroup(grouping, thousands) {
|
|
65
|
+
return function(value, width) {
|
|
66
|
+
var i = value.length,
|
|
67
|
+
t = [],
|
|
68
|
+
j = 0,
|
|
69
|
+
g = grouping[0],
|
|
70
|
+
length = 0;
|
|
71
|
+
|
|
72
|
+
while (i > 0 && g > 0) {
|
|
73
|
+
if (length + g + 1 > width) g = Math.max(1, width - length);
|
|
74
|
+
t.push(value.substring(i -= g, i + g));
|
|
75
|
+
if ((length += g + 1) > width) break;
|
|
76
|
+
g = grouping[j = (j + 1) % grouping.length];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return t.reverse().join(thousands);
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function formatNumerals(numerals) {
|
|
84
|
+
return function(value) {
|
|
85
|
+
return value.replace(/[0-9]/g, function(i) {
|
|
86
|
+
return numerals[+i];
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
|
|
92
|
+
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
|
|
93
|
+
|
|
94
|
+
function formatSpecifier(specifier) {
|
|
95
|
+
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
|
|
96
|
+
var match;
|
|
97
|
+
return new FormatSpecifier({
|
|
98
|
+
fill: match[1],
|
|
99
|
+
align: match[2],
|
|
100
|
+
sign: match[3],
|
|
101
|
+
symbol: match[4],
|
|
102
|
+
zero: match[5],
|
|
103
|
+
width: match[6],
|
|
104
|
+
comma: match[7],
|
|
105
|
+
precision: match[8] && match[8].slice(1),
|
|
106
|
+
trim: match[9],
|
|
107
|
+
type: match[10]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
|
|
112
|
+
|
|
113
|
+
function FormatSpecifier(specifier) {
|
|
114
|
+
this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
|
|
115
|
+
this.align = specifier.align === undefined ? ">" : specifier.align + "";
|
|
116
|
+
this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
|
|
117
|
+
this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
|
|
118
|
+
this.zero = !!specifier.zero;
|
|
119
|
+
this.width = specifier.width === undefined ? undefined : +specifier.width;
|
|
120
|
+
this.comma = !!specifier.comma;
|
|
121
|
+
this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
|
|
122
|
+
this.trim = !!specifier.trim;
|
|
123
|
+
this.type = specifier.type === undefined ? "" : specifier.type + "";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
FormatSpecifier.prototype.toString = function() {
|
|
127
|
+
return this.fill
|
|
128
|
+
+ this.align
|
|
129
|
+
+ this.sign
|
|
130
|
+
+ this.symbol
|
|
131
|
+
+ (this.zero ? "0" : "")
|
|
132
|
+
+ (this.width === undefined ? "" : Math.max(1, this.width | 0))
|
|
133
|
+
+ (this.comma ? "," : "")
|
|
134
|
+
+ (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
|
|
135
|
+
+ (this.trim ? "~" : "")
|
|
136
|
+
+ this.type;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
|
|
140
|
+
function formatTrim(s) {
|
|
141
|
+
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
|
|
142
|
+
switch (s[i]) {
|
|
143
|
+
case ".": i0 = i1 = i; break;
|
|
144
|
+
case "0": if (i0 === 0) i0 = i; i1 = i; break;
|
|
145
|
+
default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
var prefixExponent;
|
|
152
|
+
|
|
153
|
+
function formatPrefixAuto(x, p) {
|
|
154
|
+
var d = formatDecimalParts(x, p);
|
|
155
|
+
if (!d) return x + "";
|
|
156
|
+
var coefficient = d[0],
|
|
157
|
+
exponent = d[1],
|
|
158
|
+
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
|
|
159
|
+
n = coefficient.length;
|
|
160
|
+
return i === n ? coefficient
|
|
161
|
+
: i > n ? coefficient + new Array(i - n + 1).join("0")
|
|
162
|
+
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
|
|
163
|
+
: "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function formatRounded(x, p) {
|
|
167
|
+
var d = formatDecimalParts(x, p);
|
|
168
|
+
if (!d) return x + "";
|
|
169
|
+
var coefficient = d[0],
|
|
170
|
+
exponent = d[1];
|
|
171
|
+
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
|
|
172
|
+
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
|
|
173
|
+
: coefficient + new Array(exponent - coefficient.length + 2).join("0");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
var formatTypes = {
|
|
177
|
+
"%": (x, p) => (x * 100).toFixed(p),
|
|
178
|
+
"b": (x) => Math.round(x).toString(2),
|
|
179
|
+
"c": (x) => x + "",
|
|
180
|
+
"d": formatDecimal,
|
|
181
|
+
"e": (x, p) => x.toExponential(p),
|
|
182
|
+
"f": (x, p) => x.toFixed(p),
|
|
183
|
+
"g": (x, p) => x.toPrecision(p),
|
|
184
|
+
"o": (x) => Math.round(x).toString(8),
|
|
185
|
+
"p": (x, p) => formatRounded(x * 100, p),
|
|
186
|
+
"r": formatRounded,
|
|
187
|
+
"s": formatPrefixAuto,
|
|
188
|
+
"X": (x) => Math.round(x).toString(16).toUpperCase(),
|
|
189
|
+
"x": (x) => Math.round(x).toString(16)
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
function identity(x) {
|
|
193
|
+
return x;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var map = Array.prototype.map,
|
|
197
|
+
prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
|
|
198
|
+
|
|
199
|
+
function formatLocale(locale) {
|
|
200
|
+
var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""),
|
|
201
|
+
currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
|
|
202
|
+
currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
|
|
203
|
+
decimal = locale.decimal === undefined ? "." : locale.decimal + "",
|
|
204
|
+
numerals = locale.numerals === undefined ? identity : formatNumerals(map.call(locale.numerals, String)),
|
|
205
|
+
percent = locale.percent === undefined ? "%" : locale.percent + "",
|
|
206
|
+
minus = locale.minus === undefined ? "−" : locale.minus + "",
|
|
207
|
+
nan = locale.nan === undefined ? "NaN" : locale.nan + "";
|
|
208
|
+
|
|
209
|
+
function newFormat(specifier) {
|
|
210
|
+
specifier = formatSpecifier(specifier);
|
|
211
|
+
|
|
212
|
+
var fill = specifier.fill,
|
|
213
|
+
align = specifier.align,
|
|
214
|
+
sign = specifier.sign,
|
|
215
|
+
symbol = specifier.symbol,
|
|
216
|
+
zero = specifier.zero,
|
|
217
|
+
width = specifier.width,
|
|
218
|
+
comma = specifier.comma,
|
|
219
|
+
precision = specifier.precision,
|
|
220
|
+
trim = specifier.trim,
|
|
221
|
+
type = specifier.type;
|
|
222
|
+
|
|
223
|
+
// The "n" type is an alias for ",g".
|
|
224
|
+
if (type === "n") comma = true, type = "g";
|
|
225
|
+
|
|
226
|
+
// The "" type, and any invalid type, is an alias for ".12~g".
|
|
227
|
+
else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";
|
|
228
|
+
|
|
229
|
+
// If zero fill is specified, padding goes after sign and before digits.
|
|
230
|
+
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
|
|
231
|
+
|
|
232
|
+
// Compute the prefix and suffix.
|
|
233
|
+
// For SI-prefix, the suffix is lazily computed.
|
|
234
|
+
var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
|
|
235
|
+
suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "";
|
|
236
|
+
|
|
237
|
+
// What format function should we use?
|
|
238
|
+
// Is this an integer type?
|
|
239
|
+
// Can this type generate exponential notation?
|
|
240
|
+
var formatType = formatTypes[type],
|
|
241
|
+
maybeSuffix = /[defgprs%]/.test(type);
|
|
242
|
+
|
|
243
|
+
// Set the default precision if not specified,
|
|
244
|
+
// or clamp the specified precision to the supported range.
|
|
245
|
+
// For significant precision, it must be in [1, 21].
|
|
246
|
+
// For fixed precision, it must be in [0, 20].
|
|
247
|
+
precision = precision === undefined ? 6
|
|
248
|
+
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
|
|
249
|
+
: Math.max(0, Math.min(20, precision));
|
|
250
|
+
|
|
251
|
+
function format(value) {
|
|
252
|
+
var valuePrefix = prefix,
|
|
253
|
+
valueSuffix = suffix,
|
|
254
|
+
i, n, c;
|
|
255
|
+
|
|
256
|
+
if (type === "c") {
|
|
257
|
+
valueSuffix = formatType(value) + valueSuffix;
|
|
258
|
+
value = "";
|
|
259
|
+
} else {
|
|
260
|
+
value = +value;
|
|
261
|
+
|
|
262
|
+
// Determine the sign. -0 is not less than 0, but 1 / -0 is!
|
|
263
|
+
var valueNegative = value < 0 || 1 / value < 0;
|
|
264
|
+
|
|
265
|
+
// Perform the initial formatting.
|
|
266
|
+
value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
|
|
267
|
+
|
|
268
|
+
// Trim insignificant zeros.
|
|
269
|
+
if (trim) value = formatTrim(value);
|
|
270
|
+
|
|
271
|
+
// If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
|
|
272
|
+
if (valueNegative && +value === 0 && sign !== "+") valueNegative = false;
|
|
273
|
+
|
|
274
|
+
// Compute the prefix and suffix.
|
|
275
|
+
valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
|
|
276
|
+
valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
|
|
277
|
+
|
|
278
|
+
// Break the formatted value into the integer “value” part that can be
|
|
279
|
+
// grouped, and fractional or exponential “suffix” part that is not.
|
|
280
|
+
if (maybeSuffix) {
|
|
281
|
+
i = -1, n = value.length;
|
|
282
|
+
while (++i < n) {
|
|
283
|
+
if (c = value.charCodeAt(i), 48 > c || c > 57) {
|
|
284
|
+
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
|
|
285
|
+
value = value.slice(0, i);
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// If the fill character is not "0", grouping is applied before padding.
|
|
293
|
+
if (comma && !zero) value = group(value, Infinity);
|
|
294
|
+
|
|
295
|
+
// Compute the padding.
|
|
296
|
+
var length = valuePrefix.length + value.length + valueSuffix.length,
|
|
297
|
+
padding = length < width ? new Array(width - length + 1).join(fill) : "";
|
|
298
|
+
|
|
299
|
+
// If the fill character is "0", grouping is applied after padding.
|
|
300
|
+
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
|
|
301
|
+
|
|
302
|
+
// Reconstruct the final output based on the desired alignment.
|
|
303
|
+
switch (align) {
|
|
304
|
+
case "<": value = valuePrefix + value + valueSuffix + padding; break;
|
|
305
|
+
case "=": value = valuePrefix + padding + value + valueSuffix; break;
|
|
306
|
+
case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
|
|
307
|
+
default: value = padding + valuePrefix + value + valueSuffix; break;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return numerals(value);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
format.toString = function() {
|
|
314
|
+
return specifier + "";
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
return format;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function formatPrefix(specifier, value) {
|
|
321
|
+
var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
|
|
322
|
+
e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
|
|
323
|
+
k = Math.pow(10, -e),
|
|
324
|
+
prefix = prefixes[8 + e / 3];
|
|
325
|
+
return function(value) {
|
|
326
|
+
return f(k * value) + prefix;
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
format: newFormat,
|
|
332
|
+
formatPrefix: formatPrefix
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
var locale;
|
|
337
|
+
var format;
|
|
338
|
+
|
|
339
|
+
defaultLocale({
|
|
340
|
+
thousands: ",",
|
|
341
|
+
grouping: [3],
|
|
342
|
+
currency: ["$", ""]
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
function defaultLocale(definition) {
|
|
346
|
+
locale = formatLocale(definition);
|
|
347
|
+
format = locale.format;
|
|
348
|
+
locale.formatPrefix;
|
|
349
|
+
return locale;
|
|
350
|
+
}
|
|
351
|
+
|
|
39
352
|
// Utility functions for our components
|
|
40
353
|
var ONEAVGMONTH = 2629800000; // Average month length in ms, copied from plotly constants in plotly.js/src/constants/numerical.js
|
|
41
354
|
// Type guard to check if array contains only numbers
|
|
@@ -6052,11 +6365,17 @@ var Loading = function () {
|
|
|
6052
6365
|
var Plot$2 = lazy(function () { return import('react-plotly.js'); });
|
|
6053
6366
|
var HistogramPlot = function (props) {
|
|
6054
6367
|
var _a, _b, _c, _d;
|
|
6055
|
-
var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _e = props.barColor, barColor = _e === void 0 ?
|
|
6368
|
+
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;
|
|
6056
6369
|
// Ref for plot container
|
|
6057
6370
|
var containerRef = useRef(null);
|
|
6058
6371
|
// Track any selections made in this plot so we can style the selection box.
|
|
6059
|
-
var
|
|
6372
|
+
var _q = useState(null), selectedRange = _q[0], setSelectedRange = _q[1];
|
|
6373
|
+
// If the parent component wants to clear the selection, reset selectedRange to null.
|
|
6374
|
+
useEffect(function () {
|
|
6375
|
+
if (emptySelectedRange) {
|
|
6376
|
+
setSelectedRange(null);
|
|
6377
|
+
}
|
|
6378
|
+
}, [emptySelectedRange]);
|
|
6060
6379
|
// Combine all data into one for later calculations
|
|
6061
6380
|
var allData = __spreadArray(__spreadArray([], data, true), unselectedData, true);
|
|
6062
6381
|
// If all the data becomes selected, we should forget any old selections.
|
|
@@ -6066,13 +6385,15 @@ var HistogramPlot = function (props) {
|
|
|
6066
6385
|
}
|
|
6067
6386
|
}, [unselectedData]);
|
|
6068
6387
|
// Set the bins based on the entire data set.
|
|
6069
|
-
var nBins =
|
|
6388
|
+
var nBins = data.length + unselectedData.length >= 10
|
|
6389
|
+
? Math.ceil(Math.sqrt(data.length + unselectedData.length))
|
|
6390
|
+
: 0;
|
|
6070
6391
|
// Plotly determines "nice" bins which consequently means it internally decides the axis range. We need
|
|
6071
6392
|
// to access that information once the plot has been initialized so that we can prevent the
|
|
6072
6393
|
// axis range from changing during interaction. Dates use strings.
|
|
6073
|
-
var
|
|
6394
|
+
var _r = useState(undefined), fixedXAxisRange = _r[0], setFixedXAxisRange = _r[1];
|
|
6074
6395
|
// track xbins too
|
|
6075
|
-
var
|
|
6396
|
+
var _s = useState(undefined), binSize = _s[0], setBinSize = _s[1];
|
|
6076
6397
|
// Once the plot is drawn, record the initial axis range so we can keep it fixed.
|
|
6077
6398
|
// figure should be Readonly<Plotly.Figure> but react-plotly.js doesn't expose that type, so we use any.
|
|
6078
6399
|
var handlePlotUpdate = function (figure, graphDiv) {
|
|
@@ -6090,7 +6411,11 @@ var HistogramPlot = function (props) {
|
|
|
6090
6411
|
}
|
|
6091
6412
|
if (!binSize) {
|
|
6092
6413
|
// Get the bin size from the first trace. Both traces should have the same bin size.
|
|
6093
|
-
if (figure &&
|
|
6414
|
+
if (figure &&
|
|
6415
|
+
figure.data &&
|
|
6416
|
+
figure.data.length > 0 &&
|
|
6417
|
+
figure.data[0].xbins &&
|
|
6418
|
+
figure.data[0].xbins.size) {
|
|
6094
6419
|
setBinSize(figure.data[0].xbins.size);
|
|
6095
6420
|
}
|
|
6096
6421
|
}
|
|
@@ -6100,22 +6425,22 @@ var HistogramPlot = function (props) {
|
|
|
6100
6425
|
// Add keyboard event listeners to track shift key
|
|
6101
6426
|
useEffect(function () {
|
|
6102
6427
|
var handleKeyDown = function (e) {
|
|
6103
|
-
if (e.key ===
|
|
6428
|
+
if (e.key === "Shift") {
|
|
6104
6429
|
isShiftPressed.current = true;
|
|
6105
6430
|
}
|
|
6106
6431
|
};
|
|
6107
6432
|
var handleKeyUp = function (e) {
|
|
6108
|
-
if (e.key ===
|
|
6433
|
+
if (e.key === "Shift") {
|
|
6109
6434
|
isShiftPressed.current = false;
|
|
6110
6435
|
}
|
|
6111
6436
|
};
|
|
6112
6437
|
// Add event listeners to document to catch shift key globally
|
|
6113
|
-
document.addEventListener(
|
|
6114
|
-
document.addEventListener(
|
|
6438
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
6439
|
+
document.addEventListener("keyup", handleKeyUp);
|
|
6115
6440
|
// Cleanup
|
|
6116
6441
|
return function () {
|
|
6117
|
-
document.removeEventListener(
|
|
6118
|
-
document.removeEventListener(
|
|
6442
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
6443
|
+
document.removeEventListener("keyup", handleKeyUp);
|
|
6119
6444
|
};
|
|
6120
6445
|
}, []);
|
|
6121
6446
|
// Create handler for click event that can use event data to update the plot if desired.
|
|
@@ -6125,11 +6450,12 @@ var HistogramPlot = function (props) {
|
|
|
6125
6450
|
return;
|
|
6126
6451
|
}
|
|
6127
6452
|
// 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] &&
|
|
6453
|
+
if ("binNumber" in event.points[0] &&
|
|
6454
|
+
typeof event.points[0].binNumber === "number") {
|
|
6129
6455
|
// Get the index of the clicked bar with respect to the trace. So if
|
|
6130
6456
|
// my trace has only one bar (0, 1] but another trace has bars (-1, 0], (0, 1], (1, 2], etc.
|
|
6131
6457
|
// 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
|
|
6458
|
+
// the second bar in the other trace. Because of this, we can't use data.xbins to
|
|
6133
6459
|
// find the clicked bar, because its start and end values are based on all traces, not just the clicked trace.
|
|
6134
6460
|
var clickedBinIndex = event.points[0].binNumber;
|
|
6135
6461
|
// Handle dates and numbers separately
|
|
@@ -6139,26 +6465,35 @@ var HistogramPlot = function (props) {
|
|
|
6139
6465
|
var globalFirstBinStart = void 0;
|
|
6140
6466
|
if (isDateArray(data)) {
|
|
6141
6467
|
// Date bins are represented as strings (sometimes). We'll need to convert whatever plotly gives us to timestamps.
|
|
6142
|
-
globalFirstBinStart = fixedXAxisRange
|
|
6143
|
-
|
|
6468
|
+
globalFirstBinStart = fixedXAxisRange
|
|
6469
|
+
? new Date(fixedXAxisRange[0]).getTime()
|
|
6470
|
+
: new Date(event.points[0].data.xbins.start).getTime();
|
|
6471
|
+
minTraceValue =
|
|
6472
|
+
event.points[0].curveNumber === 0
|
|
6473
|
+
? Math.min.apply(Math, data.map(function (d) { return d.getTime(); })) : Math.min.apply(Math, unselectedData.map(function (d) { return d.getTime(); }));
|
|
6144
6474
|
}
|
|
6145
6475
|
else {
|
|
6146
6476
|
// Get the min value of the trace and the beginning of the first bin (globally)
|
|
6147
|
-
minTraceValue =
|
|
6148
|
-
|
|
6477
|
+
minTraceValue =
|
|
6478
|
+
event.points[0].curveNumber === 0
|
|
6479
|
+
? Math.min.apply(Math, data) : Math.min.apply(Math, unselectedData);
|
|
6480
|
+
globalFirstBinStart = fixedXAxisRange
|
|
6481
|
+
? fixedXAxisRange[0]
|
|
6482
|
+
: event.points[0].data.xbins.start;
|
|
6149
6483
|
}
|
|
6150
6484
|
// Finally, we need to calculate the min and max values of the clicked bin.
|
|
6151
6485
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6152
6486
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6153
6487
|
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 ===
|
|
6488
|
+
var convertedBinSize = typeof size === "string"
|
|
6155
6489
|
? plotlyMToMilliseconds(size)
|
|
6156
6490
|
: size;
|
|
6157
6491
|
// This minTraceValue is in the 0th bin of this trace. Find the index of this bin in the whole plot.
|
|
6158
|
-
var clickedBinGlobalIndex = clickedBinIndex +
|
|
6492
|
+
var clickedBinGlobalIndex = clickedBinIndex +
|
|
6493
|
+
Math.floor((minTraceValue - globalFirstBinStart) / convertedBinSize);
|
|
6159
6494
|
var _e = [
|
|
6160
6495
|
globalFirstBinStart + clickedBinGlobalIndex * convertedBinSize,
|
|
6161
|
-
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize
|
|
6496
|
+
globalFirstBinStart + (clickedBinGlobalIndex + 1) * convertedBinSize,
|
|
6162
6497
|
], minBinValue = _e[0], maxBinValue = _e[1];
|
|
6163
6498
|
if (isDateArray(data)) {
|
|
6164
6499
|
var minDate = new Date(minBinValue);
|
|
@@ -6191,7 +6526,8 @@ var HistogramPlot = function (props) {
|
|
|
6191
6526
|
}
|
|
6192
6527
|
var minValue;
|
|
6193
6528
|
var maxValue;
|
|
6194
|
-
if (typeof event.range.x[0] ===
|
|
6529
|
+
if (typeof event.range.x[0] === "string" &&
|
|
6530
|
+
typeof event.range.x[1] === "string") {
|
|
6195
6531
|
// Then we are must be dealing with dates
|
|
6196
6532
|
if (selectByBin) {
|
|
6197
6533
|
// Set selected range to include the whole bin if at least half the bin is within the explicit range
|
|
@@ -6202,7 +6538,7 @@ var HistogramPlot = function (props) {
|
|
|
6202
6538
|
var lastBinMidPoint = new Date(event.points[event.points.length - 1].x).getTime();
|
|
6203
6539
|
// If the bin size is a month or more, plotly records it in their "mstring" format like "M3" for 3 months.
|
|
6204
6540
|
// We then must convert it back to milliseconds. Otherwise, it's always ms.
|
|
6205
|
-
var convertedBinSize = typeof binSize ===
|
|
6541
|
+
var convertedBinSize = typeof binSize === "string"
|
|
6206
6542
|
? plotlyMToMilliseconds(binSize)
|
|
6207
6543
|
: binSize;
|
|
6208
6544
|
minValue = new Date(firstBinMidPoint - convertedBinSize / 2);
|
|
@@ -6249,7 +6585,7 @@ var HistogramPlot = function (props) {
|
|
|
6249
6585
|
}
|
|
6250
6586
|
if (minValue !== undefined && maxValue !== undefined) {
|
|
6251
6587
|
// Update selected range. Have to be strict about types.
|
|
6252
|
-
if (typeof minValue ===
|
|
6588
|
+
if (typeof minValue === "number" && typeof maxValue === "number") {
|
|
6253
6589
|
var newMinMax = [minValue, maxValue];
|
|
6254
6590
|
if (isShiftPressed.current && selectedRange) {
|
|
6255
6591
|
setSelectedRange(__spreadArray(__spreadArray([], selectedRange, true), [newMinMax], false));
|
|
@@ -6277,128 +6613,146 @@ var HistogramPlot = function (props) {
|
|
|
6277
6613
|
if (unselectedData.length === 0)
|
|
6278
6614
|
return []; // Don't show the box if the entire dataset is selected.
|
|
6279
6615
|
// Create a multiply-like effect by using a semi-transparent dark overlay
|
|
6280
|
-
var multiplyColor =
|
|
6616
|
+
var multiplyColor = "rgba(29, 104, 185, 0.1)";
|
|
6281
6617
|
return selectedRange.map(function (maxMin) { return ({
|
|
6282
|
-
type:
|
|
6618
|
+
type: "rect",
|
|
6283
6619
|
x0: isDateArray(maxMin) ? maxMin[0].getTime() : maxMin[0],
|
|
6284
6620
|
x1: isDateArray(maxMin) ? maxMin[1].getTime() : maxMin[1],
|
|
6285
6621
|
y0: 0,
|
|
6286
6622
|
y1: 1,
|
|
6287
|
-
yref:
|
|
6623
|
+
yref: "paper",
|
|
6288
6624
|
fillcolor: multiplyColor,
|
|
6289
6625
|
line: {
|
|
6290
6626
|
width: 1,
|
|
6291
|
-
color: multiplyColor
|
|
6627
|
+
color: multiplyColor,
|
|
6292
6628
|
},
|
|
6293
|
-
layer:
|
|
6629
|
+
layer: "above", // Ensure the selection box is above the bars
|
|
6294
6630
|
}); });
|
|
6295
6631
|
}, [selectedRange, unselectedData]);
|
|
6296
6632
|
// Calculate the mean of the selected data using normalized data
|
|
6297
6633
|
var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
|
|
6298
6634
|
var stdevValue = (_b = calculateStandardDeviation(data)) !== null && _b !== void 0 ? _b : 0;
|
|
6299
6635
|
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
|
-
|
|
6636
|
+
var meanLine = statsAnnotations.includes("mean") && data.length > 0
|
|
6637
|
+
? [
|
|
6638
|
+
{
|
|
6639
|
+
type: "line",
|
|
6640
|
+
x0: meanValue,
|
|
6641
|
+
y0: 1 - meanLineRadius,
|
|
6642
|
+
x1: meanValue,
|
|
6643
|
+
yref: "paper",
|
|
6644
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6645
|
+
line: {
|
|
6646
|
+
color: barColor,
|
|
6647
|
+
width: 1.5,
|
|
6648
|
+
},
|
|
6649
|
+
},
|
|
6650
|
+
]
|
|
6651
|
+
: [];
|
|
6312
6652
|
// Draw mean line for all data
|
|
6313
6653
|
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
|
-
|
|
6654
|
+
var allDataMeanLine = statsAnnotations.includes("mean") &&
|
|
6655
|
+
unselectedData.length > 0 &&
|
|
6656
|
+
data.length > 0
|
|
6657
|
+
? [
|
|
6658
|
+
{
|
|
6659
|
+
type: "line",
|
|
6660
|
+
x0: allDataMeanValue,
|
|
6661
|
+
y0: 1 - meanLineRadius,
|
|
6662
|
+
x1: allDataMeanValue,
|
|
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: unselectedBarColor,
|
|
6667
|
+
width: 1.5,
|
|
6668
|
+
},
|
|
6669
|
+
},
|
|
6670
|
+
]
|
|
6671
|
+
: [];
|
|
6672
|
+
var stdevLines = statsAnnotations.includes("stdev") && data.length > 0
|
|
6673
|
+
? [
|
|
6674
|
+
{
|
|
6675
|
+
type: "line",
|
|
6676
|
+
x0: meanValue - stdevValue,
|
|
6677
|
+
y0: 1 - meanLineRadius,
|
|
6678
|
+
x1: meanValue - stdevValue,
|
|
6679
|
+
yref: "paper",
|
|
6680
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6681
|
+
line: {
|
|
6682
|
+
color: barColor,
|
|
6683
|
+
width: 1.5,
|
|
6684
|
+
dash: "dot",
|
|
6685
|
+
},
|
|
6686
|
+
},
|
|
6687
|
+
{
|
|
6688
|
+
type: "line",
|
|
6689
|
+
x0: meanValue + stdevValue,
|
|
6690
|
+
y0: 1 - meanLineRadius,
|
|
6691
|
+
x1: meanValue + stdevValue,
|
|
6692
|
+
yref: "paper",
|
|
6693
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6694
|
+
line: {
|
|
6695
|
+
color: barColor,
|
|
6696
|
+
width: 1.5,
|
|
6697
|
+
dash: "dot",
|
|
6698
|
+
},
|
|
6699
|
+
},
|
|
6700
|
+
]
|
|
6352
6701
|
: [];
|
|
6353
6702
|
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
|
-
|
|
6703
|
+
var allDataStdevLines = statsAnnotations.includes("stdev") &&
|
|
6704
|
+
unselectedData.length > 0 &&
|
|
6705
|
+
data.length > 0
|
|
6706
|
+
? [
|
|
6707
|
+
{
|
|
6708
|
+
type: "line",
|
|
6709
|
+
x0: allDataMeanValue - allDataStdevValue,
|
|
6710
|
+
y0: 1 - meanLineRadius,
|
|
6711
|
+
x1: allDataMeanValue - allDataStdevValue,
|
|
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: unselectedBarColor,
|
|
6716
|
+
width: 1.5,
|
|
6717
|
+
dash: "dot",
|
|
6718
|
+
},
|
|
6719
|
+
},
|
|
6720
|
+
{
|
|
6721
|
+
type: "line",
|
|
6722
|
+
x0: allDataMeanValue + allDataStdevValue,
|
|
6723
|
+
y0: 1 - meanLineRadius,
|
|
6724
|
+
x1: allDataMeanValue + allDataStdevValue,
|
|
6725
|
+
yref: "paper",
|
|
6726
|
+
y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
|
|
6727
|
+
line: {
|
|
6728
|
+
color: unselectedBarColor,
|
|
6729
|
+
width: 1.5,
|
|
6730
|
+
dash: "dot",
|
|
6731
|
+
},
|
|
6732
|
+
},
|
|
6733
|
+
]
|
|
6380
6734
|
: [];
|
|
6381
|
-
// If binSizeOverride is provided, use it to set the bin size and range explicitly.
|
|
6735
|
+
// If binSizeOverride is provided, use it to set the bin size and range explicitly.
|
|
6382
6736
|
// Plotly does a better job of setting bins and ending them at nice numbers, so only use
|
|
6383
6737
|
// this prop when necessary.
|
|
6384
|
-
var xBins =
|
|
6385
|
-
?
|
|
6738
|
+
var xBins = binSizeOverride && allData.length > 0
|
|
6739
|
+
? isDateArray(allData)
|
|
6386
6740
|
? {
|
|
6387
6741
|
start: roundToPrevDay(Math.min.apply(Math, allData.map(function (d) { return d.getTime(); }))), // Find a nice round number as a starting point.
|
|
6388
6742
|
end: roundToNextDay(Math.max.apply(Math, allData.map(function (d) { return d.getTime(); }))),
|
|
6389
|
-
size: binSizeOverride // bin size in milliseconds
|
|
6743
|
+
size: binSizeOverride, // bin size in milliseconds
|
|
6390
6744
|
}
|
|
6391
6745
|
: isNumberArray(allData)
|
|
6392
6746
|
? {
|
|
6393
6747
|
start: Math.floor(Math.min.apply(Math, allData)),
|
|
6394
6748
|
end: Math.ceil(Math.max.apply(Math, allData)),
|
|
6395
|
-
size: binSizeOverride
|
|
6749
|
+
size: binSizeOverride,
|
|
6396
6750
|
}
|
|
6397
|
-
: undefined
|
|
6751
|
+
: undefined
|
|
6398
6752
|
: undefined;
|
|
6399
6753
|
var unselectedTrace = {
|
|
6400
6754
|
x: unselectedData,
|
|
6401
|
-
type:
|
|
6755
|
+
type: "histogram",
|
|
6402
6756
|
autobinx: false,
|
|
6403
6757
|
xbins: xBins,
|
|
6404
6758
|
// nbinsx is valid but not included in the type definition
|
|
@@ -6411,59 +6765,73 @@ var HistogramPlot = function (props) {
|
|
|
6411
6765
|
width: 0.5,
|
|
6412
6766
|
},
|
|
6413
6767
|
},
|
|
6414
|
-
hovertemplate:
|
|
6768
|
+
hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>",
|
|
6415
6769
|
};
|
|
6416
|
-
var meanAnnotation =
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6770
|
+
var meanAnnotation = statsAnnotations.includes("mean") && meanLine && data.length > 0
|
|
6771
|
+
? [
|
|
6772
|
+
{
|
|
6773
|
+
x: meanValue,
|
|
6774
|
+
y: 1 + meanLineRadius + 0.04, // Position above the mean line. Value set with respect to the paper coordinates.
|
|
6775
|
+
yref: "paper",
|
|
6776
|
+
text: "<span style=\"font-weight:300\">AVG </span><span style=\"font-weight:600\">".concat(isDateArray(data)
|
|
6777
|
+
? new Date(meanValue).toLocaleDateString("en-US", {
|
|
6778
|
+
month: "2-digit",
|
|
6779
|
+
day: "2-digit",
|
|
6780
|
+
year: "2-digit",
|
|
6781
|
+
})
|
|
6782
|
+
: format(d3FormatValueString)(meanValue), "</span>"),
|
|
6783
|
+
xanchor: "center",
|
|
6784
|
+
yanchor: "bottom",
|
|
6785
|
+
showarrow: false,
|
|
6786
|
+
font: {
|
|
6787
|
+
color: barColor,
|
|
6788
|
+
size: 12,
|
|
6789
|
+
},
|
|
6431
6790
|
},
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6791
|
+
]
|
|
6792
|
+
: [];
|
|
6793
|
+
var stdevAnnotation = statsAnnotations.includes("stdev") && stdevLines && data.length > 0
|
|
6794
|
+
? [
|
|
6795
|
+
{
|
|
6796
|
+
x: meanValue, // Draw above the mean annotation
|
|
6797
|
+
y: 1 +
|
|
6798
|
+
meanLineRadius +
|
|
6799
|
+
(statsAnnotations.includes("mean") ? 0.11 : 0.04),
|
|
6800
|
+
yref: "paper",
|
|
6801
|
+
text: "<span style=\"font-weight:300\">\u03C3 </span><span style=\"font-weight:600\">±".concat(isDateArray(data)
|
|
6802
|
+
? new Date(stdevValue).toLocaleDateString("en-US", {
|
|
6803
|
+
month: "2-digit",
|
|
6804
|
+
day: "2-digit",
|
|
6805
|
+
year: "2-digit",
|
|
6806
|
+
})
|
|
6807
|
+
: format(d3FormatValueString)(stdevValue), "</span>"),
|
|
6808
|
+
xanchor: "center",
|
|
6809
|
+
yanchor: "bottom",
|
|
6810
|
+
showarrow: false,
|
|
6811
|
+
font: {
|
|
6812
|
+
color: barColor,
|
|
6813
|
+
size: 12,
|
|
6814
|
+
},
|
|
6448
6815
|
},
|
|
6449
|
-
|
|
6816
|
+
]
|
|
6817
|
+
: [];
|
|
6450
6818
|
var plotlyData = [
|
|
6451
6819
|
{
|
|
6452
6820
|
x: data,
|
|
6453
|
-
type:
|
|
6821
|
+
type: "histogram",
|
|
6454
6822
|
autobinx: false,
|
|
6455
6823
|
xbins: xBins,
|
|
6456
6824
|
// nbinsx is valid but not included in the type definition
|
|
6457
6825
|
//@ts-ignore
|
|
6458
6826
|
nbinsx: nBins, // Maximum number of bins. Plotly may adjust to make bins "nicer".
|
|
6459
6827
|
marker: {
|
|
6460
|
-
color: barColor !== null && barColor !== void 0 ? barColor :
|
|
6828
|
+
color: barColor !== null && barColor !== void 0 ? barColor : "blue",
|
|
6461
6829
|
line: {
|
|
6462
6830
|
color: "white",
|
|
6463
6831
|
width: 0.5,
|
|
6464
6832
|
},
|
|
6465
6833
|
},
|
|
6466
|
-
hovertemplate:
|
|
6834
|
+
hovertemplate: "[%{x})<br>Count: %{y}<extra></extra>", // Custom hover text
|
|
6467
6835
|
},
|
|
6468
6836
|
unselectedTrace,
|
|
6469
6837
|
];
|
|
@@ -6471,63 +6839,63 @@ var HistogramPlot = function (props) {
|
|
|
6471
6839
|
title: {
|
|
6472
6840
|
text: title,
|
|
6473
6841
|
},
|
|
6474
|
-
barmode:
|
|
6842
|
+
barmode: "stack", // Stack unselected bars on top of selected bars
|
|
6475
6843
|
showlegend: false,
|
|
6476
6844
|
autosize: true,
|
|
6477
6845
|
width: undefined, // Let autosize handle width
|
|
6478
6846
|
height: undefined, // Let autosize handle height
|
|
6479
6847
|
margin: {
|
|
6480
6848
|
l: 50,
|
|
6481
|
-
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
6849
|
+
r: 35, // Balance between ensuring the mean annotation doesn't get cut off and having too much margin.
|
|
6482
6850
|
t: 40 + (title ? 50 : 0), // Add extra top margin if there is a title
|
|
6483
6851
|
b: 50,
|
|
6484
|
-
pad: 4
|
|
6852
|
+
pad: 4,
|
|
6485
6853
|
},
|
|
6486
6854
|
xaxis: {
|
|
6487
6855
|
title: {
|
|
6488
|
-
text: xAxisTitle
|
|
6856
|
+
text: xAxisTitle,
|
|
6489
6857
|
},
|
|
6490
6858
|
range: fixedXAxisRange, // Fixed range prevents axis shifting during interaction or data updates
|
|
6491
6859
|
showgrid: true,
|
|
6492
6860
|
zeroline: false,
|
|
6493
6861
|
showline: true,
|
|
6494
|
-
mirror:
|
|
6495
|
-
gridcolor:
|
|
6862
|
+
mirror: "ticks",
|
|
6863
|
+
gridcolor: "#efefef",
|
|
6496
6864
|
gridwidth: 0.2,
|
|
6497
|
-
zerolinecolor:
|
|
6865
|
+
zerolinecolor: "#969696",
|
|
6498
6866
|
zerolinewidth: 1,
|
|
6499
|
-
linecolor:
|
|
6867
|
+
linecolor: "#bababa",
|
|
6500
6868
|
linewidth: 1,
|
|
6501
6869
|
fixedrange: true, // Disable zooming
|
|
6502
|
-
ticklabelposition:
|
|
6503
|
-
tickformat: isDateArray(data) ? dateTickFormat :
|
|
6870
|
+
ticklabelposition: "outside",
|
|
6871
|
+
tickformat: isDateArray(data) ? dateTickFormat : d3FormatValueString, // Format ticks for dates
|
|
6504
6872
|
automargin: true, // Adjust margin if tick labels rotate
|
|
6505
|
-
hoverformat:
|
|
6873
|
+
hoverformat: isNumberArray(allData) ? d3FormatValueString : undefined,
|
|
6506
6874
|
},
|
|
6507
6875
|
yaxis: {
|
|
6508
6876
|
title: {
|
|
6509
|
-
text:
|
|
6877
|
+
text: "Count",
|
|
6510
6878
|
standoff: 12, // Add space between title and axis
|
|
6511
6879
|
},
|
|
6512
6880
|
automargin: true, // Required for standoff to work properly
|
|
6513
6881
|
showgrid: true,
|
|
6514
6882
|
zeroline: false,
|
|
6515
6883
|
showline: true,
|
|
6516
|
-
mirror:
|
|
6517
|
-
gridcolor:
|
|
6884
|
+
mirror: "ticks",
|
|
6885
|
+
gridcolor: "#efefef",
|
|
6518
6886
|
gridwidth: 0.2,
|
|
6519
|
-
zerolinecolor:
|
|
6887
|
+
zerolinecolor: "#969696",
|
|
6520
6888
|
zerolinewidth: 1,
|
|
6521
|
-
linecolor:
|
|
6889
|
+
linecolor: "#bababa",
|
|
6522
6890
|
linewidth: 1,
|
|
6523
6891
|
fixedrange: true, // Disable zooming
|
|
6524
|
-
ticksuffix:
|
|
6892
|
+
ticksuffix: " ", // Add space between y axis and ticks
|
|
6525
6893
|
},
|
|
6526
6894
|
bargap: 0.03, // Gap between bars
|
|
6527
|
-
dragmode:
|
|
6528
|
-
selectdirection:
|
|
6895
|
+
dragmode: "select", // Enable drag to select
|
|
6896
|
+
selectdirection: "h", // User can select in horizontal direction only
|
|
6529
6897
|
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)
|
|
6898
|
+
annotations: __spreadArray(__spreadArray([], meanAnnotation, true), stdevAnnotation, true),
|
|
6531
6899
|
};
|
|
6532
6900
|
var config = {
|
|
6533
6901
|
responsive: true, // Make the plot responsive
|
|
@@ -6537,14 +6905,14 @@ var HistogramPlot = function (props) {
|
|
|
6537
6905
|
staticPlot: false, // Enable interactivity
|
|
6538
6906
|
};
|
|
6539
6907
|
var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
6540
|
-
return (jsx("div", { ref: containerRef, className: "plot-container ".concat(plotId), style: __assign({
|
|
6908
|
+
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
6909
|
onDeselect();
|
|
6542
6910
|
setSelectedRange(null); // Remove selected box
|
|
6543
6911
|
}, onUpdate: handlePlotUpdate, useResizeHandler: true, style: {
|
|
6544
6912
|
width: "100%",
|
|
6545
6913
|
height: "100%",
|
|
6546
|
-
display: "block"
|
|
6547
|
-
} }, "histogram-".concat(plotId ||
|
|
6914
|
+
display: "block",
|
|
6915
|
+
} }, "histogram-".concat(plotId || "default")) }) }) }));
|
|
6548
6916
|
};
|
|
6549
6917
|
|
|
6550
6918
|
var Plot$1 = lazy(function () { return import('react-plotly.js'); });
|