stream-charts 1.2.1 → 2.0.0
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/LICENSE +21 -0
- package/README.md +809 -1022
- package/changes.md +36 -0
- package/dist/app/charts/Chart.d.ts +35 -139
- package/dist/app/charts/Chart.d.ts.map +1 -0
- package/dist/app/charts/Chart.js +74 -65
- package/dist/app/charts/Chart.js.map +1 -1
- package/dist/app/charts/axes/AxesState.d.ts +26 -18
- package/dist/app/charts/axes/AxesState.d.ts.map +1 -0
- package/dist/app/charts/axes/AxesState.js +26 -24
- package/dist/app/charts/axes/AxesState.js.map +1 -1
- package/dist/app/charts/axes/AxisInterval.d.ts +44 -26
- package/dist/app/charts/axes/AxisInterval.d.ts.map +1 -0
- package/dist/app/charts/axes/AxisInterval.js +48 -29
- package/dist/app/charts/axes/AxisInterval.js.map +1 -1
- package/dist/app/charts/axes/BaseAxisRange.d.ts +46 -22
- package/dist/app/charts/axes/BaseAxisRange.d.ts.map +1 -0
- package/dist/app/charts/axes/BaseAxisRange.js +17 -12
- package/dist/app/charts/axes/BaseAxisRange.js.map +1 -1
- package/dist/app/charts/axes/ContinuousAxis.d.ts +47 -6
- package/dist/app/charts/axes/ContinuousAxis.d.ts.map +1 -0
- package/dist/app/charts/axes/ContinuousAxis.js +160 -27
- package/dist/app/charts/axes/ContinuousAxis.js.map +1 -1
- package/dist/app/charts/axes/ContinuousAxisRange.d.ts +29 -10
- package/dist/app/charts/axes/ContinuousAxisRange.d.ts.map +1 -0
- package/dist/app/charts/axes/ContinuousAxisRange.js +29 -11
- package/dist/app/charts/axes/ContinuousAxisRange.js.map +1 -1
- package/dist/app/charts/axes/EmptyAxis.d.ts +5 -2
- package/dist/app/charts/axes/EmptyAxis.d.ts.map +1 -0
- package/dist/app/charts/axes/EmptyAxis.js +30 -9
- package/dist/app/charts/axes/EmptyAxis.js.map +1 -1
- package/dist/app/charts/axes/OrdinalAxis.d.ts +5 -3
- package/dist/app/charts/axes/OrdinalAxis.d.ts.map +1 -0
- package/dist/app/charts/axes/OrdinalAxis.js +39 -16
- package/dist/app/charts/axes/OrdinalAxis.js.map +1 -1
- package/dist/app/charts/axes/OrdinalAxisRange.d.ts +76 -13
- package/dist/app/charts/axes/OrdinalAxisRange.d.ts.map +1 -0
- package/dist/app/charts/axes/OrdinalAxisRange.js +95 -16
- package/dist/app/charts/axes/OrdinalAxisRange.js.map +1 -1
- package/dist/app/charts/axes/autoScale.d.ts +111 -0
- package/dist/app/charts/axes/autoScale.d.ts.map +1 -0
- package/dist/app/charts/axes/autoScale.js +188 -0
- package/dist/app/charts/axes/autoScale.js.map +1 -0
- package/dist/app/charts/axes/axes.d.ts +273 -150
- package/dist/app/charts/axes/axes.d.ts.map +1 -0
- package/dist/app/charts/axes/axes.js +808 -583
- package/dist/app/charts/axes/axes.js.map +1 -1
- package/dist/app/charts/d3types.d.ts +40 -11
- package/dist/app/charts/d3types.d.ts.map +1 -0
- package/dist/app/charts/d3types.js +3 -0
- package/dist/app/charts/d3types.js.map +1 -1
- package/dist/app/charts/datasources/StreamingDataSource.d.ts +149 -0
- package/dist/app/charts/datasources/StreamingDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/StreamingDataSource.js +110 -0
- package/dist/app/charts/datasources/StreamingDataSource.js.map +1 -0
- package/dist/app/charts/datasources/iteratesDataSource.d.ts +73 -0
- package/dist/app/charts/datasources/iteratesDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/iteratesDataSource.js +87 -0
- package/dist/app/charts/datasources/iteratesDataSource.js.map +1 -0
- package/dist/app/charts/datasources/ordinalDataSource.d.ts +75 -0
- package/dist/app/charts/datasources/ordinalDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/ordinalDataSource.js +135 -0
- package/dist/app/charts/datasources/ordinalDataSource.js.map +1 -0
- package/dist/app/charts/datasources/outlierDataSource.d.ts +53 -0
- package/dist/app/charts/datasources/outlierDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/outlierDataSource.js +57 -0
- package/dist/app/charts/datasources/outlierDataSource.js.map +1 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.d.ts +77 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.d.ts.map +1 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.js +85 -0
- package/dist/app/charts/datasources/timeSeriesDataSource.js.map +1 -0
- package/dist/app/charts/filters/regexFilter.d.ts +31 -4
- package/dist/app/charts/filters/regexFilter.d.ts.map +1 -0
- package/dist/app/charts/filters/regexFilter.js +38 -4
- package/dist/app/charts/filters/regexFilter.js.map +1 -1
- package/dist/app/charts/hooks/AxesProvider.d.ts +21 -0
- package/dist/app/charts/hooks/AxesProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/AxesProvider.js +213 -0
- package/dist/app/charts/hooks/AxesProvider.js.map +1 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.d.ts +25 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.js +76 -0
- package/dist/app/charts/hooks/CanvasSurfaceProvider.js.map +1 -0
- package/dist/app/charts/hooks/ChartProvider.d.ts +40 -0
- package/dist/app/charts/hooks/ChartProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/ChartProvider.js +33 -0
- package/dist/app/charts/hooks/ChartProvider.js.map +1 -0
- package/dist/app/charts/hooks/InteractionProvider.d.ts +23 -0
- package/dist/app/charts/hooks/InteractionProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/InteractionProvider.js +60 -0
- package/dist/app/charts/hooks/InteractionProvider.js.map +1 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.d.ts +16 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.d.ts.map +1 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.js +76 -0
- package/dist/app/charts/hooks/PlotDimensionsProvider.js.map +1 -0
- package/dist/app/charts/hooks/defaultAxesValues.d.ts +11 -0
- package/dist/app/charts/hooks/defaultAxesValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultAxesValues.js +36 -0
- package/dist/app/charts/hooks/defaultAxesValues.js.map +1 -0
- package/dist/app/charts/hooks/defaultMouseValues.d.ts +9 -0
- package/dist/app/charts/hooks/defaultMouseValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultMouseValues.js +23 -0
- package/dist/app/charts/hooks/defaultMouseValues.js.map +1 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.d.ts +13 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.js +23 -0
- package/dist/app/charts/hooks/defaultPlotDimensions.js.map +1 -0
- package/dist/app/charts/hooks/defaultTooltipValues.d.ts +9 -0
- package/dist/app/charts/hooks/defaultTooltipValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultTooltipValues.js +21 -0
- package/dist/app/charts/hooks/defaultTooltipValues.js.map +1 -0
- package/dist/app/charts/hooks/defaultUseChartValues.d.ts +14 -0
- package/dist/app/charts/hooks/defaultUseChartValues.d.ts.map +1 -0
- package/dist/app/charts/hooks/defaultUseChartValues.js +30 -0
- package/dist/app/charts/hooks/defaultUseChartValues.js.map +1 -0
- package/dist/app/charts/hooks/useAxes.d.ts +49 -36
- package/dist/app/charts/hooks/useAxes.d.ts.map +1 -0
- package/dist/app/charts/hooks/useAxes.js +16 -176
- package/dist/app/charts/hooks/useAxes.js.map +1 -1
- package/dist/app/charts/hooks/useCanvasSurface.d.ts +25 -0
- package/dist/app/charts/hooks/useCanvasSurface.d.ts.map +1 -0
- package/dist/app/charts/hooks/useCanvasSurface.js +18 -0
- package/dist/app/charts/hooks/useCanvasSurface.js.map +1 -0
- package/dist/app/charts/hooks/useChart.d.ts +30 -44
- package/dist/app/charts/hooks/useChart.d.ts.map +1 -0
- package/dist/app/charts/hooks/useChart.js +26 -48
- package/dist/app/charts/hooks/useChart.js.map +1 -1
- package/dist/app/charts/hooks/useDataSource.d.ts +68 -0
- package/dist/app/charts/hooks/useDataSource.d.ts.map +1 -0
- package/dist/app/charts/hooks/useDataSource.js +63 -0
- package/dist/app/charts/hooks/useDataSource.js.map +1 -0
- package/dist/app/charts/hooks/useHoveredSeries.d.ts +25 -0
- package/dist/app/charts/hooks/useHoveredSeries.d.ts.map +1 -0
- package/dist/app/charts/hooks/useHoveredSeries.js +15 -0
- package/dist/app/charts/hooks/useHoveredSeries.js.map +1 -0
- package/dist/app/charts/hooks/useMouse.d.ts +46 -22
- package/dist/app/charts/hooks/useMouse.d.ts.map +1 -0
- package/dist/app/charts/hooks/useMouse.js +12 -56
- package/dist/app/charts/hooks/useMouse.js.map +1 -1
- package/dist/app/charts/hooks/usePlotDimensions.d.ts +25 -13
- package/dist/app/charts/hooks/usePlotDimensions.d.ts.map +1 -0
- package/dist/app/charts/hooks/usePlotDimensions.js +6 -62
- package/dist/app/charts/hooks/usePlotDimensions.js.map +1 -1
- package/dist/app/charts/hooks/useTooltip.d.ts +24 -26
- package/dist/app/charts/hooks/useTooltip.d.ts.map +1 -0
- package/dist/app/charts/hooks/useTooltip.js +12 -42
- package/dist/app/charts/hooks/useTooltip.js.map +1 -1
- package/dist/app/charts/index.d.ts +66 -0
- package/dist/app/charts/index.d.ts.map +1 -0
- package/dist/app/charts/index.js +87 -0
- package/dist/app/charts/index.js.map +1 -0
- package/dist/app/charts/legends/Legend.d.ts +33 -12
- package/dist/app/charts/legends/Legend.d.ts.map +1 -0
- package/dist/app/charts/legends/Legend.js +138 -379
- package/dist/app/charts/legends/Legend.js.map +1 -1
- package/dist/app/charts/legends/constants.d.ts +19 -0
- package/dist/app/charts/legends/constants.d.ts.map +1 -0
- package/dist/app/charts/legends/constants.js +34 -0
- package/dist/app/charts/legends/constants.js.map +1 -0
- package/dist/app/charts/observables/ChartData.d.ts +1 -0
- package/dist/app/charts/observables/ChartData.d.ts.map +1 -0
- package/dist/app/charts/observables/iterates.d.ts +13 -7
- package/dist/app/charts/observables/iterates.d.ts.map +1 -0
- package/dist/app/charts/observables/iterates.js +42 -9
- package/dist/app/charts/observables/iterates.js.map +1 -1
- package/dist/app/charts/observables/ordinals.d.ts +70 -12
- package/dist/app/charts/observables/ordinals.d.ts.map +1 -0
- package/dist/app/charts/observables/ordinals.js +127 -48
- package/dist/app/charts/observables/ordinals.js.map +1 -1
- package/dist/app/charts/observables/outliers.d.ts +18 -0
- package/dist/app/charts/observables/outliers.d.ts.map +1 -0
- package/dist/app/charts/observables/outliers.js +2 -0
- package/dist/app/charts/observables/outliers.js.map +1 -0
- package/dist/app/charts/plots/BarPlot.d.ts +87 -13
- package/dist/app/charts/plots/BarPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/BarPlot.js +603 -356
- package/dist/app/charts/plots/BarPlot.js.map +1 -1
- package/dist/app/charts/plots/OutlierPlot.d.ts +123 -0
- package/dist/app/charts/plots/OutlierPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/OutlierPlot.js +430 -0
- package/dist/app/charts/plots/OutlierPlot.js.map +1 -0
- package/dist/app/charts/plots/PoincarePlot.d.ts +92 -14
- package/dist/app/charts/plots/PoincarePlot.d.ts.map +1 -0
- package/dist/app/charts/plots/PoincarePlot.js +523 -364
- package/dist/app/charts/plots/PoincarePlot.js.map +1 -1
- package/dist/app/charts/plots/RasterPlot.d.ts +31 -10
- package/dist/app/charts/plots/RasterPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/RasterPlot.js +198 -306
- package/dist/app/charts/plots/RasterPlot.js.map +1 -1
- package/dist/app/charts/plots/ScatterPlot.d.ts +77 -21
- package/dist/app/charts/plots/ScatterPlot.d.ts.map +1 -0
- package/dist/app/charts/plots/ScatterPlot.js +359 -302
- package/dist/app/charts/plots/ScatterPlot.js.map +1 -1
- package/dist/app/charts/plots/autoScaleYAxes.d.ts +43 -0
- package/dist/app/charts/plots/autoScaleYAxes.d.ts.map +1 -0
- package/dist/app/charts/plots/autoScaleYAxes.js +71 -0
- package/dist/app/charts/plots/autoScaleYAxes.js.map +1 -0
- package/dist/app/charts/plots/colorizedLine.d.ts +61 -0
- package/dist/app/charts/plots/colorizedLine.d.ts.map +1 -0
- package/dist/app/charts/plots/colorizedLine.js +157 -0
- package/dist/app/charts/plots/colorizedLine.js.map +1 -0
- package/dist/app/charts/plots/constants.d.ts +7 -0
- package/dist/app/charts/plots/constants.d.ts.map +1 -0
- package/dist/app/charts/plots/constants.js +11 -0
- package/dist/app/charts/plots/constants.js.map +1 -0
- package/dist/app/charts/plots/hitTesting.d.ts +88 -0
- package/dist/app/charts/plots/hitTesting.d.ts.map +1 -0
- package/dist/app/charts/plots/hitTesting.js +136 -0
- package/dist/app/charts/plots/hitTesting.js.map +1 -0
- package/dist/app/charts/plots/plot.d.ts +52 -16
- package/dist/app/charts/plots/plot.d.ts.map +1 -0
- package/dist/app/charts/plots/plot.js +108 -35
- package/dist/app/charts/plots/plot.js.map +1 -1
- package/dist/app/charts/plots/useCanvasZoomPan.d.ts +119 -0
- package/dist/app/charts/plots/useCanvasZoomPan.d.ts.map +1 -0
- package/dist/app/charts/plots/useCanvasZoomPan.js +113 -0
- package/dist/app/charts/plots/useCanvasZoomPan.js.map +1 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.d.ts +103 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.d.ts.map +1 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.js +257 -0
- package/dist/app/charts/plots/useStreamingTimeAxes.js.map +1 -0
- package/dist/app/charts/series/baseSeries.d.ts +60 -8
- package/dist/app/charts/series/baseSeries.d.ts.map +1 -0
- package/dist/app/charts/series/baseSeries.js +53 -8
- package/dist/app/charts/series/baseSeries.js.map +1 -1
- package/dist/app/charts/series/iterateSeries.d.ts +9 -8
- package/dist/app/charts/series/iterateSeries.d.ts.map +1 -0
- package/dist/app/charts/series/iterateSeries.js +7 -7
- package/dist/app/charts/series/iterateSeries.js.map +1 -1
- package/dist/app/charts/series/ordinalSeries.d.ts +27 -13
- package/dist/app/charts/series/ordinalSeries.d.ts.map +1 -0
- package/dist/app/charts/series/ordinalSeries.js +29 -15
- package/dist/app/charts/series/ordinalSeries.js.map +1 -1
- package/dist/app/charts/series/outlierSeries.d.ts +142 -0
- package/dist/app/charts/series/outlierSeries.d.ts.map +1 -0
- package/dist/app/charts/series/outlierSeries.js +82 -0
- package/dist/app/charts/series/outlierSeries.js.map +1 -0
- package/dist/app/charts/series/timeSeries.d.ts +13 -9
- package/dist/app/charts/series/timeSeries.d.ts.map +1 -0
- package/dist/app/charts/series/timeSeries.js +6 -3
- package/dist/app/charts/series/timeSeries.js.map +1 -1
- package/dist/app/charts/series/timeSeriesChartData.d.ts +18 -10
- package/dist/app/charts/series/timeSeriesChartData.d.ts.map +1 -0
- package/dist/app/charts/series/timeSeriesChartData.js +28 -14
- package/dist/app/charts/series/timeSeriesChartData.js.map +1 -1
- package/dist/app/charts/styling/barPlotStyle.d.ts +46 -2
- package/dist/app/charts/styling/barPlotStyle.d.ts.map +1 -0
- package/dist/app/charts/styling/barPlotStyle.js +37 -3
- package/dist/app/charts/styling/barPlotStyle.js.map +1 -1
- package/dist/app/charts/styling/canvasStyle.d.ts +53 -0
- package/dist/app/charts/styling/canvasStyle.d.ts.map +1 -0
- package/dist/app/charts/styling/canvasStyle.js +71 -0
- package/dist/app/charts/styling/canvasStyle.js.map +1 -0
- package/dist/app/charts/styling/margins.d.ts +21 -2
- package/dist/app/charts/styling/margins.d.ts.map +1 -0
- package/dist/app/charts/styling/margins.js +25 -4
- package/dist/app/charts/styling/margins.js.map +1 -1
- package/dist/app/charts/styling/svgStyle.d.ts +10 -56
- package/dist/app/charts/styling/svgStyle.d.ts.map +1 -0
- package/dist/app/charts/styling/svgStyle.js +3 -78
- package/dist/app/charts/styling/svgStyle.js.map +1 -1
- package/dist/app/charts/subscriptions/viewDrivers.d.ts +124 -0
- package/dist/app/charts/subscriptions/viewDrivers.d.ts.map +1 -0
- package/dist/app/charts/subscriptions/viewDrivers.js +338 -0
- package/dist/app/charts/subscriptions/viewDrivers.js.map +1 -0
- package/dist/app/charts/tooltips/BarPlotTooltipContent.d.ts +12 -78
- package/dist/app/charts/tooltips/BarPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/BarPlotTooltipContent.js +65 -257
- package/dist/app/charts/tooltips/BarPlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.d.ts +9 -0
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.js +16 -0
- package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.js.map +1 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.d.ts +30 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.js +26 -0
- package/dist/app/charts/tooltips/OutlierPlotTooltipContent.js.map +1 -0
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.d.ts +22 -72
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.js +104 -171
- package/dist/app/charts/tooltips/PoincarePlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.d.ts +32 -8
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.js +62 -115
- package/dist/app/charts/tooltips/RasterPlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.d.ts +39 -12
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.js +162 -134
- package/dist/app/charts/tooltips/ScatterPlotTooltipContent.js.map +1 -1
- package/dist/app/charts/tooltips/Tooltip.d.ts +27 -32
- package/dist/app/charts/tooltips/Tooltip.d.ts.map +1 -0
- package/dist/app/charts/tooltips/Tooltip.js +37 -81
- package/dist/app/charts/tooltips/Tooltip.js.map +1 -1
- package/dist/app/charts/tooltips/TooltipContent.d.ts +81 -0
- package/dist/app/charts/tooltips/TooltipContent.d.ts.map +1 -0
- package/dist/app/charts/tooltips/TooltipContent.js +99 -0
- package/dist/app/charts/tooltips/TooltipContent.js.map +1 -0
- package/dist/app/charts/tooltips/tooltipUtils.d.ts +186 -36
- package/dist/app/charts/tooltips/tooltipUtils.d.ts.map +1 -0
- package/dist/app/charts/tooltips/tooltipUtils.js +277 -48
- package/dist/app/charts/tooltips/tooltipUtils.js.map +1 -1
- package/dist/app/charts/tooltips/useOutlierTooltip.d.ts +59 -0
- package/dist/app/charts/tooltips/useOutlierTooltip.d.ts.map +1 -0
- package/dist/app/charts/tooltips/useOutlierTooltip.js +16 -0
- package/dist/app/charts/tooltips/useOutlierTooltip.js.map +1 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.d.ts +51 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.d.ts.map +1 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.js +52 -0
- package/dist/app/charts/tooltips/useTooltipPlacement.js.map +1 -0
- package/dist/app/charts/tooltips/useTooltipStyle.d.ts +11 -0
- package/dist/app/charts/tooltips/useTooltipStyle.d.ts.map +1 -0
- package/dist/app/charts/tooltips/useTooltipStyle.js +14 -0
- package/dist/app/charts/tooltips/useTooltipStyle.js.map +1 -0
- package/dist/app/charts/trackers/Tracker.d.ts +22 -6
- package/dist/app/charts/trackers/Tracker.d.ts.map +1 -0
- package/dist/app/charts/trackers/Tracker.js +36 -22
- package/dist/app/charts/trackers/Tracker.js.map +1 -1
- package/dist/app/charts/trackers/trackerUtils.d.ts +40 -18
- package/dist/app/charts/trackers/trackerUtils.d.ts.map +1 -0
- package/dist/app/charts/trackers/trackerUtils.js +213 -300
- package/dist/app/charts/trackers/trackerUtils.js.map +1 -1
- package/dist/app/charts/utils.d.ts +72 -33
- package/dist/app/charts/utils.d.ts.map +1 -0
- package/dist/app/charts/utils.js +87 -42
- package/dist/app/charts/utils.js.map +1 -1
- package/dist/index.d.ts +2 -45
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -72
- package/dist/index.js.map +1 -1
- package/package.json +87 -46
- package/src/app/charts/Chart.tsx +132 -168
- package/src/app/charts/axes/AxesState.ts +27 -29
- package/src/app/charts/axes/AxisInterval.ts +57 -32
- package/src/app/charts/axes/BaseAxisRange.ts +47 -27
- package/src/app/charts/axes/ContinuousAxis.tsx +235 -39
- package/src/app/charts/axes/ContinuousAxisRange.ts +29 -11
- package/src/app/charts/axes/EmptyAxis.tsx +52 -17
- package/src/app/charts/axes/OrdinalAxis.tsx +54 -28
- package/src/app/charts/axes/OrdinalAxisRange.ts +96 -16
- package/src/app/charts/axes/autoScale.ts +244 -0
- package/src/app/charts/axes/axes.ts +954 -735
- package/src/app/charts/d3types.ts +42 -13
- package/src/app/charts/datasources/StreamingDataSource.ts +214 -0
- package/src/app/charts/datasources/iteratesDataSource.ts +122 -0
- package/src/app/charts/datasources/ordinalDataSource.ts +205 -0
- package/src/app/charts/datasources/outlierDataSource.ts +90 -0
- package/src/app/charts/datasources/timeSeriesDataSource.ts +133 -0
- package/src/app/charts/filters/regexFilter.ts +45 -5
- package/src/app/charts/hooks/AxesProvider.tsx +301 -0
- package/src/app/charts/hooks/CanvasSurfaceProvider.tsx +117 -0
- package/src/app/charts/hooks/ChartProvider.tsx +79 -0
- package/src/app/charts/hooks/InteractionProvider.tsx +88 -0
- package/src/app/charts/hooks/PlotDimensionsProvider.tsx +109 -0
- package/src/app/charts/hooks/defaultAxesValues.ts +40 -0
- package/src/app/charts/hooks/defaultMouseValues.ts +24 -0
- package/src/app/charts/hooks/defaultPlotDimensions.ts +27 -0
- package/src/app/charts/hooks/defaultTooltipValues.tsx +23 -0
- package/src/app/charts/hooks/defaultUseChartValues.tsx +36 -0
- package/src/app/charts/hooks/useAxes.tsx +60 -228
- package/src/app/charts/hooks/useCanvasSurface.tsx +35 -0
- package/src/app/charts/hooks/useChart.tsx +47 -106
- package/src/app/charts/hooks/useDataSource.tsx +106 -0
- package/src/app/charts/hooks/useHoveredSeries.tsx +33 -0
- package/src/app/charts/hooks/useMouse.tsx +58 -82
- package/src/app/charts/hooks/usePlotDimensions.tsx +25 -89
- package/src/app/charts/hooks/useTooltip.tsx +32 -63
- package/src/app/charts/index.ts +213 -0
- package/src/app/charts/legends/Legend.tsx +198 -479
- package/src/app/charts/legends/constants.ts +37 -0
- package/src/app/charts/observables/iterates.ts +32 -12
- package/src/app/charts/observables/ordinals.ts +141 -67
- package/src/app/charts/observables/outliers.ts +20 -0
- package/src/app/charts/plots/BarPlot.tsx +784 -666
- package/src/app/charts/plots/OutlierPlot.tsx +685 -0
- package/src/app/charts/plots/PoincarePlot.tsx +707 -489
- package/src/app/charts/plots/RasterPlot.tsx +253 -445
- package/src/app/charts/plots/ScatterPlot.tsx +480 -463
- package/src/app/charts/plots/autoScaleYAxes.ts +102 -0
- package/src/app/charts/plots/colorizedLine.ts +185 -0
- package/src/app/charts/plots/constants.ts +16 -0
- package/src/app/charts/plots/hitTesting.ts +198 -0
- package/src/app/charts/plots/plot.ts +138 -44
- package/src/app/charts/plots/useCanvasZoomPan.ts +240 -0
- package/src/app/charts/plots/useStreamingTimeAxes.ts +384 -0
- package/src/app/charts/series/baseSeries.ts +81 -14
- package/src/app/charts/series/iterateSeries.ts +8 -8
- package/src/app/charts/series/ordinalSeries.ts +35 -20
- package/src/app/charts/series/outlierSeries.ts +188 -0
- package/src/app/charts/series/timeSeries.ts +14 -12
- package/src/app/charts/series/timeSeriesChartData.ts +31 -17
- package/src/app/charts/styling/barPlotStyle.ts +48 -5
- package/src/app/charts/styling/canvasStyle.ts +86 -0
- package/src/app/charts/styling/margins.ts +28 -4
- package/src/app/charts/styling/svgStyle.ts +10 -91
- package/src/app/charts/subscriptions/viewDrivers.ts +447 -0
- package/src/app/charts/tooltips/BarPlotTooltipContent.tsx +156 -380
- package/src/app/charts/tooltips/DefaultOutlierTooltipContent.tsx +40 -0
- package/src/app/charts/tooltips/OutlierPlotTooltipContent.tsx +67 -0
- package/src/app/charts/tooltips/PoincarePlotTooltipContent.tsx +229 -292
- package/src/app/charts/tooltips/RasterPlotTooltipContent.tsx +164 -217
- package/src/app/charts/tooltips/ScatterPlotTooltipContent.tsx +373 -236
- package/src/app/charts/tooltips/Tooltip.tsx +58 -124
- package/src/app/charts/tooltips/TooltipContent.tsx +177 -0
- package/src/app/charts/tooltips/tooltipUtils.ts +359 -61
- package/src/app/charts/tooltips/useOutlierTooltip.tsx +68 -0
- package/src/app/charts/tooltips/useTooltipPlacement.ts +86 -0
- package/src/app/charts/tooltips/useTooltipStyle.ts +15 -0
- package/src/app/charts/trackers/Tracker.tsx +68 -33
- package/src/app/charts/trackers/trackerUtils.ts +263 -376
- package/src/app/charts/utils.ts +90 -48
- package/src/index.ts +2 -322
- package/dist/app/charts/axes/AxesState.test.d.ts +0 -1
- package/dist/app/charts/axes/AxesState.test.js +0 -30
- package/dist/app/charts/axes/AxesState.test.js.map +0 -1
- package/dist/app/charts/axes/AxisInterval.test.d.ts +0 -1
- package/dist/app/charts/axes/AxisInterval.test.js +0 -120
- package/dist/app/charts/axes/AxisInterval.test.js.map +0 -1
- package/dist/app/charts/axes/ContinuousAxisRange.test.d.ts +0 -1
- package/dist/app/charts/axes/ContinuousAxisRange.test.js +0 -47
- package/dist/app/charts/axes/ContinuousAxisRange.test.js.map +0 -1
- package/dist/app/charts/axes/OrdinalAxisRange.test.d.ts +0 -1
- package/dist/app/charts/axes/OrdinalAxisRange.test.js +0 -48
- package/dist/app/charts/axes/OrdinalAxisRange.test.js.map +0 -1
- package/dist/app/charts/filters/regexFilter.test.d.ts +0 -1
- package/dist/app/charts/filters/regexFilter.test.js +0 -11
- package/dist/app/charts/filters/regexFilter.test.js.map +0 -1
- package/dist/app/charts/hooks/useDataObservable.d.ts +0 -72
- package/dist/app/charts/hooks/useDataObservable.js +0 -74
- package/dist/app/charts/hooks/useDataObservable.js.map +0 -1
- package/dist/app/charts/hooks/useInitialData.d.ts +0 -36
- package/dist/app/charts/hooks/useInitialData.js +0 -28
- package/dist/app/charts/hooks/useInitialData.js.map +0 -1
- package/dist/app/charts/observables/iterates.test.d.ts +0 -1
- package/dist/app/charts/observables/iterates.test.js +0 -180
- package/dist/app/charts/observables/iterates.test.js.map +0 -1
- package/dist/app/charts/observables/ordinals.test.d.ts +0 -1
- package/dist/app/charts/observables/ordinals.test.js +0 -102
- package/dist/app/charts/observables/ordinals.test.js.map +0 -1
- package/dist/app/charts/series/datumSeries.test.d.ts +0 -1
- package/dist/app/charts/series/datumSeries.test.js +0 -50
- package/dist/app/charts/series/datumSeries.test.js.map +0 -1
- package/dist/app/charts/styling/margins.test.d.ts +0 -1
- package/dist/app/charts/styling/margins.test.js +0 -19
- package/dist/app/charts/styling/margins.test.js.map +0 -1
- package/dist/app/charts/subscriptions/subscription.test.d.ts +0 -1
- package/dist/app/charts/subscriptions/subscription.test.js +0 -395
- package/dist/app/charts/subscriptions/subscription.test.js.map +0 -1
- package/dist/app/charts/subscriptions/subscriptions.d.ts +0 -100
- package/dist/app/charts/subscriptions/subscriptions.js +0 -449
- package/dist/app/charts/subscriptions/subscriptions.js.map +0 -1
- package/src/app/charts/axes/AxesState.test.ts +0 -34
- package/src/app/charts/axes/AxisInterval.test.ts +0 -143
- package/src/app/charts/axes/ContinuousAxisRange.test.ts +0 -55
- package/src/app/charts/axes/OrdinalAxisRange.test.ts +0 -55
- package/src/app/charts/filters/regexFilter.test.ts +0 -13
- package/src/app/charts/hooks/useDataObservable.tsx +0 -170
- package/src/app/charts/hooks/useInitialData.tsx +0 -64
- package/src/app/charts/observables/iterates.test.ts +0 -201
- package/src/app/charts/observables/ordinals.test.ts +0 -135
- package/src/app/charts/series/datumSeries.test.ts +0 -60
- package/src/app/charts/styling/margins.test.ts +0 -22
- package/src/app/charts/subscriptions/subscription.test.ts +0 -499
- package/src/app/charts/subscriptions/subscriptions.ts +0 -635
|
@@ -1,57 +1,61 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { clipToArea } from "./plot";
|
|
2
|
+
import { useCanvasZoomPan } from "./useCanvasZoomPan";
|
|
2
3
|
import * as d3 from "d3";
|
|
3
4
|
import { noop } from "../utils";
|
|
4
5
|
import { useChart } from "../hooks/useChart";
|
|
5
|
-
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { useCallback, useEffect, useEffectEvent, useMemo, useRef } from "react";
|
|
7
|
+
import { seriesAt, canvasLocalPoint } from "./hitTesting";
|
|
8
|
+
import { axesForSeriesGen, AxisType, checkAxisType, ordinalAxisIntervals, ordinalAxisRanges, ordinalAxisZoomHandler, ordinalPanHandler } from "../axes/axes";
|
|
9
|
+
import { ordinalViewDriverFor } from "../subscriptions/viewDrivers";
|
|
10
|
+
import { useDataSource, useDataSourceRunning, useInitialData, useStreamingSettings } from "../hooks/useDataSource";
|
|
11
|
+
import { initialOrdinalStats } from "../datasources/ordinalDataSource";
|
|
9
12
|
import { usePlotDimensions } from "../hooks/usePlotDimensions";
|
|
10
|
-
import {
|
|
11
|
-
import { copyValueStatsForSeries } from "../observables/ordinals";
|
|
12
|
-
import { calculateOrdinalStats } from "../series/ordinalSeries";
|
|
13
|
-
import { applyFillStylesTo, applyStrokeStylesTo, STROKE_COLOR, STROKE_OPACITY, STROKE_WIDTH } from "../styling/svgStyle";
|
|
13
|
+
import { applyFillStyle, applyStrokeStyle } from "../styling/canvasStyle";
|
|
14
14
|
import { defaultBarSeriesStyle } from "../styling/barPlotStyle";
|
|
15
|
-
import { AxisInterval } from "../axes/AxisInterval";
|
|
16
15
|
import { Optional } from "result-fn";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
minMax: TOOLTIP_PROVIDER_ID + '-min-max',
|
|
33
|
-
windowedMeanValue: TOOLTIP_PROVIDER_ID + '-windowed-min-max',
|
|
34
|
-
windowedMinMax: TOOLTIP_PROVIDER_ID + '-windowed-mean'
|
|
16
|
+
import { BAR_CHART_TOOLTIP_PROVIDER_IDS } from "./constants";
|
|
17
|
+
import { AxisInterval } from "../axes/AxisInterval";
|
|
18
|
+
import { extentOf, extentWith } from "../axes/autoScale";
|
|
19
|
+
import { growAutoScaledYAxes, useAutoScaleRestart } from "./autoScaleYAxes";
|
|
20
|
+
/**
|
|
21
|
+
* Maps the short element-type keys used internally for hit-testing geometry (`minMax`,
|
|
22
|
+
* `windowedMinMax`, `meanValue`, `windowedMeanValue`, `currentValue`) to the actual provider IDs
|
|
23
|
+
* (`BAR_CHART_TOOLTIP_PROVIDER_IDS`) that `mouseOverHandlerFor`/`mouseLeaveHandlerFor` expect.
|
|
24
|
+
*/
|
|
25
|
+
const PROVIDER_ID_FOR_ELEMENT_TYPE = {
|
|
26
|
+
minMax: BAR_CHART_TOOLTIP_PROVIDER_IDS.minMax,
|
|
27
|
+
windowedMinMax: BAR_CHART_TOOLTIP_PROVIDER_IDS.windowedMinMax,
|
|
28
|
+
meanValue: BAR_CHART_TOOLTIP_PROVIDER_IDS.meanValue,
|
|
29
|
+
windowedMeanValue: BAR_CHART_TOOLTIP_PROVIDER_IDS.windowedMeanValue,
|
|
30
|
+
currentValue: BAR_CHART_TOOLTIP_PROVIDER_IDS.currentValue,
|
|
35
31
|
};
|
|
36
32
|
/**
|
|
37
|
-
* Renders a streaming bar plot for the series
|
|
38
|
-
*
|
|
33
|
+
* Renders a streaming bar plot for the series held by the {@link StreamingDataSource} handed to the
|
|
34
|
+
* {@link Chart} (its `dataSource` prop) -- along with each series' lifetime and windowed stats,
|
|
35
|
+
* which an {@link OrdinalDataSource} keeps. This component uses the {@link useChart}
|
|
39
36
|
* hook, and therefore must be a child of the {@link Chart} to be plugged in to the
|
|
40
37
|
* chart ecosystem (axes, tracker, tooltip).
|
|
41
38
|
*
|
|
39
|
+
* Internally, this no longer creates/updates SVG `<rect>`/`<line>` elements. Instead, it registers
|
|
40
|
+
* a single draw function with the chart's {@link CanvasContext} that redraws every series' bars
|
|
41
|
+
* and lines from scratch each time the canvas repaints. Mouse hover (for the tooltip and the
|
|
42
|
+
* value-line/windowed-mean-line highlight) is handled by hit-testing the mouse position against
|
|
43
|
+
* the last-drawn geometry, keyed per `${seriesName}::${elementType}` so the five overlaid visual
|
|
44
|
+
* elements (min-max bar, windowed min-max bar, mean line, windowed mean line, value line) can be
|
|
45
|
+
* hit-tested and highlighted independently, matching the old per-element SVG mouseover behavior.
|
|
46
|
+
*
|
|
42
47
|
* For a relatively complete example of how to use this plot component, see the
|
|
43
48
|
* <a href="https://github.com/robphilipp/stream-charts-examples">`StreamingBarChart` example</a>
|
|
44
49
|
*
|
|
45
50
|
* @param props The properties associated with the bar plot
|
|
51
|
+
* @return `null` (the plot draws onto the chart's canvas)
|
|
46
52
|
* @example
|
|
47
53
|
* ```typescript
|
|
48
54
|
* <BarPlot
|
|
49
55
|
* barMargin={1}
|
|
50
|
-
* dropDataAfter={5000}
|
|
51
56
|
* panEnabled={true}
|
|
52
57
|
* zoomEnabled={true}
|
|
53
58
|
* zoomKeyModifiersRequired={true}
|
|
54
|
-
* withCadenceOf={50}
|
|
55
59
|
*
|
|
56
60
|
* showMinMaxBars={true}
|
|
57
61
|
* showValueLines={true}
|
|
@@ -62,135 +66,89 @@ export const BAR_CHART_TOOLTIP_PROVIDER_IDS = {
|
|
|
62
66
|
* ```
|
|
63
67
|
*/
|
|
64
68
|
export function BarPlot(props) {
|
|
65
|
-
|
|
66
|
-
const {
|
|
69
|
+
var _a;
|
|
70
|
+
const { chartId, canvasContext, axes, seriesStyles, seriesFilter, mouse } = useChart();
|
|
71
|
+
const { xAxesState, yAxesState, setAxisAssignments, setAxisIntervalFor, setOriginalAxisIntervalFor, axesRanges, axisRangeFor, updateAxisRanges, } = axes;
|
|
67
72
|
const { mouseOverHandlerFor, mouseLeaveHandlerFor } = mouse;
|
|
68
73
|
const { plotDimensions, margin } = usePlotDimensions();
|
|
69
|
-
const {
|
|
74
|
+
const { windowingTime = 100, onUpdateChartTime = noop } = useStreamingSettings();
|
|
75
|
+
// the application-owned source of the data, and whether it's running (streaming)
|
|
76
|
+
const dataSource = useDataSource();
|
|
77
|
+
const running = useDataSourceRunning(dataSource);
|
|
70
78
|
const { initialData } = useInitialData();
|
|
71
|
-
const { axisAssignments = new Map(),
|
|
79
|
+
const { axisAssignments = new Map(), panEnabled = false, zoomEnabled = false, zoomKeyModifiersRequired = true, showMinMaxBars = true, showWindowedMinMaxBars = true, showValueLines = true, showMeanValueLines = true, showWindowedMeanValueLines = true, barMargin = 2, barSeriesStyle = defaultBarSeriesStyle(), highlightAxesOnMouseOver = false, zoomState = undefined, onZoomStateChange = noop, onZoomReset = noop, } = props;
|
|
72
80
|
// why do "dataRef" and "seriesRef" both hold on to the same underlying data? for performance.
|
|
73
81
|
//
|
|
74
82
|
// the "dataRef" and "seriesRef" both point to the same underlying data, a collection
|
|
75
|
-
// of series
|
|
76
|
-
// are the
|
|
83
|
+
// of series (held, and updated as new data is streamed in, by the data source). The series in
|
|
84
|
+
// "dataRef" are read by the canvas draw function, and the "seriesRef" map is for looking a
|
|
85
|
+
// series up by its name.
|
|
77
86
|
//
|
|
78
87
|
// the "dataRef" object holds on to a copy of the initial data (which is an array of
|
|
79
88
|
// time-series, e.i. an array of BaseSeries<OrdinalDatum> objects). The slice just creates a copy of
|
|
80
89
|
// the array, but the references to the BaseSeries objects are the same and still point to the same
|
|
81
90
|
// data as the "initialData" array.
|
|
82
91
|
//
|
|
83
|
-
// the "seriesRef" object is a reference to a map (series_name -> BaseSeries<OrdinalDatum>)
|
|
84
|
-
//
|
|
92
|
+
// the "seriesRef" object is a reference to a map (series_name -> BaseSeries<OrdinalDatum>), used
|
|
93
|
+
// to find the series under the mouse (for the tooltip).
|
|
85
94
|
//
|
|
86
|
-
// the series in the "dataRef" object are the ones
|
|
87
|
-
//
|
|
95
|
+
// the series in the "dataRef" object are the ones read by the next redraw, so as these are
|
|
96
|
+
// updated, the next canvas repaint picks up the new data.
|
|
88
97
|
const dataRef = useRef(initialData.slice());
|
|
89
98
|
const seriesRef = useRef(new Map(initialData.map(series => [series.name, series])));
|
|
90
|
-
|
|
99
|
+
// the lifetime and windowed stats for each series -- kept by the data source (when it's an
|
|
100
|
+
// ordinal data source), so they keep accumulating while this plot is unmounted
|
|
101
|
+
const statsRef = useRef(statsFrom(dataSource, initialData));
|
|
91
102
|
// map(axis_id -> current_time) -- maps the axis ID to the current time for that axis
|
|
92
103
|
const currentTimeRef = useRef(0);
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const axesForSeries = useMemo(() => axesForSeriesGen(initialData, axisAssignments, xAxesState), [initialData, axisAssignments, xAxesState]);
|
|
105
|
-
// updates the timing using the onUpdateTime and updatePlot references. This and the references
|
|
106
|
-
// defined above allow the axes' times to be updated properly by avoid stale reference to these
|
|
107
|
-
// functions.
|
|
108
|
-
const updateTimingAndPlot = useCallback((ranges) => {
|
|
109
|
-
if (mainG !== null) {
|
|
110
|
-
updatePlotRef.current(ranges, mainG);
|
|
111
|
-
onUpdateChartTime(currentTimeRef.current);
|
|
112
|
-
updatePlotRef.current(ranges, mainG);
|
|
113
|
-
}
|
|
114
|
-
}, [mainG, onUpdateChartTime]);
|
|
115
|
-
// todo find better way
|
|
116
|
-
// when the initial data changes, then reset the plot. note that the initial data doesn't change
|
|
117
|
-
// during the normal course of updates from the observable, only when the plot is restarted.
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
dataRef.current = initialData.slice();
|
|
120
|
-
seriesRef.current = new Map(initialData.map(series => [series.name, series]));
|
|
121
|
-
currentTimeRef.current = 0;
|
|
122
|
-
statsRef.current = initialOrdinalStats(dataRef.current);
|
|
123
|
-
},
|
|
124
|
-
// ** not happy about this **
|
|
125
|
-
// only want this effect to run when the initial data is changed, which mean all the
|
|
126
|
-
// other dependencies are recalculated anyway.
|
|
127
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
128
|
-
[initialData]);
|
|
129
|
-
/**
|
|
130
|
-
* Adjusts the time-range and updates the plot when the plot is dragged to the left or right
|
|
131
|
-
* @param deltaX The amount that the plot is dragged
|
|
132
|
-
* @param plotDimensions The dimensions of the plot
|
|
133
|
-
* @param series An array of series names
|
|
134
|
-
* @param ranges A map holding the axis ID and its associated time range
|
|
135
|
-
*/
|
|
136
|
-
const onPan = useCallback((x, plotDimensions, series, ranges) => ordinalPanHandler(axesForSeries, margin, setAxisIntervalFor, xAxesState)(x, plotDimensions, series, ranges), [axesForSeries, margin, setAxisIntervalFor, xAxesState]);
|
|
137
|
-
/**
|
|
138
|
-
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out. Zooms in/out
|
|
139
|
-
* at the location of the mouse when the scroll wheel or gesture was applied.
|
|
140
|
-
* @param transform The d3 zoom transformation information
|
|
141
|
-
* @param x The x-position of the mouse when the scroll wheel or gesture is used
|
|
142
|
-
* @param plotDimensions The dimensions of the plot
|
|
143
|
-
* @param series An array of series names
|
|
144
|
-
* @param ranges A map holding the axis ID and its associated time-range
|
|
145
|
-
*/
|
|
146
|
-
const onZoom = useCallback((transform, x, plotDimensions, ranges) => ordinalAxisZoomHandler(axesForSeries, margin, setAxisIntervalFor, setOriginalAxisIntervalFor, xAxesState)(transform, x, plotDimensions, ranges), [axesForSeries, margin, setAxisIntervalFor, setOriginalAxisIntervalFor, xAxesState]);
|
|
104
|
+
// tooltips are only shown while the data source is paused (and not while panning)
|
|
105
|
+
const allowTooltipRef = useRef(!((_a = dataSource === null || dataSource === void 0 ? void 0 : dataSource.running) !== null && _a !== void 0 ? _a : false));
|
|
106
|
+
// the last-drawn geometry for each `${seriesName}::${elementType}`, in canvas coordinates,
|
|
107
|
+
// used for hit-testing mouse hover on `mousemove` (see the effect below that wires up the
|
|
108
|
+
// listener)
|
|
109
|
+
const geometryRef = useRef(new Map());
|
|
110
|
+
// which specific element (series + type) the mouse was over on the previous `mousemove`, so
|
|
111
|
+
// we know when to fire a "leave" before firing an "over" for a different element -- unlike
|
|
112
|
+
// Scatter/Raster, BarPlot doesn't use the shared `hoveredSeriesName` chart state, since here
|
|
113
|
+
// hover is scoped to one of five element *types* per series, not the series as a whole
|
|
114
|
+
const lastHoveredRef = useRef(undefined);
|
|
147
115
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
116
|
+
* (Re-)registers this plot's draw function with the canvas context and requests a redraw.
|
|
117
|
+
* Replaces the old version, which directly mutated SVG `<rect>`/`<line>` elements bound via
|
|
118
|
+
* d3's enter/update/exit join. Canvas has no persistent elements to join against, so the draw
|
|
119
|
+
* function just redraws every element from current data/scale state each time it's invoked.
|
|
120
|
+
*
|
|
121
|
+
* Pan/zoom behavior setup lives in a separate effect (see below), not here -- this function
|
|
122
|
+
* runs on every data tick (each `windowingTime` interval), and recreating/reattaching a
|
|
123
|
+
* `d3.drag()`/`d3.zoom()` behavior that often is pure overhead unrelated to drawing the new
|
|
124
|
+
* data.
|
|
125
|
+
* @param cc The canvas context to register the draw function with
|
|
150
126
|
*/
|
|
151
|
-
const updatePlot = useCallback((
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
d3.select(container).style("cursor", "move");
|
|
160
|
-
allowTooltipRef.current = false;
|
|
161
|
-
})
|
|
162
|
-
.on("drag", (event) => {
|
|
163
|
-
const names = dataRef.current.map(series => series.name);
|
|
164
|
-
onPan(event.dx, plotDimensions, names, ordinalRanges);
|
|
165
|
-
// need to update the plot with the new time-ranges
|
|
166
|
-
updatePlotRef.current(ordinalRanges, mainGElem);
|
|
167
|
-
})
|
|
168
|
-
.on("end", () => {
|
|
169
|
-
d3.select(container).style("cursor", "auto");
|
|
170
|
-
allowTooltipRef.current = isSubscriptionClosed();
|
|
171
|
-
});
|
|
172
|
-
svg.call(drag);
|
|
173
|
-
}
|
|
174
|
-
// set up for zooming
|
|
175
|
-
if (zoomEnabled) {
|
|
176
|
-
const zoom = d3.zoom()
|
|
177
|
-
.filter((event) => !zoomKeyModifiersRequired || event.shiftKey || event.ctrlKey)
|
|
178
|
-
.scaleExtent([1, 10])
|
|
179
|
-
.translateExtent([[margin.left, margin.top], [plotDimensions.width, plotDimensions.height]])
|
|
180
|
-
.on("zoom", (event) => {
|
|
181
|
-
onZoom(event.transform, event.sourceEvent.offsetX - margin.left, plotDimensions, ordinalRanges);
|
|
182
|
-
updatePlotRef.current(ordinalRanges, mainGElem);
|
|
183
|
-
});
|
|
184
|
-
svg.call(zoom);
|
|
185
|
-
}
|
|
127
|
+
const updatePlot = useCallback((cc) => {
|
|
128
|
+
const draw = (context) => {
|
|
129
|
+
const { context2D } = context;
|
|
130
|
+
context2D.save();
|
|
131
|
+
clipToArea(context, plotDimensions, { x: margin.left, y: margin.top });
|
|
132
|
+
context2D.translate(margin.left, margin.top);
|
|
133
|
+
const newGeometry = new Map();
|
|
134
|
+
const hovered = lastHoveredRef.current;
|
|
186
135
|
// enter, update, delete the bar data
|
|
187
136
|
dataRef.current.forEach(series => {
|
|
188
|
-
var _a, _b, _c;
|
|
137
|
+
var _a, _b, _c, _d, _e, _f;
|
|
189
138
|
const [xAxis, yAxis] = axesFor(series.name, axisAssignments, axisId => xAxesState.axisFor(axisId).getOrUndefined(), axisId => yAxesState.axisFor(axisId).getOrUndefined());
|
|
139
|
+
if (xAxis === undefined || yAxis === undefined)
|
|
140
|
+
return;
|
|
190
141
|
// grab the series styles, or the defaults if none exist
|
|
191
|
-
const { margin: categoryMargin = barMargin, valueLine: valueLineStyle, meanValueLine: meanValueLineStyle, windowedMeanValueLine: windowedMeanLineStyle, minMaxBar: minMaxBarStyle, windowedMinMaxBar: windowedBarStyle } = seriesStyles.get(series.name) ||
|
|
142
|
+
const { margin: categoryMargin = barMargin, valueLine: valueLineStyle, meanValueLine: meanValueLineStyle, windowedMeanValueLine: windowedMeanLineStyle, minMaxBar: minMaxBarStyle, windowedMinMaxBar: windowedBarStyle } = seriesStyles.get(series.name) || {
|
|
143
|
+
...barSeriesStyle,
|
|
144
|
+
highlightColor: barSeriesStyle.color
|
|
145
|
+
};
|
|
192
146
|
// only show the data for which the regex filter matches
|
|
193
|
-
const plotData = series.name.match(seriesFilter)
|
|
147
|
+
const plotData = series.name.match(seriesFilter) && series.data.length > 0 ?
|
|
148
|
+
[series.data[series.data.length - 1]] :
|
|
149
|
+
[];
|
|
150
|
+
if (plotData.length === 0)
|
|
151
|
+
return;
|
|
194
152
|
// grab the functions for determining the lower and upper bounds of the category
|
|
195
153
|
const { lower, upper } = xAxisCategoryBoundsFn(xAxis.scale.bandwidth(), valueLineStyle.regular.width, categoryMargin);
|
|
196
154
|
// grab the value (index) associated with the series name (this is a category axis)
|
|
@@ -198,141 +156,330 @@ export function BarPlot(props) {
|
|
|
198
156
|
//
|
|
199
157
|
// min/max bar rectangle
|
|
200
158
|
const totalBar = barDimensions(minMaxBarStyle.widthFraction, lower(x), upper(x), ((_a = statsRef.current.valueStatsForSeries.get(series.name)) === null || _a === void 0 ? void 0 : _a.min.value) || 0, ((_b = statsRef.current.valueStatsForSeries.get(series.name)) === null || _b === void 0 ? void 0 : _b.max.value) || 0, yAxis);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
159
|
+
drawBar(context2D, totalBar, barStyleFor(showMinMaxBars, minMaxBarStyle));
|
|
160
|
+
newGeometry.set(`${series.name}::minMax`, {
|
|
161
|
+
points: [],
|
|
162
|
+
rects: [{
|
|
163
|
+
x: totalBar.upperX + margin.left,
|
|
164
|
+
y: totalBar.upperY + margin.top,
|
|
165
|
+
width: totalBar.width,
|
|
166
|
+
height: totalBar.height
|
|
167
|
+
}],
|
|
168
|
+
hitRadius: 0
|
|
169
|
+
});
|
|
208
170
|
//
|
|
209
|
-
// windowed-mean line when the windowed stats are defined for the series
|
|
171
|
+
// windowed-mean line and windowed min/max bar, when the windowed stats are defined for the series
|
|
210
172
|
const seriesWindowedStats = statsRef.current.windowedValueStatsForSeries.get(series.name);
|
|
211
173
|
if (seriesWindowedStats !== undefined) {
|
|
212
174
|
const windowedBar = barDimensions(windowedBarStyle.widthFraction, lower(x), upper(x), seriesWindowedStats.min.value, seriesWindowedStats.max.value, yAxis);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
175
|
+
drawBar(context2D, windowedBar, barStyleFor(showWindowedMinMaxBars, windowedBarStyle));
|
|
176
|
+
newGeometry.set(`${series.name}::windowedMinMax`, {
|
|
177
|
+
points: [],
|
|
178
|
+
rects: [{
|
|
179
|
+
x: windowedBar.upperX + margin.left,
|
|
180
|
+
y: windowedBar.upperY + margin.top,
|
|
181
|
+
width: windowedBar.width,
|
|
182
|
+
height: windowedBar.height
|
|
183
|
+
}],
|
|
184
|
+
hitRadius: 0
|
|
185
|
+
});
|
|
220
186
|
//
|
|
221
187
|
// mean line
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
.
|
|
239
|
-
.
|
|
240
|
-
|
|
241
|
-
.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
188
|
+
if (showMeanValueLines) {
|
|
189
|
+
const meanLineY = yAxis.scale(((_c = statsRef.current.valueStatsForSeries.get(series.name)) === null || _c === void 0 ? void 0 : _c.mean) || 0);
|
|
190
|
+
drawLine(context2D, lower(x), meanLineY, upper(x), meanLineY, meanValueLineStyle.regular);
|
|
191
|
+
newGeometry.set(`${series.name}::meanValue`, {
|
|
192
|
+
points: [],
|
|
193
|
+
segments: [[
|
|
194
|
+
[lower(x) + margin.left, meanLineY + margin.top],
|
|
195
|
+
[upper(x) + margin.left, meanLineY + margin.top]
|
|
196
|
+
]],
|
|
197
|
+
hitRadius: Math.max(4, (_d = meanValueLineStyle.regular.width) !== null && _d !== void 0 ? _d : 1)
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
//
|
|
201
|
+
// windowed-mean line
|
|
202
|
+
if (showWindowedMeanValueLines) {
|
|
203
|
+
const windowedMeanLineY = yAxis.scale(isNaN(seriesWindowedStats.mean) ? 0 : seriesWindowedStats.mean);
|
|
204
|
+
const isHovered = (hovered === null || hovered === void 0 ? void 0 : hovered.seriesName) === series.name && hovered.elementType === 'windowedMeanValue';
|
|
205
|
+
const style = isHovered ? windowedMeanLineStyle.highlight : windowedMeanLineStyle.regular;
|
|
206
|
+
drawLine(context2D, lower(x), windowedMeanLineY, upper(x), windowedMeanLineY, style);
|
|
207
|
+
newGeometry.set(`${series.name}::windowedMeanValue`, {
|
|
208
|
+
points: [],
|
|
209
|
+
segments: [[
|
|
210
|
+
[lower(x) + margin.left, windowedMeanLineY + margin.top],
|
|
211
|
+
[upper(x) + margin.left, windowedMeanLineY + margin.top]
|
|
212
|
+
]],
|
|
213
|
+
hitRadius: Math.max(4, (_e = style.width) !== null && _e !== void 0 ? _e : 1)
|
|
214
|
+
});
|
|
215
|
+
}
|
|
250
216
|
}
|
|
251
217
|
//
|
|
252
|
-
// value
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
.
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
218
|
+
// value line
|
|
219
|
+
if (showValueLines) {
|
|
220
|
+
const datum = plotData[0];
|
|
221
|
+
const valueLineY = yAxis.scale(datum.value);
|
|
222
|
+
const isHovered = (hovered === null || hovered === void 0 ? void 0 : hovered.seriesName) === series.name && hovered.elementType === 'currentValue';
|
|
223
|
+
const style = isHovered ? valueLineStyle.highlight : valueLineStyle.regular;
|
|
224
|
+
drawLine(context2D, lower(x), valueLineY, upper(x), valueLineY, style);
|
|
225
|
+
newGeometry.set(`${series.name}::currentValue`, {
|
|
226
|
+
points: [],
|
|
227
|
+
segments: [[
|
|
228
|
+
[lower(x) + margin.left, valueLineY + margin.top],
|
|
229
|
+
[upper(x) + margin.left, valueLineY + margin.top]
|
|
230
|
+
]],
|
|
231
|
+
hitRadius: Math.max(4, (_f = style.width) !== null && _f !== void 0 ? _f : 1)
|
|
232
|
+
});
|
|
233
|
+
}
|
|
266
234
|
});
|
|
267
|
-
|
|
235
|
+
geometryRef.current = newGeometry;
|
|
236
|
+
context2D.restore();
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Grows the auto-scaling y-axes (see `ContinuousAxis`'s `autoScale` prop) to fit what's
|
|
240
|
+
* shown of the series whose categories are on screen (within the x-axis' current,
|
|
241
|
+
* possibly zoomed, window): the min/max bars, the windowed min/max bars, the mean and
|
|
242
|
+
* windowed-mean lines, and the value lines -- each only when it's shown. Registered to
|
|
243
|
+
* run before the axes draw (they're at z-index 0), so the axes and the bars are drawn
|
|
244
|
+
* with the grown domain in the same frame.
|
|
245
|
+
*/
|
|
246
|
+
const autoScaleYAxes = () => {
|
|
247
|
+
const extents = new Map();
|
|
248
|
+
dataRef.current.forEach(series => {
|
|
249
|
+
if (!series.name.match(seriesFilter) || series.data.length === 0)
|
|
250
|
+
return;
|
|
251
|
+
const [xAxis, yAxis] = axesFor(series.name, axisAssignments, axisId => xAxesState.axisFor(axisId).getOrUndefined(), axisId => yAxesState.axisFor(axisId).getOrUndefined());
|
|
252
|
+
if (xAxis === undefined || (yAxis === null || yAxis === void 0 ? void 0 : yAxis.autoScale) === undefined)
|
|
253
|
+
return;
|
|
254
|
+
// only the categories (at least partly) on screen
|
|
255
|
+
const x = xAxis.scale(series.name);
|
|
256
|
+
if (x === undefined || x + xAxis.scale.bandwidth() <= 0 || x >= plotDimensions.width)
|
|
257
|
+
return;
|
|
258
|
+
// what's shown of the series (mirrors the draw function above)
|
|
259
|
+
const values = [];
|
|
260
|
+
const stats = statsRef.current.valueStatsForSeries.get(series.name);
|
|
261
|
+
if (showMinMaxBars && stats !== undefined)
|
|
262
|
+
values.push(stats.min.value, stats.max.value);
|
|
263
|
+
const windowedStats = statsRef.current.windowedValueStatsForSeries.get(series.name);
|
|
264
|
+
if (windowedStats !== undefined) {
|
|
265
|
+
if (showWindowedMinMaxBars)
|
|
266
|
+
values.push(windowedStats.min.value, windowedStats.max.value);
|
|
267
|
+
if (showMeanValueLines && stats !== undefined)
|
|
268
|
+
values.push(stats.mean);
|
|
269
|
+
if (showWindowedMeanValueLines)
|
|
270
|
+
values.push(windowedStats.mean);
|
|
271
|
+
}
|
|
272
|
+
if (showValueLines)
|
|
273
|
+
values.push(series.data[series.data.length - 1].value);
|
|
274
|
+
const seriesExtent = extentOf(values, yAxis.scale);
|
|
275
|
+
if (seriesExtent === undefined)
|
|
276
|
+
return;
|
|
277
|
+
const extent = extents.get(yAxis.axisId);
|
|
278
|
+
extents.set(yAxis.axisId, extent === undefined ? seriesExtent : extentWith(extentWith(extent, seriesExtent[0]), seriesExtent[1]));
|
|
279
|
+
});
|
|
280
|
+
// (the y-axes are continuous axes, even though this plot's axes context is typed
|
|
281
|
+
// for its ordinal x-axes)
|
|
282
|
+
growAutoScaledYAxes(extents, {
|
|
283
|
+
yAxes: yAxesState.axes,
|
|
284
|
+
axisRangeFor,
|
|
285
|
+
updateAxisRanges: updateAxisRanges,
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
cc.register(`bar-plot-autoscale-${chartId}`, autoScaleYAxes, -10);
|
|
289
|
+
cc.register(`bar-plot-${chartId}`, draw, 10);
|
|
290
|
+
cc.requestRedraw();
|
|
268
291
|
}, [
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
axisAssignments, xAxesState, yAxesState,
|
|
274
|
-
barMargin, seriesStyles, barSeriesStyle,
|
|
275
|
-
seriesFilter,
|
|
276
|
-
chartId,
|
|
277
|
-
showValueLines,
|
|
278
|
-
showMinMaxBars,
|
|
279
|
-
mouseOverHandlerFor, mouseLeaveHandlerFor,
|
|
280
|
-
showMeanValueLines,
|
|
281
|
-
showWindowedMeanValueLines,
|
|
282
|
-
showWindowedMinMaxBars
|
|
292
|
+
chartId, plotDimensions, axisAssignments, xAxesState, yAxesState, barMargin, seriesStyles,
|
|
293
|
+
barSeriesStyle, seriesFilter, showValueLines, showMinMaxBars, showMeanValueLines,
|
|
294
|
+
showWindowedMeanValueLines, showWindowedMinMaxBars, axisRangeFor, updateAxisRanges,
|
|
295
|
+
margin.left, margin.top
|
|
283
296
|
]);
|
|
297
|
+
// new data, new scale: restarts the auto-scaling y-axes when the data source is replaced
|
|
298
|
+
useAutoScaleRestart(dataSource, {
|
|
299
|
+
yAxes: yAxesState.axes,
|
|
300
|
+
axisRangeFor,
|
|
301
|
+
updateAxisRanges: updateAxisRanges,
|
|
302
|
+
});
|
|
284
303
|
// need to keep the function references for use by the subscription, which forms a closure
|
|
285
304
|
// on them. without the references, the closures become stale, and resizing during streaming
|
|
286
305
|
// doesn't work properly
|
|
287
|
-
const updatePlotRef = useRef(
|
|
306
|
+
const updatePlotRef = useRef(updatePlot);
|
|
288
307
|
useEffect(() => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
308
|
+
updatePlotRef.current = updatePlot;
|
|
309
|
+
}, [updatePlot]);
|
|
310
|
+
useEffect(() => {
|
|
311
|
+
currentTimeRef.current = 0;
|
|
312
|
+
}, [xAxesState]);
|
|
313
|
+
// set the axis assignments needed if a tooltip is being used
|
|
314
|
+
useEffect(() => {
|
|
315
|
+
setAxisAssignments(axisAssignments);
|
|
316
|
+
}, [axisAssignments, setAxisAssignments]);
|
|
317
|
+
// calculates the distinct series IDs that cover all the series in the plot
|
|
318
|
+
const axesForSeries = useMemo(() => axesForSeriesGen(initialData, axisAssignments, xAxesState), [initialData, axisAssignments, xAxesState]);
|
|
319
|
+
// redraws the plot for newly arrived data and reports the chart time, using the updatePlot
|
|
320
|
+
// reference (to avoid a stale updatePlot). Deliberately leaves the axes' ranges
|
|
321
|
+
// (`ordinalRangesRef`) alone: the ordinal axes don't scroll as data arrives, so only this plot's
|
|
322
|
+
// own zoom, pan, and resize handling changes them -- replacing them here (as a previous version
|
|
323
|
+
// did, with the y-axes' ranges) left the x-axis zoom/pan handlers with nothing to act on until
|
|
324
|
+
// something else happened to rebuild the map.
|
|
325
|
+
const updateTimingAndPlot = useCallback(() => {
|
|
326
|
+
if (canvasContext !== null) {
|
|
327
|
+
// (one redraw request is enough: `onUpdateChartTime` only reports the time to the
|
|
328
|
+
// application, and redraw requests are coalesced into one animation frame anyway)
|
|
329
|
+
updatePlotRef.current(canvasContext);
|
|
330
|
+
onUpdateChartTime(currentTimeRef.current);
|
|
309
331
|
}
|
|
310
|
-
}, [
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
if (seriesObservable === undefined || mainG === null)
|
|
314
|
-
return undefined;
|
|
315
|
-
return subscriptionOrdinalXFor(seriesObservable, onSubscribe, windowingTime, axisAssignments, yAxesState, onUpdateData, dropDataAfter, updateTimingAndPlot,
|
|
316
|
-
// as new data flows into the subscription, the subscription
|
|
317
|
-
// updates this map directly (for performance)
|
|
318
|
-
seriesRef.current, statsRef, (currentTime) => currentTimeRef.current = currentTime, AxisInterval.from(0, plotDimensions.width));
|
|
319
|
-
}, [
|
|
320
|
-
axisAssignments, dropDataAfter, mainG,
|
|
321
|
-
onSubscribe, onUpdateData,
|
|
322
|
-
seriesObservable, updateTimingAndPlot, windowingTime, yAxesState,
|
|
323
|
-
plotDimensions.width
|
|
324
|
-
]);
|
|
332
|
+
}, [canvasContext, onUpdateChartTime]);
|
|
333
|
+
// when the initial data changes, then reset the plot. note that the initial data doesn't change
|
|
334
|
+
// during the normal course of updates from the data source, only when the data source is replaced.
|
|
325
335
|
useEffect(() => {
|
|
326
|
-
|
|
336
|
+
dataRef.current = initialData.slice();
|
|
337
|
+
seriesRef.current = new Map(initialData.map(series => [series.name, series]));
|
|
338
|
+
currentTimeRef.current = 0;
|
|
339
|
+
statsRef.current = statsFrom(dataSource, dataRef.current);
|
|
340
|
+
}, [initialData, dataSource]);
|
|
341
|
+
/**
|
|
342
|
+
* Adjusts the ordinal x-axes' ranges when the plot is dragged to the left or right (the caller
|
|
343
|
+
* redraws the plot)
|
|
344
|
+
* @param x The amount that the plot is dragged
|
|
345
|
+
* @param plotDimensions The dimensions of the plot
|
|
346
|
+
* @param series An array of series names
|
|
347
|
+
* @param ranges A map holding the axis ID and its associated range
|
|
348
|
+
*/
|
|
349
|
+
const onPan = useCallback((x, plotDimensions, series, ranges) => ordinalPanHandler(axesForSeries, margin, setAxisIntervalFor, xAxesState)(x, plotDimensions, series, ranges), [axesForSeries, margin, setAxisIntervalFor, xAxesState]);
|
|
350
|
+
/**
|
|
351
|
+
* Called when the user uses the scroll wheel (or scroll gesture) to zoom in or out. Zooms in/out
|
|
352
|
+
* at the location of the mouse when the scroll wheel or gesture was applied.
|
|
353
|
+
* @param zoomFactor The *cumulative* zoom scale factor for this event -- d3-zoom's own
|
|
354
|
+
* `event.transform.k`, passed through unmodified. See {@link OrdinalAxisRange.scaledCumulative}
|
|
355
|
+
* for why the ordinal x-axis needs this cumulative factor (from which it derives the
|
|
356
|
+
* incremental step itself, and which it snaps back to `.original` at exactly 1).
|
|
357
|
+
* @param x The x-position of the mouse when the scroll wheel or gesture is used
|
|
358
|
+
* @param plotDimensions The dimensions of the plot
|
|
359
|
+
* @param ranges A map holding the axis ID and its associated range
|
|
360
|
+
*/
|
|
361
|
+
const onZoom = useCallback((zoomFactor, x, plotDimensions, ranges) => ordinalAxisZoomHandler(axesForSeries, margin, setAxisIntervalFor, setOriginalAxisIntervalFor, xAxesState)(zoomFactor, x, plotDimensions, ranges), [axesForSeries, margin, setAxisIntervalFor, setOriginalAxisIntervalFor, xAxesState]);
|
|
362
|
+
// holds the current per-axis ordinal ranges, kept in sync by the effect below. Replaces
|
|
363
|
+
// threading `ordinalRanges` through as an explicit `updatePlot` parameter, so the pan/zoom
|
|
364
|
+
// handlers (now set up once, in a separate effect below, rather than inside `updatePlot`
|
|
365
|
+
// itself) can always read the current ranges without needing `updatePlot` to be recreated
|
|
366
|
+
// every time the ranges change.
|
|
367
|
+
const ordinalRangesRef = useRef(new Map());
|
|
368
|
+
// hands the current zoom/pan state (the ordinal x-axes' ranges, as fractions of their
|
|
369
|
+
// original extent, and d3-zoom's cumulative `k`) to the `onZoomStateChange` callback
|
|
370
|
+
const reportZoomState = useCallback((cc) => {
|
|
371
|
+
const ranges = {};
|
|
372
|
+
ordinalRangesRef.current.forEach((range, axisId) => {
|
|
373
|
+
const extent = range.original.measure();
|
|
374
|
+
if (xAxesState.axes.has(axisId) && extent > 0) {
|
|
375
|
+
ranges[axisId] = [
|
|
376
|
+
(range.current.start - range.original.start) / extent,
|
|
377
|
+
(range.current.end - range.original.start) / extent
|
|
378
|
+
];
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
onZoomStateChange({ k: d3.zoomTransform(cc.canvas).k, ranges });
|
|
382
|
+
}, [onZoomStateChange, xAxesState.axes]);
|
|
383
|
+
// panning (dragging) and zooming (the mouse wheel) -- see `useCanvasZoomPan`. The ordinal zoom
|
|
384
|
+
// takes d3-zoom's cumulative scale (`k`), rather than the incremental factor, so that it can
|
|
385
|
+
// snap back to the original range exactly when fully zoomed out (see `OrdinalAxisRange.scale`)
|
|
386
|
+
const { setZoomScale } = useCanvasZoomPan(canvasContext, {
|
|
387
|
+
panEnabled,
|
|
388
|
+
zoomEnabled,
|
|
389
|
+
keyModifiersRequired: zoomKeyModifiersRequired,
|
|
390
|
+
scaleExtent: [1, 10],
|
|
391
|
+
// (an ordinal axis zooms in as d3-zoom's scale goes up, the opposite way to the other
|
|
392
|
+
// plots' continuous axes, so the wheel is inverted to zoom the same way as they do)
|
|
393
|
+
invertWheel: true,
|
|
394
|
+
translateExtent: [[margin.left, margin.top], [plotDimensions.width, plotDimensions.height]],
|
|
395
|
+
// (tooltips are suppressed while panning, so that one isn't left behind)
|
|
396
|
+
onPanStart: () => {
|
|
397
|
+
allowTooltipRef.current = false;
|
|
398
|
+
},
|
|
399
|
+
onPan: dx => {
|
|
400
|
+
if (canvasContext === null)
|
|
401
|
+
return;
|
|
402
|
+
onPan(dx, plotDimensions, dataRef.current.map(series => series.name), ordinalRangesRef.current);
|
|
403
|
+
updatePlotRef.current(canvasContext);
|
|
404
|
+
},
|
|
405
|
+
onPanEnd: () => {
|
|
406
|
+
var _a;
|
|
407
|
+
allowTooltipRef.current = !((_a = dataSource === null || dataSource === void 0 ? void 0 : dataSource.running) !== null && _a !== void 0 ? _a : false);
|
|
408
|
+
if (canvasContext !== null)
|
|
409
|
+
reportZoomState(canvasContext);
|
|
410
|
+
},
|
|
411
|
+
onZoom: ({ k, x }) => {
|
|
412
|
+
if (canvasContext === null)
|
|
413
|
+
return;
|
|
414
|
+
onZoom(k, x - margin.left, plotDimensions, ordinalRangesRef.current);
|
|
415
|
+
updatePlotRef.current(canvasContext);
|
|
416
|
+
reportZoomState(canvasContext);
|
|
417
|
+
},
|
|
418
|
+
onZoomReset,
|
|
419
|
+
// restores each axis's range to its original
|
|
420
|
+
resetView: () => {
|
|
421
|
+
ordinalRangesRef.current.forEach((range, axisId) => {
|
|
422
|
+
xAxesState.axisFor(axisId).ifPresent(axis => {
|
|
423
|
+
ordinalRangesRef.current.set(axisId, range.update(range.original.start, range.original.end));
|
|
424
|
+
setAxisIntervalFor(axisId, range.original);
|
|
425
|
+
axis.update(axis.scale.domain(), range.original, range.original, plotDimensions, margin);
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
if (canvasContext !== null)
|
|
429
|
+
updatePlotRef.current(canvasContext);
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
// the zoom state to restore, captured once at mount (see the `zoomState` prop); cleared once
|
|
433
|
+
// it has been applied (see `restoreZoomState` below), so it's only ever applied once
|
|
434
|
+
const pendingZoomStateRef = useRef(zoomState);
|
|
435
|
+
// applies the pending zoom state (if any) to the ordinal x-axes' ranges and to d3-zoom's
|
|
436
|
+
// transform on the canvas -- a remounted plot has a brand-new canvas, whose d3-zoom transform
|
|
437
|
+
// starts at identity (k = 1). Both must be restored together: the ordinal zoom math derives
|
|
438
|
+
// its incremental step from d3's cumulative `k` relative to the range's current/original width
|
|
439
|
+
// ratio, and treats `k === 1` as "snap back to fully zoomed out" (see
|
|
440
|
+
// `OrdinalAxisRange.scaledCumulative`), so restoring the ranges without `k` would make the
|
|
441
|
+
// very next wheel tick jump. Waits (leaving the state pending) until every axis in the
|
|
442
|
+
// snapshot exists, since the axes register themselves with the chart asynchronously.
|
|
443
|
+
const restoreZoomState = useCallback(() => {
|
|
444
|
+
const pending = pendingZoomStateRef.current;
|
|
445
|
+
if (pending === undefined)
|
|
446
|
+
return;
|
|
447
|
+
const axisIds = Object.keys(pending.ranges);
|
|
448
|
+
const ready = axisIds.every(axisId => ordinalRangesRef.current.has(axisId) && xAxesState.axisFor(axisId).getOrUndefined() !== undefined);
|
|
449
|
+
if (!ready || plotDimensions.width <= 0)
|
|
450
|
+
return;
|
|
451
|
+
axisIds.forEach(axisId => {
|
|
452
|
+
const range = ordinalRangesRef.current.get(axisId);
|
|
453
|
+
const axis = xAxesState.axisFor(axisId).getOrUndefined();
|
|
454
|
+
if (range === undefined || axis === undefined)
|
|
455
|
+
return;
|
|
456
|
+
const [startFraction, endFraction] = pending.ranges[axisId];
|
|
457
|
+
const { start: originalStart } = range.original;
|
|
458
|
+
const extent = range.original.measure();
|
|
459
|
+
const current = AxisInterval.from(originalStart + startFraction * extent, originalStart + endFraction * extent);
|
|
460
|
+
ordinalRangesRef.current.set(axisId, range.update(current.start, current.end));
|
|
461
|
+
setAxisIntervalFor(axisId, current);
|
|
462
|
+
axis.update(axis.scale.domain(), current, range.original, plotDimensions, margin);
|
|
463
|
+
});
|
|
464
|
+
// (set directly, without dispatching a "zoom" event -- see `setZoomScale`)
|
|
465
|
+
setZoomScale(pending.k);
|
|
466
|
+
pendingZoomStateRef.current = undefined;
|
|
467
|
+
}, [margin, plotDimensions, setAxisIntervalFor, xAxesState, setZoomScale]);
|
|
468
|
+
useEffect(() => {
|
|
469
|
+
if (canvasContext) {
|
|
327
470
|
const ordinalAxesRanges = axesRanges();
|
|
328
471
|
// so this gets a bit complicated. the ordinal-ranges need to be updated whenever the ordinal-ranges
|
|
329
472
|
// change. for example, when the window is resized, and then we need to update the
|
|
330
473
|
// ordinal-range. however, we want to keep the ordinal-ranges to reflect their original scale so that
|
|
331
474
|
// we can zoom properly (so the updates can't fuck with the scale).
|
|
332
475
|
if (ordinalAxesRanges.size === 0) {
|
|
333
|
-
// when no time-ranges have yet been created, then create them and
|
|
334
|
-
//
|
|
335
|
-
|
|
476
|
+
// when no time-ranges have yet been created, then create them and populate the
|
|
477
|
+
// existing ref's map in place (rather than replacing it -- reassigning `.current`
|
|
478
|
+
// once it's already in play elsewhere, e.g. the zoom/pan handlers, isn't allowed
|
|
479
|
+
// by react-hooks/immutability)
|
|
480
|
+
ordinalRangesRef.current.clear();
|
|
481
|
+
ordinalAxisRanges(xAxesState.axes)
|
|
482
|
+
.forEach((range, id) => ordinalRangesRef.current.set(id, range));
|
|
336
483
|
}
|
|
337
484
|
else {
|
|
338
485
|
// when the ordinal-ranges already exist, then we want to update the ordinal-ranges for each
|
|
@@ -350,64 +497,194 @@ export function BarPlot(props) {
|
|
|
350
497
|
rangesMap.set(id, range.update(start, end));
|
|
351
498
|
});
|
|
352
499
|
});
|
|
353
|
-
|
|
500
|
+
ordinalRangesRef.current.clear();
|
|
501
|
+
ordinalAxesRanges.forEach((range, id) => ordinalRangesRef.current.set(id, range));
|
|
354
502
|
}
|
|
503
|
+
// restore a zoom state handed in from a previous instance (only does anything the
|
|
504
|
+
// first time the axes are all available -- see `restoreZoomState`)
|
|
505
|
+
restoreZoomState();
|
|
506
|
+
updatePlot(canvasContext);
|
|
355
507
|
}
|
|
356
|
-
}, [axesRanges,
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
//
|
|
360
|
-
//
|
|
508
|
+
}, [axesRanges, canvasContext, plotDimensions.width, updatePlot, xAxesState.axes, restoreZoomState]);
|
|
509
|
+
// wires up a single mousemove/mouseleave listener on the shared canvas to replace the old
|
|
510
|
+
// per-element SVG mouseover/mouseleave handlers. Hit-tests the mouse position against the
|
|
511
|
+
// last-drawn geometry (see `geometryRef`, populated by the draw function above), keyed per
|
|
512
|
+
// `${seriesName}::${elementType}` so the five overlaid elements resolve independently.
|
|
361
513
|
useEffect(() => {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
514
|
+
if (!canvasContext)
|
|
515
|
+
return;
|
|
516
|
+
const canvas = canvasContext.canvas;
|
|
517
|
+
// highlights (or un-highlights) the x- and y-axes a series is plotted against --
|
|
518
|
+
// keyed on the series name alone (not the specific hovered element type), so moving
|
|
519
|
+
// the mouse between a series' own bar/lines doesn't flicker the highlight off and on.
|
|
520
|
+
// Unlike Scatter/Outlier, bar series styles don't carry a single flat highlight
|
|
521
|
+
// color/width (they're nested per element type), so this uses the axis' own default
|
|
522
|
+
// highlight styling rather than trying to match a specific element's highlight style.
|
|
523
|
+
const highlightAxesFor = (seriesName, isHighlighted) => {
|
|
524
|
+
if (!highlightAxesOnMouseOver)
|
|
525
|
+
return;
|
|
526
|
+
const [xAxis, yAxis] = axesFor(seriesName, axisAssignments, axisId => xAxesState.axisFor(axisId).getOrUndefined(), axisId => yAxesState.axisFor(axisId).getOrUndefined());
|
|
527
|
+
xAxis === null || xAxis === void 0 ? void 0 : xAxis.setHighlighted(isHighlighted);
|
|
528
|
+
yAxis === null || yAxis === void 0 ? void 0 : yAxis.setHighlighted(isHighlighted);
|
|
529
|
+
};
|
|
530
|
+
const handleMove = (event) => {
|
|
531
|
+
const [x, y] = canvasLocalPoint(event, canvas);
|
|
532
|
+
const hit = seriesAt(x, y, geometryRef.current);
|
|
533
|
+
// geometry keys are "${seriesName}::${elementType}"; split back apart
|
|
534
|
+
const [hitSeriesName, hitElementType] = hit !== undefined ? hit.name.split('::') : [undefined, undefined];
|
|
535
|
+
const previous = lastHoveredRef.current;
|
|
536
|
+
const sameAsBefore = previous !== undefined && hitSeriesName === previous.seriesName && hitElementType === previous.elementType;
|
|
537
|
+
if ((previous === null || previous === void 0 ? void 0 : previous.seriesName) !== hitSeriesName) {
|
|
538
|
+
if (previous !== undefined)
|
|
539
|
+
highlightAxesFor(previous.seriesName, false);
|
|
540
|
+
if (hitSeriesName !== undefined)
|
|
541
|
+
highlightAxesFor(hitSeriesName, true);
|
|
542
|
+
}
|
|
543
|
+
if (!sameAsBefore) {
|
|
544
|
+
if (previous !== undefined) {
|
|
545
|
+
handleMouseLeaveSeries(previous.seriesName, mouseLeaveHandlerFor(`tooltip-${chartId}`, PROVIDER_ID_FOR_ELEMENT_TYPE[previous.elementType]));
|
|
546
|
+
}
|
|
547
|
+
if (hitSeriesName !== undefined && hitElementType !== undefined) {
|
|
548
|
+
const series = seriesRef.current.get(hitSeriesName);
|
|
549
|
+
const yAxis = axesFor(hitSeriesName, axisAssignments, axisId => xAxesState.axisFor(axisId).getOrUndefined(), axisId => yAxesState.axisFor(axisId).getOrUndefined())[1];
|
|
550
|
+
const showingByType = {
|
|
551
|
+
minMax: showMinMaxBars,
|
|
552
|
+
windowedMinMax: showWindowedMinMaxBars,
|
|
553
|
+
meanValue: showMeanValueLines,
|
|
554
|
+
windowedMeanValue: showWindowedMeanValueLines,
|
|
555
|
+
currentValue: showValueLines,
|
|
556
|
+
};
|
|
557
|
+
if (series !== undefined && yAxis !== undefined && allowTooltipRef.current && showingByType[hitElementType]) {
|
|
558
|
+
handleMouseOverBar(yAxis, series, statsRef.current, [x, y], margin, mouseOverHandlerFor(`tooltip-${chartId}`, PROVIDER_ID_FOR_ELEMENT_TYPE[hitElementType]));
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
lastHoveredRef.current = hitSeriesName !== undefined && hitElementType !== undefined ?
|
|
562
|
+
{ seriesName: hitSeriesName, elementType: hitElementType } :
|
|
563
|
+
undefined;
|
|
564
|
+
// the value-line and windowed-mean-line highlight depends on hover state, so
|
|
565
|
+
// request a redraw when it changes
|
|
566
|
+
canvasContext.requestRedraw();
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
const handleLeaveCanvas = () => {
|
|
570
|
+
const previous = lastHoveredRef.current;
|
|
571
|
+
if (previous !== undefined) {
|
|
572
|
+
handleMouseLeaveSeries(previous.seriesName, mouseLeaveHandlerFor(`tooltip-${chartId}`, PROVIDER_ID_FOR_ELEMENT_TYPE[previous.elementType]));
|
|
573
|
+
highlightAxesFor(previous.seriesName, false);
|
|
574
|
+
lastHoveredRef.current = undefined;
|
|
575
|
+
canvasContext.requestRedraw();
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
canvas.addEventListener('mousemove', handleMove);
|
|
579
|
+
canvas.addEventListener('mouseleave', handleLeaveCanvas);
|
|
580
|
+
return () => {
|
|
581
|
+
canvas.removeEventListener('mousemove', handleMove);
|
|
582
|
+
canvas.removeEventListener('mouseleave', handleLeaveCanvas);
|
|
583
|
+
};
|
|
584
|
+
}, [
|
|
585
|
+
canvasContext, chartId, margin, axisAssignments, xAxesState, yAxesState,
|
|
586
|
+
mouseOverHandlerFor, mouseLeaveHandlerFor,
|
|
587
|
+
showMinMaxBars, showWindowedMinMaxBars, showMeanValueLines, showWindowedMeanValueLines, showValueLines,
|
|
588
|
+
highlightAxesOnMouseOver
|
|
589
|
+
]);
|
|
590
|
+
// the latest `updateTimingAndPlot`, for the view driver to call -- the driver is created once
|
|
591
|
+
// per run (see below), so it must not capture a stale one (e.g. bound to an older canvas)
|
|
592
|
+
const updateTimingAndPlotRef = useRef(updateTimingAndPlot);
|
|
593
|
+
useEffect(() => {
|
|
594
|
+
updateTimingAndPlotRef.current = updateTimingAndPlot;
|
|
595
|
+
}, [updateTimingAndPlot]);
|
|
596
|
+
// creates the view driver that keeps this plot's view in step with the data source, using the
|
|
597
|
+
// current settings -- see `useStreamingTimeAxes`'s identical effect event
|
|
598
|
+
const createViewDriver = useEffectEvent((source) => ordinalViewDriverFor(source, windowingTime, () => updateTimingAndPlotRef.current(), currentTime => currentTimeRef.current = currentTime));
|
|
599
|
+
// while the data source is running (and this plot has a canvas), drive the view from the
|
|
600
|
+
// data source's updates -- see `useStreamingTimeAxes`'s identical effect. The driver belongs to this plot
|
|
601
|
+
// instance alone and is always torn down with it.
|
|
602
|
+
useEffect(() => {
|
|
603
|
+
if (dataSource === undefined || !running || canvasContext === null)
|
|
604
|
+
return;
|
|
605
|
+
allowTooltipRef.current = false;
|
|
606
|
+
const driver = createViewDriver(dataSource);
|
|
607
|
+
return () => {
|
|
608
|
+
driver.unsubscribe();
|
|
370
609
|
allowTooltipRef.current = true;
|
|
610
|
+
};
|
|
611
|
+
}, [dataSource, running, canvasContext]);
|
|
612
|
+
// this plot needs a data source (see the `Chart`'s `dataSource` prop)
|
|
613
|
+
useEffect(() => {
|
|
614
|
+
if (dataSource === undefined) {
|
|
615
|
+
console.error("BarPlot requires a data source; set the enclosing Chart's `dataSource` prop");
|
|
371
616
|
}
|
|
372
|
-
}, [
|
|
617
|
+
}, [dataSource]);
|
|
618
|
+
// unregister this plot's draw function on unmount
|
|
619
|
+
useEffect(() => {
|
|
620
|
+
return () => {
|
|
621
|
+
if (canvasContext) {
|
|
622
|
+
canvasContext.unregister(`bar-plot-autoscale-${chartId}`);
|
|
623
|
+
canvasContext.unregister(`bar-plot-${chartId}`);
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
}, [canvasContext, chartId]);
|
|
373
627
|
return null;
|
|
374
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* The bar style, made fully transparent when the bar isn't shown
|
|
631
|
+
* @param isVisible Whether the bar is shown
|
|
632
|
+
* @param style The bar's style
|
|
633
|
+
* @return The style (with its fill and stroke opacities 0 when the bar isn't shown)
|
|
634
|
+
*/
|
|
375
635
|
function barStyleFor(isVisible, style) {
|
|
376
|
-
return
|
|
636
|
+
return {
|
|
637
|
+
...style,
|
|
638
|
+
fill: updateOpacityFor(isVisible, style.fill),
|
|
639
|
+
stroke: updateOpacityFor(isVisible, style.stroke)
|
|
640
|
+
};
|
|
377
641
|
}
|
|
642
|
+
/**
|
|
643
|
+
* The fill or stroke style, made fully transparent when its element isn't shown
|
|
644
|
+
* @param isVisible Whether the element is shown
|
|
645
|
+
* @param style The fill or stroke style
|
|
646
|
+
* @return The style (with an opacity of 0 when the element isn't shown)
|
|
647
|
+
*/
|
|
378
648
|
function updateOpacityFor(isVisible, style) {
|
|
379
|
-
return
|
|
649
|
+
return {
|
|
650
|
+
...style,
|
|
651
|
+
opacity: isVisible ? style.opacity : 0
|
|
652
|
+
};
|
|
380
653
|
}
|
|
381
654
|
/**
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
* @param
|
|
655
|
+
* Draws a bar (rectangle) onto the canvas context. Replaces the old `barFor`, which set SVG
|
|
656
|
+
* `<rect>` attributes via a d3 selection.
|
|
657
|
+
* @param context The canvas 2D context
|
|
658
|
+
* @param dimensions The bar's dimensions
|
|
385
659
|
* @param style The bar style holding the fill and stroke styles
|
|
386
|
-
* @return The updated SVG selection (rect SVG element)
|
|
387
660
|
*/
|
|
388
|
-
function
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
661
|
+
function drawBar(context, dimensions, style) {
|
|
662
|
+
var _a;
|
|
663
|
+
if (dimensions.width <= 0 || dimensions.height <= 0)
|
|
664
|
+
return;
|
|
665
|
+
applyFillStyle(context, style.fill);
|
|
666
|
+
context.fillRect(dimensions.upperX, dimensions.upperY, dimensions.width, dimensions.height);
|
|
667
|
+
if (((_a = style.stroke.width) !== null && _a !== void 0 ? _a : 0) > 0) {
|
|
668
|
+
applyStrokeStyle(context, style.stroke);
|
|
669
|
+
context.strokeRect(dimensions.upperX, dimensions.upperY, dimensions.width, dimensions.height);
|
|
670
|
+
}
|
|
395
671
|
}
|
|
396
672
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
* @param
|
|
400
|
-
*
|
|
673
|
+
* Draws a horizontal line segment (used for the value/mean/windowed-mean lines) onto the canvas
|
|
674
|
+
* context. Replaces the old `lineFor`, which set SVG `<line>` attributes via a d3 selection.
|
|
675
|
+
* @param context The canvas 2D context
|
|
676
|
+
* @param x1 The line's start x-coordinate
|
|
677
|
+
* @param y1 The line's start y-coordinate
|
|
678
|
+
* @param x2 The line's end x-coordinate
|
|
679
|
+
* @param y2 The line's end y-coordinate
|
|
401
680
|
* @param strokeStyle The stroke style
|
|
402
|
-
* @return The updated SVG selection (rect SVG element)
|
|
403
681
|
*/
|
|
404
|
-
function
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return applyStrokeStylesTo(selection, strokeStyle);
|
|
682
|
+
function drawLine(context, x1, y1, x2, y2, strokeStyle) {
|
|
683
|
+
applyStrokeStyle(context, strokeStyle);
|
|
684
|
+
context.beginPath();
|
|
685
|
+
context.moveTo(x1, y1);
|
|
686
|
+
context.lineTo(x2, y2);
|
|
687
|
+
context.stroke();
|
|
411
688
|
}
|
|
412
689
|
/**
|
|
413
690
|
* Calculates the upper (x, y) coordinates of the bar, and the width and height of the bar
|
|
@@ -434,48 +711,48 @@ function barDimensions(widthFraction, lowerX, upperX, min, max, axis) {
|
|
|
434
711
|
};
|
|
435
712
|
}
|
|
436
713
|
/**
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
* @
|
|
440
|
-
*
|
|
714
|
+
* @param dataSource The chart's data source
|
|
715
|
+
* @param series The series to calculate the stats for when the data source doesn't keep them
|
|
716
|
+
* @return The data source's (live) stats when it keeps them (i.e. an ordinal data source);
|
|
717
|
+
* otherwise, the stats calculated from the specified series
|
|
441
718
|
*/
|
|
442
|
-
function
|
|
443
|
-
|
|
444
|
-
|
|
719
|
+
function statsFrom(dataSource, series) {
|
|
720
|
+
return dataSource !== null && typeof dataSource === 'object' && 'stats' in dataSource ?
|
|
721
|
+
dataSource.stats :
|
|
722
|
+
initialOrdinalStats(series);
|
|
445
723
|
}
|
|
446
724
|
/**
|
|
447
|
-
* Attempts to locate the x- and y-axes for the specified series. If
|
|
448
|
-
*
|
|
725
|
+
* Attempts to locate the x- and y-axes for the specified series. If the series has no axis
|
|
726
|
+
* assignment, then uses the default (first) x- and y-axes.
|
|
449
727
|
* @param seriesName Name of the series for which to retrieve the axis
|
|
450
728
|
* @param axisAssignments A map holding the series name and the associated x- and y-axes assigned
|
|
451
729
|
* to that series. Note that the series in the axis-assignment map is merely a subset of the set
|
|
452
730
|
* of series names.
|
|
453
731
|
* @param xAxisFor The function that accepts an axis ID and returns the corresponding x-axis
|
|
454
732
|
* @param yAxisFor The function that accepts an axis ID and returns the corresponding y-axis
|
|
455
|
-
* @return A 2d tuple holding the
|
|
456
|
-
* the second element.
|
|
733
|
+
* @return A 2d tuple holding the category x-axis as its first element and the linear y-axis as
|
|
734
|
+
* the second element (either is actually `undefined` when it isn't found, despite the type).
|
|
735
|
+
* @throws Error when the x-axis isn't a category axis, or the y-axis isn't a continuous numeric axis
|
|
457
736
|
*/
|
|
458
737
|
function axesFor(seriesName, axisAssignments, xAxisFor, yAxisFor) {
|
|
459
738
|
const axes = axisAssignments.get(seriesName);
|
|
460
739
|
const xAxis = xAxisFor((axes === null || axes === void 0 ? void 0 : axes.xAxis) || "");
|
|
740
|
+
checkAxisType("BarPlot", "x", xAxis, AxisType.OrdinalString);
|
|
461
741
|
const xAxisCategory = xAxis;
|
|
462
|
-
if (xAxis && !xAxisCategory) {
|
|
463
|
-
throw Error("Bar plot requires that x-axis be of type CategoryAxis");
|
|
464
|
-
}
|
|
465
742
|
const yAxis = yAxisFor((axes === null || axes === void 0 ? void 0 : axes.yAxis) || "");
|
|
743
|
+
checkAxisType("BarPlot", "y", yAxis, AxisType.ContinuousNumeric);
|
|
466
744
|
const yAxisContinuous = yAxis;
|
|
467
|
-
if (yAxis && !yAxisContinuous) {
|
|
468
|
-
throw Error("Bar plot requires that y-axis be of type ContinuousNumericAxis");
|
|
469
|
-
}
|
|
470
745
|
return [xAxisCategory, yAxisContinuous];
|
|
471
746
|
}
|
|
472
747
|
/**
|
|
473
|
-
* Calculates the
|
|
474
|
-
*
|
|
748
|
+
* Calculates the lower (left) and upper (right) x-coordinates of a category's lines, inside its
|
|
749
|
+
* margins
|
|
750
|
+
* @param categorySize The size of the category (i.e. plot_width / num_series)
|
|
475
751
|
* @param lineWidth The width of the series line
|
|
476
|
-
* @param margin The margin applied to the
|
|
477
|
-
* @return An object with two functions, that when handed
|
|
478
|
-
*
|
|
752
|
+
* @param margin The margin applied to the left and right of the category's lines (horizontal spacing)
|
|
753
|
+
* @return An object with two functions, that when handed the category's (left) x-coordinate,
|
|
754
|
+
* return the location of the start (lower) or end (upper) of its lines (when the category is no
|
|
755
|
+
* wider than the margin, the lines are just the line width long)
|
|
479
756
|
*/
|
|
480
757
|
function xAxisCategoryBoundsFn(categorySize, lineWidth, margin) {
|
|
481
758
|
if (categorySize <= margin)
|
|
@@ -489,68 +766,38 @@ function xAxisCategoryBoundsFn(categorySize, lineWidth, margin) {
|
|
|
489
766
|
};
|
|
490
767
|
}
|
|
491
768
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
769
|
+
* Reports a tooltip for the hovered element of a series in the bar chart (see {@link BarPlotTooltipContent}).
|
|
770
|
+
* Replaces the old version, which also mutated the hovered SVG element's stroke directly for the
|
|
771
|
+
* two element types that support a highlight (`currentValue`, `windowedMeanValue`); that highlight
|
|
772
|
+
* is now handled by the draw function checking the hover state (see `updatePlot`'s `draw`) rather
|
|
773
|
+
* than by touching an element here.
|
|
494
774
|
* @param yAxis The y-axis
|
|
495
775
|
* @param selectedSeries The selected series
|
|
496
776
|
* @param seriesStats The statistics about the current series
|
|
497
|
-
* @param
|
|
777
|
+
* @param mouseCoords The `[x, y]` position of the mouse, in canvas coordinates
|
|
498
778
|
* @param margin The plot margin
|
|
499
|
-
* @param barStyles The series style information (needed for (un)highlighting)
|
|
500
|
-
* @param defaultBarSeriesStyle The default bar series style that is used if no style is found for the series
|
|
501
|
-
* @param allowTooltip When set to `false` won't show tooltip, even if it is visible (used by pan)
|
|
502
779
|
* @param mouseOverHandlerFor The handler for the mouse over (registered by the <Tooltip/>)
|
|
503
|
-
* @param tooltipProvider The ID of the tooltip provider
|
|
504
780
|
*/
|
|
505
|
-
function handleMouseOverBar(
|
|
506
|
-
|
|
507
|
-
const [x, y] = d3.pointer(event, container);
|
|
781
|
+
function handleMouseOverBar(yAxis, selectedSeries, seriesStats, mouseCoords, margin, mouseOverHandlerFor) {
|
|
782
|
+
const [, y] = mouseCoords;
|
|
508
783
|
const value = yAxis.scale.invert(y - margin.top);
|
|
509
784
|
const { name: categoryName, data: selectedData } = selectedSeries;
|
|
510
|
-
|
|
511
|
-
const lineStyle = lineStyleFor(tooltipProvider, barSeriesStyle);
|
|
512
|
-
if (lineStyle !== undefined) {
|
|
513
|
-
d3.select(event.currentTarget)
|
|
514
|
-
.style(STROKE_COLOR, lineStyle.highlight.color)
|
|
515
|
-
.style(STROKE_WIDTH, lineStyle.highlight.width)
|
|
516
|
-
.style(STROKE_OPACITY, lineStyle.highlight.opacity);
|
|
517
|
-
}
|
|
518
|
-
if (mouseOverHandlerFor && allowTooltip) {
|
|
785
|
+
if (mouseOverHandlerFor) {
|
|
519
786
|
// the contract for the mouse over handler is for a series
|
|
520
|
-
mouseOverHandlerFor(categoryName, value, { series: selectedData, metadata: seriesStats },
|
|
787
|
+
mouseOverHandlerFor(categoryName, value, { series: selectedData, metadata: seriesStats }, mouseCoords);
|
|
521
788
|
}
|
|
522
789
|
}
|
|
523
790
|
/**
|
|
524
|
-
*
|
|
791
|
+
* Calls the mouse-leave-series handler registered for this series. Replaces the old version, which
|
|
792
|
+
* also reset the hovered SVG element's stroke color/width directly; that reset is now implicit --
|
|
793
|
+
* once the hover state no longer matches this element, the next redraw simply paints it in its
|
|
794
|
+
* normal (non-highlighted) style.
|
|
525
795
|
* @param seriesName The name of the series (i.e. the neuron ID)
|
|
526
|
-
* @param segment The SVG line element representing the spike, over which the mouse is hovering.
|
|
527
|
-
* @param seriesStyles The styles for the series (for (un)highlighting)
|
|
528
|
-
* @param defaultBarSeriesStyle The default bar series style that is used if no style is found for the series
|
|
529
796
|
* @param mouseLeaverHandlerFor Registered handler for the series when the mouse leaves
|
|
530
|
-
* @param tooltipProvider The tooltip provider ID for the mouse-over event
|
|
531
797
|
*/
|
|
532
|
-
function handleMouseLeaveSeries(seriesName,
|
|
533
|
-
const barSeriesStyle = seriesStyles.get(seriesName) || defaultBarSeriesStyle;
|
|
534
|
-
const lineStyle = lineStyleFor(tooltipProvider, barSeriesStyle);
|
|
535
|
-
if (lineStyle !== undefined) {
|
|
536
|
-
d3.select(segment)
|
|
537
|
-
.style(STROKE_COLOR, lineStyle.regular.color)
|
|
538
|
-
.style(STROKE_WIDTH, lineStyle.regular.width)
|
|
539
|
-
.style(STROKE_OPACITY, lineStyle.regular.opacity);
|
|
540
|
-
}
|
|
798
|
+
function handleMouseLeaveSeries(seriesName, mouseLeaverHandlerFor) {
|
|
541
799
|
if (mouseLeaverHandlerFor) {
|
|
542
800
|
mouseLeaverHandlerFor(seriesName);
|
|
543
801
|
}
|
|
544
802
|
}
|
|
545
|
-
function lineStyleFor(tooltipProvider, barSeriesStyle) {
|
|
546
|
-
const { valueLine, windowedMeanValueLine } = barSeriesStyle;
|
|
547
|
-
switch (tooltipProvider) {
|
|
548
|
-
case BAR_CHART_TOOLTIP_PROVIDER_IDS.currentValue:
|
|
549
|
-
return valueLine;
|
|
550
|
-
case BAR_CHART_TOOLTIP_PROVIDER_IDS.windowedMeanValue:
|
|
551
|
-
return windowedMeanValueLine;
|
|
552
|
-
default:
|
|
553
|
-
return undefined;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
803
|
//# sourceMappingURL=BarPlot.js.map
|