td-plots 1.2.0 → 1.2.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
@@ -7807,9 +7807,13 @@ var Loading = function () {
7807
7807
  var Plot$2 = React.lazy(function () { return import('react-plotly.js'); });
7808
7808
  var HistogramPlot = function (props) {
7809
7809
  var _a;
7810
- var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _b = props.barColor, barColor = _b === void 0 ? 'rgb(72, 72, 74)' : _b, _c = props.unselectedBarColor, unselectedBarColor = _c === void 0 ? 'rgba(203, 195, 195, 0.88)' : _c, _d = props.selectorsColor, selectorsColor = _d === void 0 ? 'black' : _d, _e = props.showMeanLine, showMeanLine = _e === void 0 ? true : _e, _f = props.meanLineColor, meanLineColor = _f === void 0 ? 'grey' : _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;
7810
+ var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _b = props.barColor, barColor = _b === void 0 ? 'rgb(72, 72, 74)' : _b, _c = props.unselectedBarColor, unselectedBarColor = _c === void 0 ? 'rgba(203, 195, 195, 0.88)' : _c, _d = props.selectorsColor, selectorsColor = _d === void 0 ? 'black' : _d, _e = props.showMeanLine, showMeanLine = _e === void 0 ? true : _e, containerStyleOverrides = props.containerStyleOverrides, _f = props.unselectedData, unselectedData = _f === void 0 ? [] : _f, _g = props.handleClickOrSelection, handleClickOrSelection = _g === void 0 ? function () { } : _g, _h = props.onDeselect, onDeselect = _h === void 0 ? function () { } : _h, plotId = props.plotId;
7811
7811
  // Ref for plot container
7812
7812
  var containerRef = React.useRef(null);
7813
+ // Track any selections made in this plot so we can style the selection box.
7814
+ var _j = React.useState(null), selectedRange = _j[0], setSelectedRange = _j[1];
7815
+ // Set the bins based on the entire data set.
7816
+ var nBins = Math.ceil(Math.sqrt(data.length + unselectedData.length));
7813
7817
  // Create handler for click event that can use event data to update the plot if desired.
7814
7818
  var handleClick = function (event) {
7815
7819
  if (!event || !event.points || event.points.length === 0) {
@@ -7820,9 +7824,8 @@ var HistogramPlot = function (props) {
7820
7824
  if (event.points[0].curveNumber !== 0) {
7821
7825
  return;
7822
7826
  }
7823
- // If we are given a function to update the data (handleClickOrSelection), use
7824
- // the bin number to determine which bar was clicked and determine the range of the clicked bar.
7825
- if (handleClickOrSelection && "binNumber" in event.points[0] && typeof event.points[0].binNumber === 'number') {
7827
+ // Use the bin number to determine which bar was clicked and determine the range of the clicked bar.
7828
+ if ("binNumber" in event.points[0] && typeof event.points[0].binNumber === 'number') {
7826
7829
  // Get the index of the clicked bar with respect to the trace. So if
7827
7830
  // my trace has only one bar (0, 1] but another trace has bars (-1, 0], (0, 1], (1, 2], etc.
7828
7831
  // then when I click on (0, 1] in my trace the index will be 0, even thought it would be
@@ -7861,9 +7864,11 @@ var HistogramPlot = function (props) {
7861
7864
  var minDate = new Date(minBinValue);
7862
7865
  var maxDate = new Date(maxBinValue);
7863
7866
  handleClickOrSelection(minDate, maxDate);
7867
+ setSelectedRange([minDate, maxDate]);
7864
7868
  }
7865
7869
  else {
7866
7870
  handleClickOrSelection(minBinValue, maxBinValue);
7871
+ setSelectedRange([minBinValue, maxBinValue]);
7867
7872
  }
7868
7873
  }
7869
7874
  };
@@ -7878,17 +7883,36 @@ var HistogramPlot = function (props) {
7878
7883
  // Then we must be dealing with dates
7879
7884
  minValue = new Date(event.range.x[0]);
7880
7885
  maxValue = new Date(event.range.x[1]);
7886
+ setSelectedRange([minValue, maxValue]);
7881
7887
  }
7882
7888
  else {
7883
7889
  minValue = event.range.x[0];
7884
7890
  maxValue = event.range.x[1];
7891
+ setSelectedRange([minValue, maxValue]);
7885
7892
  }
7886
- if (handleClickOrSelection) {
7887
- handleClickOrSelection(minValue, maxValue);
7888
- }
7893
+ handleClickOrSelection(minValue, maxValue);
7889
7894
  };
7890
- // Set the bins based on the entire data set.
7891
- var nBins = Math.ceil(Math.sqrt(data.length + unselectedData.length));
7895
+ // Create the selected range box
7896
+ var selectedRangeBox = React.useMemo(function () {
7897
+ if (!selectedRange)
7898
+ return [];
7899
+ // Create a multiply-like effect by using a semi-transparent dark overlay
7900
+ var multiplyColor = 'rgba(29, 104, 185, 0.1)';
7901
+ return [{
7902
+ type: 'rect',
7903
+ x0: isDateArray(selectedRange) ? selectedRange[0].getTime() : selectedRange[0],
7904
+ x1: isDateArray(selectedRange) ? selectedRange[1].getTime() : selectedRange[1],
7905
+ y0: 0,
7906
+ y1: 1,
7907
+ yref: 'paper',
7908
+ fillcolor: multiplyColor,
7909
+ line: {
7910
+ width: 1,
7911
+ color: multiplyColor
7912
+ },
7913
+ layer: 'above' // Ensure the selection box is above the bars
7914
+ }];
7915
+ }, [selectedRange]);
7892
7916
  var unselectedTrace = {
7893
7917
  x: unselectedData,
7894
7918
  type: 'histogram',
@@ -7937,18 +7961,21 @@ var HistogramPlot = function (props) {
7937
7961
  isDateArray(allData) ? new Date(dataMin - padding) : dataMin - padding,
7938
7962
  isDateArray(allData) ? new Date(dataMax + padding) : dataMax + padding
7939
7963
  ];
7964
+ var meanLineRadius = 0.01; // distance from the top of the y axis to the top/bottom end of the mean line
7940
7965
  var meanLine = showMeanLine ? {
7941
7966
  type: 'line',
7942
7967
  x0: meanValue,
7943
- y0: 0,
7968
+ y0: 1 - meanLineRadius,
7944
7969
  x1: meanValue,
7945
7970
  yref: 'paper',
7946
- y1: 1.04, // Extend slightly above so we can annotate better
7971
+ y1: 1 + meanLineRadius + 0.04, // Add extra length above to make the line look centered on the y-axis top.
7947
7972
  line: {
7948
- color: meanLineColor,
7973
+ color: barColor,
7949
7974
  width: 1.5,
7950
7975
  }
7951
7976
  } : {};
7977
+ // Draw the mean line annotation on right unless the mean is too close to the upper end of the x-axis range.
7978
+ var drawMeanAnnotationOnRight = meanValue < (0.75 * (fixedXAxisRange[1] - fixedXAxisRange[0]) + fixedXAxisRange[0]);
7952
7979
  var layout = {
7953
7980
  title: {
7954
7981
  text: title,
@@ -7985,8 +8012,10 @@ var HistogramPlot = function (props) {
7985
8012
  },
7986
8013
  yaxis: {
7987
8014
  title: {
7988
- text: 'Count'
8015
+ text: 'Count',
8016
+ standoff: 12, // Add space between title and axis
7989
8017
  },
8018
+ automargin: true, // Required for standoff to work properly
7990
8019
  showgrid: true,
7991
8020
  zeroline: false,
7992
8021
  showline: true,
@@ -8003,19 +8032,22 @@ var HistogramPlot = function (props) {
8003
8032
  bargap: 0.03, // Gap between bars
8004
8033
  dragmode: 'select', // Enable drag to select
8005
8034
  selectdirection: 'h', // User can select in horizontal direction only
8006
- shapes: meanLine ? [meanLine] : [], // Add the mean line if it exists
8007
- annotations: showMeanLine ? [{
8035
+ shapes: __spreadArray([meanLine], selectedRangeBox, true), // Add the mean line and selection box
8036
+ annotations: (showMeanLine && meanLine) ? [{
8008
8037
  x: meanValue,
8009
- y: 1.12, // Position above the top of the plot
8038
+ y: 1 + meanLineRadius + 0.12, // Position above the mean line
8010
8039
  yref: 'paper',
8011
8040
  text: "Mean: ".concat(isDateArray(data) ? new Date(meanValue).toLocaleDateString('en-US', {
8012
8041
  month: 'short',
8013
8042
  day: '2-digit',
8014
8043
  year: 'numeric'
8015
8044
  }) : meanValue.toFixed(2)),
8016
- showarrow: false, // No arrow for the annotation
8045
+ xanchor: drawMeanAnnotationOnRight ? 'left' : 'right',
8046
+ yanchor: 'top',
8047
+ xshift: drawMeanAnnotationOnRight ? -3 : 3,
8048
+ showarrow: false,
8017
8049
  font: {
8018
- color: meanLineColor,
8050
+ color: barColor,
8019
8051
  size: 12,
8020
8052
  },
8021
8053
  }] : [],
@@ -8028,7 +8060,10 @@ var HistogramPlot = function (props) {
8028
8060
  staticPlot: false, // Enable interactivity
8029
8061
  };
8030
8062
  var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
8031
- return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container ".concat(plotId), style: __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: onDeselect, useResizeHandler: true, style: {
8063
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container ".concat(plotId), style: __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 () {
8064
+ onDeselect();
8065
+ setSelectedRange(null); // Remove selected box
8066
+ }, useResizeHandler: true, style: {
8032
8067
  width: "100%",
8033
8068
  height: "100%",
8034
8069
  display: "block"