td-plots 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,7 @@ export type HistogramPlotProps = {
14
14
  containerStyleOverrides?: React.CSSProperties;
15
15
  onDeselect?: () => void;
16
16
  plotId?: string;
17
+ selectByBin?: boolean;
17
18
  };
18
19
  export declare const HistogramPlot: (props: HistogramPlotProps) => import("react/jsx-runtime").JSX.Element;
19
20
  export default HistogramPlot;
package/dist/index.esm.js CHANGED
@@ -5840,25 +5840,35 @@ var Loading = function () {
5840
5840
  var Plot$2 = lazy(function () { return import('react-plotly.js'); });
5841
5841
  var HistogramPlot = function (props) {
5842
5842
  var _a, _b;
5843
- 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;
5843
+ 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, _l = props.selectByBin, selectByBin = _l === void 0 ? false : _l;
5844
5844
  // Ref for plot container
5845
5845
  var containerRef = useRef(null);
5846
5846
  // Track any selections made in this plot so we can style the selection box.
5847
- var _l = useState(null), selectedRange = _l[0], setSelectedRange = _l[1];
5847
+ var _m = useState(null), selectedRange = _m[0], setSelectedRange = _m[1];
5848
5848
  // Set the bins based on the entire data set.
5849
5849
  var nBins = Math.ceil(Math.sqrt(data.length + unselectedData.length));
5850
5850
  // Plotly determines "nice" bins which consequently means it internally decides the axis range. We need
5851
5851
  // to access that information once the plot has been initialized so that we can prevent the
5852
5852
  // axis range from changing during interaction. Dates use strings.
5853
- var _m = useState(undefined), fixedXAxisRange = _m[0], setFixedXAxisRange = _m[1];
5853
+ var _o = useState(undefined), fixedXAxisRange = _o[0], setFixedXAxisRange = _o[1];
5854
+ // Once the plot is drawn, record the initial axis range so we can keep it fixed.
5854
5855
  // figure should be Readonly<Plotly.Figure> but react-plotly.js doesn't expose that type, so we use any.
5855
- var handlePlotInitialized = function (figure, graphDiv) {
5856
- var _a, _b;
5857
- if (((_b = (_a = figure.layout) === null || _a === void 0 ? void 0 : _a.xaxis) === null || _b === void 0 ? void 0 : _b.range) && !fixedXAxisRange) {
5858
- var computedRange = typeof (figure.layout.xaxis.range[0]) === 'string'
5859
- ? [new Date(figure.layout.xaxis.range[0]), new Date(figure.layout.xaxis.range[1])]
5860
- : [figure.layout.xaxis.range[0], figure.layout.xaxis.range[1]];
5861
- setFixedXAxisRange(computedRange);
5856
+ var handlePlotUpdate = function (figure, graphDiv) {
5857
+ var _a;
5858
+ if (!fixedXAxisRange) {
5859
+ var currentLayout = graphDiv._fullLayout;
5860
+ if ((_a = currentLayout === null || currentLayout === void 0 ? void 0 : currentLayout.xaxis) === null || _a === void 0 ? void 0 : _a.range) {
5861
+ var range = currentLayout.xaxis.range;
5862
+ // Skip temporary [-1, 1] range
5863
+ if (range[0] === -1 && range[1] === 1) {
5864
+ return;
5865
+ }
5866
+ var computedRange = typeof (range[0]) === 'string'
5867
+ ? [new Date(range[0]), new Date(range[1])]
5868
+ : [range[0], range[1]];
5869
+ console.log('Captured range from onUpdate:', computedRange);
5870
+ setFixedXAxisRange(computedRange);
5871
+ }
5862
5872
  }
5863
5873
  };
5864
5874
  // Create handler for click event that can use event data to update the plot if desired.
@@ -5927,18 +5937,68 @@ var HistogramPlot = function (props) {
5927
5937
  var minValue;
5928
5938
  var maxValue;
5929
5939
  if (typeof event.range.x[0] === 'string' && typeof event.range.x[1] === 'string') {
5930
- // Then we must be dealing with dates
5931
- minValue = new Date(event.range.x[0]);
5932
- maxValue = new Date(event.range.x[1]);
5933
- setSelectedRange([minValue, maxValue]);
5940
+ // Then we are must be dealing with dates
5941
+ if (selectByBin) {
5942
+ // Set selected range to include the whole bin if at least half the bin is within the explicit range
5943
+ // Plotly already tells us which bins were selected based on this logic. These are the points in the event.
5944
+ if (event.points && event.points.length > 0) {
5945
+ // Means at least one bin has been selected
5946
+ var firstBinMidPoint = new Date(event.points[0].x).getTime();
5947
+ var lastBinMidPoint = new Date(event.points[event.points.length - 1].x).getTime();
5948
+ var binSize = event.points[0].data.xbins.size;
5949
+ minValue = new Date(firstBinMidPoint - binSize / 2);
5950
+ maxValue = new Date(lastBinMidPoint + binSize / 2);
5951
+ }
5952
+ else {
5953
+ // No bins selected, so the range should be empty.
5954
+ minValue = new Date(event.range.x[0]);
5955
+ maxValue = minValue;
5956
+ }
5957
+ }
5958
+ else {
5959
+ // Set the range based on the explicit selection boundaries
5960
+ minValue = new Date(event.range.x[0]);
5961
+ maxValue = new Date(event.range.x[1]);
5962
+ }
5934
5963
  }
5935
5964
  else {
5936
- minValue = event.range.x[0];
5937
- maxValue = event.range.x[1];
5938
- setSelectedRange([minValue, maxValue]);
5965
+ // Handle selection for numbers
5966
+ if (selectByBin) {
5967
+ // Set the range based on the bins selected. Plotly will include a bin in event.points if
5968
+ // at least half of it is selected.
5969
+ if (event.points && event.points.length > 0) {
5970
+ var firstBinMidPoint = event.points[0].x;
5971
+ var lastBinMidPoint = event.points[event.points.length - 1].x;
5972
+ var binSize = event.points[0].data.xbins.size;
5973
+ var roundedMinValue = firstBinMidPoint - binSize / 2;
5974
+ var roundedMaxValue = lastBinMidPoint + binSize / 2;
5975
+ minValue = roundedMinValue;
5976
+ maxValue = roundedMaxValue;
5977
+ }
5978
+ else {
5979
+ // No bins selected, so set the range to be empty.
5980
+ minValue = event.range.x[0];
5981
+ maxValue = minValue;
5982
+ }
5983
+ }
5984
+ else {
5985
+ // Set the range based on the explicit selection boundaries
5986
+ minValue = event.range.x[0];
5987
+ maxValue = event.range.x[1];
5988
+ }
5989
+ }
5990
+ if (minValue !== undefined && maxValue !== undefined) {
5991
+ // Update selected range. Have to be strict about types.
5992
+ if (typeof minValue === 'number' && typeof maxValue === 'number') {
5993
+ setSelectedRange([minValue, maxValue]);
5994
+ }
5995
+ else if (minValue instanceof Date && maxValue instanceof Date) {
5996
+ setSelectedRange([minValue, maxValue]);
5997
+ }
5998
+ handleClickOrSelection(minValue, maxValue);
5939
5999
  }
5940
- handleClickOrSelection(minValue, maxValue);
5941
6000
  };
6001
+ console.log('fixed range', fixedXAxisRange);
5942
6002
  // Create the selected range box
5943
6003
  var selectedRangeBox = useMemo(function () {
5944
6004
  if (!selectedRange)
@@ -6111,7 +6171,7 @@ var HistogramPlot = function (props) {
6111
6171
  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 () {
6112
6172
  onDeselect();
6113
6173
  setSelectedRange(null); // Remove selected box
6114
- }, onInitialized: handlePlotInitialized, useResizeHandler: true, style: {
6174
+ }, onUpdate: handlePlotUpdate, useResizeHandler: true, style: {
6115
6175
  width: "100%",
6116
6176
  height: "100%",
6117
6177
  display: "block"