td-plots 1.2.2 → 1.3.1

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/index.js CHANGED
@@ -5860,7 +5860,7 @@ var Loading = function () {
5860
5860
  var Plot$2 = React.lazy(function () { return import('react-plotly.js'); });
5861
5861
  var HistogramPlot = function (props) {
5862
5862
  var _a, _b;
5863
- var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _c = props.barColor, barColor = _c === void 0 ? 'rgb(72, 72, 74)' : _c, _d = props.unselectedBarColor, unselectedBarColor = _d === void 0 ? 'rgba(203, 195, 195, 0.88)' : _d, _e = props.selectorsColor, selectorsColor = _e === void 0 ? 'black' : _e, _f = props.showMeanLine, showMeanLine = _f === void 0 ? true : _f, _g = props.showAllDataMeanLine, showAllDataMeanLine = _g === void 0 ? true : _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;
5863
+ var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _c = props.barColor, barColor = _c === void 0 ? 'rgb(72, 72, 74)' : _c, _d = props.unselectedBarColor, unselectedBarColor = _d === void 0 ? 'rgba(203, 195, 195, 0.88)' : _d, _e = props.selectorsColor, selectorsColor = _e === void 0 ? 'black' : _e, _f = props.showMeanLines, showMeanLines = _f === void 0 ? true : _f, containerStyleOverrides = props.containerStyleOverrides, _g = props.unselectedData, unselectedData = _g === void 0 ? [] : _g, _h = props.handleClickOrSelection, handleClickOrSelection = _h === void 0 ? function () { } : _h, _j = props.onDeselect, onDeselect = _j === void 0 ? function () { } : _j, plotId = props.plotId, _k = props.selectByBin, selectByBin = _k === void 0 ? false : _k;
5864
5864
  // Ref for plot container
5865
5865
  var containerRef = React.useRef(null);
5866
5866
  // Track any selections made in this plot so we can style the selection box.
@@ -5871,14 +5871,23 @@ var HistogramPlot = function (props) {
5871
5871
  // to access that information once the plot has been initialized so that we can prevent the
5872
5872
  // axis range from changing during interaction. Dates use strings.
5873
5873
  var _m = React.useState(undefined), fixedXAxisRange = _m[0], setFixedXAxisRange = _m[1];
5874
+ // Once the plot is drawn, record the initial axis range so we can keep it fixed.
5874
5875
  // figure should be Readonly<Plotly.Figure> but react-plotly.js doesn't expose that type, so we use any.
5875
- var handlePlotInitialized = function (figure, graphDiv) {
5876
- var _a, _b;
5877
- if (((_b = (_a = figure.layout) === null || _a === void 0 ? void 0 : _a.xaxis) === null || _b === void 0 ? void 0 : _b.range) && !fixedXAxisRange) {
5878
- var computedRange = typeof (figure.layout.xaxis.range[0]) === 'string'
5879
- ? [new Date(figure.layout.xaxis.range[0]), new Date(figure.layout.xaxis.range[1])]
5880
- : [figure.layout.xaxis.range[0], figure.layout.xaxis.range[1]];
5881
- setFixedXAxisRange(computedRange);
5876
+ var handlePlotUpdate = function (figure, graphDiv) {
5877
+ var _a;
5878
+ if (!fixedXAxisRange) {
5879
+ var currentLayout = graphDiv._fullLayout;
5880
+ if ((_a = currentLayout === null || currentLayout === void 0 ? void 0 : currentLayout.xaxis) === null || _a === void 0 ? void 0 : _a.range) {
5881
+ var range = currentLayout.xaxis.range;
5882
+ // Skip temporary [-1, 1] range
5883
+ if (range[0] === -1 && range[1] === 1) {
5884
+ return;
5885
+ }
5886
+ var computedRange = typeof (range[0]) === 'string'
5887
+ ? [new Date(range[0]), new Date(range[1])]
5888
+ : [range[0], range[1]];
5889
+ setFixedXAxisRange(computedRange);
5890
+ }
5882
5891
  }
5883
5892
  };
5884
5893
  // Create handler for click event that can use event data to update the plot if desired.
@@ -5947,22 +5956,73 @@ var HistogramPlot = function (props) {
5947
5956
  var minValue;
5948
5957
  var maxValue;
5949
5958
  if (typeof event.range.x[0] === 'string' && typeof event.range.x[1] === 'string') {
5950
- // Then we must be dealing with dates
5951
- minValue = new Date(event.range.x[0]);
5952
- maxValue = new Date(event.range.x[1]);
5953
- setSelectedRange([minValue, maxValue]);
5959
+ // Then we are must be dealing with dates
5960
+ if (selectByBin) {
5961
+ // Set selected range to include the whole bin if at least half the bin is within the explicit range
5962
+ // Plotly already tells us which bins were selected based on this logic. These are the points in the event.
5963
+ if (event.points && event.points.length > 0) {
5964
+ // Means at least one bin has been selected
5965
+ var firstBinMidPoint = new Date(event.points[0].x).getTime();
5966
+ var lastBinMidPoint = new Date(event.points[event.points.length - 1].x).getTime();
5967
+ var binSize = event.points[0].data.xbins.size;
5968
+ minValue = new Date(firstBinMidPoint - binSize / 2);
5969
+ maxValue = new Date(lastBinMidPoint + binSize / 2);
5970
+ }
5971
+ else {
5972
+ // No bins selected, so the range should be empty.
5973
+ minValue = new Date(event.range.x[0]);
5974
+ maxValue = minValue;
5975
+ }
5976
+ }
5977
+ else {
5978
+ // Set the range based on the explicit selection boundaries
5979
+ minValue = new Date(event.range.x[0]);
5980
+ maxValue = new Date(event.range.x[1]);
5981
+ }
5954
5982
  }
5955
5983
  else {
5956
- minValue = event.range.x[0];
5957
- maxValue = event.range.x[1];
5958
- setSelectedRange([minValue, maxValue]);
5984
+ // Handle selection for numbers
5985
+ if (selectByBin) {
5986
+ // Set the range based on the bins selected. Plotly will include a bin in event.points if
5987
+ // at least half of it is selected.
5988
+ if (event.points && event.points.length > 0) {
5989
+ var firstBinMidPoint = event.points[0].x;
5990
+ var lastBinMidPoint = event.points[event.points.length - 1].x;
5991
+ var binSize = event.points[0].data.xbins.size;
5992
+ var roundedMinValue = firstBinMidPoint - binSize / 2;
5993
+ var roundedMaxValue = lastBinMidPoint + binSize / 2;
5994
+ minValue = roundedMinValue;
5995
+ maxValue = roundedMaxValue;
5996
+ }
5997
+ else {
5998
+ // No bins selected, so set the range to be empty.
5999
+ minValue = event.range.x[0];
6000
+ maxValue = minValue;
6001
+ }
6002
+ }
6003
+ else {
6004
+ // Set the range based on the explicit selection boundaries
6005
+ minValue = event.range.x[0];
6006
+ maxValue = event.range.x[1];
6007
+ }
6008
+ }
6009
+ if (minValue !== undefined && maxValue !== undefined) {
6010
+ // Update selected range. Have to be strict about types.
6011
+ if (typeof minValue === 'number' && typeof maxValue === 'number') {
6012
+ setSelectedRange([minValue, maxValue]);
6013
+ }
6014
+ else if (minValue instanceof Date && maxValue instanceof Date) {
6015
+ setSelectedRange([minValue, maxValue]);
6016
+ }
6017
+ handleClickOrSelection(minValue, maxValue);
5959
6018
  }
5960
- handleClickOrSelection(minValue, maxValue);
5961
6019
  };
5962
6020
  // Create the selected range box
5963
6021
  var selectedRangeBox = React.useMemo(function () {
5964
6022
  if (!selectedRange)
5965
6023
  return [];
6024
+ if (unselectedData.length === 0)
6025
+ return []; // Don't show the box if the entire dataset is selected.
5966
6026
  // Create a multiply-like effect by using a semi-transparent dark overlay
5967
6027
  var multiplyColor = 'rgba(29, 104, 185, 0.1)';
5968
6028
  return [{
@@ -5979,7 +6039,7 @@ var HistogramPlot = function (props) {
5979
6039
  },
5980
6040
  layer: 'above' // Ensure the selection box is above the bars
5981
6041
  }];
5982
- }, [selectedRange]);
6042
+ }, [selectedRange, unselectedData]);
5983
6043
  var unselectedTrace = {
5984
6044
  x: unselectedData,
5985
6045
  type: 'histogram',
@@ -6018,7 +6078,7 @@ var HistogramPlot = function (props) {
6018
6078
  // Calculate the mean of the selected data using normalized data
6019
6079
  var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
6020
6080
  var meanLineRadius = 0.01; // distance from the top of the y axis to the top/bottom end of the mean line
6021
- var meanLine = showMeanLine ? [{
6081
+ var meanLine = (showMeanLines && data.length > 0) ? [{
6022
6082
  type: 'line',
6023
6083
  x0: meanValue,
6024
6084
  y0: 1 - meanLineRadius,
@@ -6033,7 +6093,7 @@ var HistogramPlot = function (props) {
6033
6093
  // Draw mean line for all data
6034
6094
  var allData = tslib.__spreadArray(tslib.__spreadArray([], data, true), unselectedData, true);
6035
6095
  var allDataMeanValue = (_b = calculateMean(allData)) !== null && _b !== void 0 ? _b : 0;
6036
- var allDataMeanLine = (showAllDataMeanLine && unselectedData.length > 0) ? [{
6096
+ var allDataMeanLine = (showMeanLines && unselectedData.length > 0 && data.length > 0) ? [{
6037
6097
  type: 'line',
6038
6098
  x0: allDataMeanValue,
6039
6099
  y0: 1 - meanLineRadius,
@@ -6102,7 +6162,7 @@ var HistogramPlot = function (props) {
6102
6162
  dragmode: 'select', // Enable drag to select
6103
6163
  selectdirection: 'h', // User can select in horizontal direction only
6104
6164
  shapes: tslib.__spreadArray(tslib.__spreadArray(tslib.__spreadArray([], allDataMeanLine, true), meanLine, true), selectedRangeBox, true), // Add the mean line and selection box
6105
- annotations: (showMeanLine && meanLine) ? [{
6165
+ annotations: (showMeanLines && meanLine && data.length > 0) ? [{
6106
6166
  x: meanValue,
6107
6167
  y: 1 + meanLineRadius + 0.04, // Position above the mean line. Value set with respect to the paper coordinates.
6108
6168
  yref: 'paper',
@@ -6131,7 +6191,7 @@ var HistogramPlot = function (props) {
6131
6191
  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 () {
6132
6192
  onDeselect();
6133
6193
  setSelectedRange(null); // Remove selected box
6134
- }, onInitialized: handlePlotInitialized, useResizeHandler: true, style: {
6194
+ }, onUpdate: handlePlotUpdate, useResizeHandler: true, style: {
6135
6195
  width: "100%",
6136
6196
  height: "100%",
6137
6197
  display: "block"