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
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {useEffect, useRef} from "react";
|
|
2
|
+
import type {Optional} from "result-fn";
|
|
3
|
+
import type {BaseAxis, ContinuousNumericAxis} from "../axes/axes";
|
|
4
|
+
import type {BaseAxisRange} from "../axes/BaseAxisRange";
|
|
5
|
+
import {ContinuousAxisRange} from "../axes/ContinuousAxisRange";
|
|
6
|
+
import {grownDomain} from "../axes/autoScale";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What a plot needs from its chart's axes to auto-scale its y-axes (see `ContinuousAxis`'s
|
|
10
|
+
* `autoScale` prop)
|
|
11
|
+
*/
|
|
12
|
+
export type AutoScaleAxes = {
|
|
13
|
+
/**
|
|
14
|
+
* The plot's y-axes, by their IDs
|
|
15
|
+
*/
|
|
16
|
+
yAxes: Map<string, BaseAxis>
|
|
17
|
+
/**
|
|
18
|
+
* The (current and original) range of the specified axis
|
|
19
|
+
*/
|
|
20
|
+
axisRangeFor: (axisId: string) => Optional<BaseAxisRange>
|
|
21
|
+
/**
|
|
22
|
+
* Updates the specified axes' ranges (which updates the axes)
|
|
23
|
+
*/
|
|
24
|
+
updateAxisRanges: (ranges: Map<string, ContinuousAxisRange>) => void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The axis' range, updated to the specified domain (or a new range for it, when the axis has none)
|
|
29
|
+
* @param axisId The axis' ID
|
|
30
|
+
* @param domain The domain
|
|
31
|
+
* @param axisRangeFor The (current and original) range of the specified axis
|
|
32
|
+
* @return The updated range
|
|
33
|
+
*/
|
|
34
|
+
function rangeFor(
|
|
35
|
+
axisId: string,
|
|
36
|
+
[min, max]: [min: number, max: number],
|
|
37
|
+
axisRangeFor: AutoScaleAxes['axisRangeFor']
|
|
38
|
+
): ContinuousAxisRange {
|
|
39
|
+
return axisRangeFor(axisId)
|
|
40
|
+
.map(range => range.update(min, max) as ContinuousAxisRange)
|
|
41
|
+
.getOrElse(ContinuousAxisRange.from(min, max))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Grows the auto-scaling y-axes to fit the specified extents of the data plotted against them
|
|
46
|
+
* (within their limits, and with their padding -- see `grownDomain`). Meant to be called from a
|
|
47
|
+
* draw function registered to run before the axes draw (they're at z-index 0), so that the axes
|
|
48
|
+
* and the data are drawn with the grown domain in the same frame.
|
|
49
|
+
* @param extents The extent of the (visible) data plotted against each y-axis, by axis ID
|
|
50
|
+
* @param axes The plot's y-axes, and their ranges
|
|
51
|
+
*/
|
|
52
|
+
export function growAutoScaledYAxes(
|
|
53
|
+
extents: Map<string, [min: number, max: number]>,
|
|
54
|
+
axes: AutoScaleAxes
|
|
55
|
+
): void {
|
|
56
|
+
const {yAxes, axisRangeFor, updateAxisRanges} = axes
|
|
57
|
+
const updates = new Map<string, ContinuousAxisRange>()
|
|
58
|
+
extents.forEach((extent, axisId) => {
|
|
59
|
+
const axis = yAxes.get(axisId) as ContinuousNumericAxis | undefined
|
|
60
|
+
if (axis?.autoScale === undefined) return
|
|
61
|
+
const [currentMin, currentMax] = axis.scale.domain()
|
|
62
|
+
const [min, max] = grownDomain([currentMin, currentMax], extent, axis.autoScale, axis.scale)
|
|
63
|
+
if (min !== currentMin || max !== currentMax) {
|
|
64
|
+
updates.set(axisId, rangeFor(axisId, [min, max], axisRangeFor))
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
if (updates.size > 0) updateAxisRanges(updates)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* New data, new scale: when the plot's data source is replaced (e.g. on a reset, or a change to
|
|
72
|
+
* the number of series), restarts the auto-scaling y-axes from their starts (and they then grow
|
|
73
|
+
* to fit the new data). Only on a *change* of data source -- not when the plot mounts with its
|
|
74
|
+
* data source, which would throw away an axis' kept growth (see `ContinuousAxis`'s
|
|
75
|
+
* `autoScaledDomain`). The axes are read through a ref, so that this only acts when the data
|
|
76
|
+
* source changes -- not, say, when an axis is added.
|
|
77
|
+
* @param dataSource The plot's data source
|
|
78
|
+
* @param axes The plot's y-axes, and their ranges
|
|
79
|
+
*/
|
|
80
|
+
export function useAutoScaleRestart(dataSource: unknown, axes: AutoScaleAxes): void {
|
|
81
|
+
const axesRef = useRef(axes)
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
axesRef.current = axes
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const dataSourceRef = useRef(dataSource)
|
|
87
|
+
useEffect(
|
|
88
|
+
() => {
|
|
89
|
+
if (dataSourceRef.current === dataSource) return
|
|
90
|
+
dataSourceRef.current = dataSource
|
|
91
|
+
|
|
92
|
+
const {yAxes, axisRangeFor, updateAxisRanges} = axesRef.current
|
|
93
|
+
const updates = new Map<string, ContinuousAxisRange>()
|
|
94
|
+
yAxes.forEach((axis, axisId) => {
|
|
95
|
+
const {autoScale} = axis as ContinuousNumericAxis
|
|
96
|
+
if (autoScale !== undefined) updates.set(axisId, rangeFor(axisId, autoScale.domain, axisRangeFor))
|
|
97
|
+
})
|
|
98
|
+
if (updates.size > 0) updateAxisRanges(updates)
|
|
99
|
+
},
|
|
100
|
+
[dataSource]
|
|
101
|
+
)
|
|
102
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import * as d3 from "d3";
|
|
2
|
+
import type {CurveFactory} from "d3";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The default color of a colorized line's start (its oldest point): a blue
|
|
6
|
+
*/
|
|
7
|
+
export const DEFAULT_LINE_START_COLOR = '#2f6cf6'
|
|
8
|
+
/**
|
|
9
|
+
* The default color of a colorized line's end (its newest point): a red
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_LINE_END_COLOR = '#e8423f'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The default number of points it takes a colorized line's color to sweep from its start color to
|
|
15
|
+
* its end color (see `sweepFraction`)
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_LINE_COLOR_STEPS = 1000
|
|
18
|
+
|
|
19
|
+
// a piece of a line, as d3's line generator traced it: where it starts and ends, and how to draw
|
|
20
|
+
// it (from its start) onto a canvas path
|
|
21
|
+
type LinePiece = {
|
|
22
|
+
start: [x: number, y: number]
|
|
23
|
+
end: [x: number, y: number]
|
|
24
|
+
draw: (context: CanvasPath) => void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Records the pieces of the line that d3's line generator traces (one per drawing command:
|
|
29
|
+
* `lineTo`, `bezierCurveTo`, ...), rather than drawing them, so that each piece can be stroked in
|
|
30
|
+
* its own color while keeping the curve's exact shape
|
|
31
|
+
*/
|
|
32
|
+
class LineRecorder {
|
|
33
|
+
readonly pieces: Array<LinePiece> = []
|
|
34
|
+
private current: [x: number, y: number] = [0, 0]
|
|
35
|
+
private subpathStart: [x: number, y: number] = [0, 0]
|
|
36
|
+
|
|
37
|
+
moveTo(x: number, y: number): void {
|
|
38
|
+
this.current = [x, y]
|
|
39
|
+
this.subpathStart = [x, y]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
lineTo(x: number, y: number): void {
|
|
43
|
+
this.add([x, y], context => context.lineTo(x, y))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {
|
|
47
|
+
this.add([x, y], context => context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void {
|
|
51
|
+
this.add([x, y], context => context.quadraticCurveTo(cpx, cpy, x, y))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void {
|
|
55
|
+
this.add([x2, y2], context => context.arcTo(x1, y1, x2, y2, radius))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {
|
|
59
|
+
const end: [number, number] = [x + radius * Math.cos(endAngle), y + radius * Math.sin(endAngle)]
|
|
60
|
+
this.add(end, context => context.arc(x, y, radius, startAngle, endAngle, counterclockwise))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
closePath(): void {
|
|
64
|
+
const [x, y] = this.subpathStart
|
|
65
|
+
this.add([x, y], context => context.lineTo(x, y))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
rect(x: number, y: number, width: number, height: number): void {
|
|
69
|
+
this.moveTo(x, y)
|
|
70
|
+
this.lineTo(x + width, y)
|
|
71
|
+
this.lineTo(x + width, y + height)
|
|
72
|
+
this.lineTo(x, y + height)
|
|
73
|
+
this.closePath()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private add(end: [x: number, y: number], draw: (context: CanvasPath) => void): void {
|
|
77
|
+
this.pieces.push({start: this.current, end, draw})
|
|
78
|
+
this.current = end
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Creates the function that gives the color at a fraction of the way along a colorized line:
|
|
84
|
+
* from the start color (at 0) to the end color (at 1), sweeping the long way around the hue
|
|
85
|
+
* circle, so that the line passes through the colors of the spectrum in between (e.g. from blue,
|
|
86
|
+
* through cyan, green, and yellow, to red)
|
|
87
|
+
* @param startColor The color at the line's start
|
|
88
|
+
* @param endColor The color at the line's end
|
|
89
|
+
* @return The color at a fraction (from 0 to 1) of the way along the line
|
|
90
|
+
*/
|
|
91
|
+
export function lineColorScale(startColor: string, endColor: string): (fraction: number) => string {
|
|
92
|
+
return d3.interpolateHslLong(startColor, endColor)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Where a point is in the color sweep of a colorized line: the line's color advances one step per
|
|
97
|
+
* point, sweeping from the start color (0) to the end color (1) over `steps` points, then back to
|
|
98
|
+
* the start color over the next `steps` points, and so on -- so the color never jumps
|
|
99
|
+
* @param pointNumber The point's overall sequence number in its series (from 0)
|
|
100
|
+
* @param steps The number of points (steps) a sweep from the start color to the end color takes
|
|
101
|
+
* @return The fraction (from 0, the start color, to 1, the end color) of the way through the sweep
|
|
102
|
+
*/
|
|
103
|
+
export function sweepFraction(pointNumber: number, steps: number): number {
|
|
104
|
+
const span = Math.max(1, steps)
|
|
105
|
+
const phase = (Math.max(0, pointNumber) / span) % 2
|
|
106
|
+
return phase <= 1 ? phase : 2 - phase
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Creates the function that gives the color of a colorized line at a point: from the start color,
|
|
111
|
+
* one step per point, to the end color, and back (see {@link sweepFraction}), sweeping the spectrum
|
|
112
|
+
* in between (see {@link lineColorScale})
|
|
113
|
+
* @param startColor The color the sweep starts at
|
|
114
|
+
* @param endColor The color the sweep ends at
|
|
115
|
+
* @param steps The number of points (steps) a sweep from the start color to the end color takes
|
|
116
|
+
* @return The color at a point, given its overall sequence number in its series
|
|
117
|
+
*/
|
|
118
|
+
export function pointColorScale(startColor: string, endColor: string, steps: number): (pointNumber: number) => string {
|
|
119
|
+
const colorAt = lineColorScale(startColor, endColor)
|
|
120
|
+
return pointNumber => colorAt(sweepFraction(pointNumber, steps))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Strokes a line through the specified points, with the specified curve, whose color changes
|
|
125
|
+
* along it: each piece of the line, as the curve traces it (e.g. the segment between two points),
|
|
126
|
+
* gets the color of the point it's at (pieces are matched to points by their position along the
|
|
127
|
+
* line, since some curves trace more, or fewer, pieces than there are segments). Consecutive
|
|
128
|
+
* pieces of the same color are stroked together. The curve's shape is exactly the same as
|
|
129
|
+
* stroking the whole line at once. The context's current line width (and other stroke settings)
|
|
130
|
+
* are used.
|
|
131
|
+
* @param context The canvas 2D context to stroke onto
|
|
132
|
+
* @param points The points, in order
|
|
133
|
+
* @param x The x-coordinate (in the context's space) of a point
|
|
134
|
+
* @param y The y-coordinate (in the context's space) of a point
|
|
135
|
+
* @param curve The curve (interpolation) between the points
|
|
136
|
+
* @param colorOf The color of the line at the point with the specified index (in `points`)
|
|
137
|
+
* @template P The type of the points
|
|
138
|
+
*/
|
|
139
|
+
export function strokeColorizedLine<P>(
|
|
140
|
+
context: CanvasRenderingContext2D,
|
|
141
|
+
points: Array<P>,
|
|
142
|
+
x: (point: P) => number,
|
|
143
|
+
y: (point: P) => number,
|
|
144
|
+
curve: CurveFactory,
|
|
145
|
+
colorOf: (index: number) => string
|
|
146
|
+
): void {
|
|
147
|
+
// (with a single point, there's no line to draw -- d3 would close the path back on itself)
|
|
148
|
+
if (points.length < 2) return
|
|
149
|
+
|
|
150
|
+
const recorder = new LineRecorder()
|
|
151
|
+
d3.line<P>().x(x).y(y).curve(curve).context(recorder as unknown as CanvasRenderingContext2D)(points)
|
|
152
|
+
const {pieces} = recorder
|
|
153
|
+
if (pieces.length === 0) return
|
|
154
|
+
|
|
155
|
+
// the index of the point a piece is at (for e.g. a linear curve, a segment's starting point)
|
|
156
|
+
const pointIndexOf = (pieceIndex: number) => pieces.length === 1 ?
|
|
157
|
+
0 :
|
|
158
|
+
Math.round(pieceIndex / (pieces.length - 1) * (points.length - 2))
|
|
159
|
+
const sameSpot = (a: [number, number], b: [number, number]) => a[0] === b[0] && a[1] === b[1]
|
|
160
|
+
|
|
161
|
+
context.save()
|
|
162
|
+
// (round joins and caps, so that consecutive runs of different colors meet without a notch)
|
|
163
|
+
context.lineJoin = 'round'
|
|
164
|
+
context.lineCap = 'round'
|
|
165
|
+
let color: string | undefined = undefined
|
|
166
|
+
let previousEnd: [number, number] | undefined = undefined
|
|
167
|
+
pieces.forEach((piece, index) => {
|
|
168
|
+
const pieceColor = colorOf(pointIndexOf(index))
|
|
169
|
+
if (pieceColor !== color) {
|
|
170
|
+
// a new color: stroke the run so far, and start a new one at this piece
|
|
171
|
+
if (color !== undefined) context.stroke()
|
|
172
|
+
color = pieceColor
|
|
173
|
+
context.strokeStyle = color
|
|
174
|
+
context.beginPath()
|
|
175
|
+
context.moveTo(piece.start[0], piece.start[1])
|
|
176
|
+
} else if (previousEnd === undefined || !sameSpot(previousEnd, piece.start)) {
|
|
177
|
+
// (a gap in the line, e.g. a new subpath)
|
|
178
|
+
context.moveTo(piece.start[0], piece.start[1])
|
|
179
|
+
}
|
|
180
|
+
piece.draw(context)
|
|
181
|
+
previousEnd = piece.end
|
|
182
|
+
})
|
|
183
|
+
context.stroke()
|
|
184
|
+
context.restore()
|
|
185
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// A sentinel that represents that no curve factory is to be used, which means
|
|
2
|
+
// that no line will be drawn between the iterates (kinda gross)
|
|
3
|
+
import type {CurveFactory} from "d3";
|
|
4
|
+
import type {BarChartElementId} from "./BarPlot";
|
|
5
|
+
|
|
6
|
+
export const NoCurveFactory: CurveFactory = undefined as unknown as CurveFactory; // constants identifying the bar-chart elements for which mouse-over/mouse-leave events are defined
|
|
7
|
+
|
|
8
|
+
export const STREAM_CHARTS_BAR_CHART_ID = 'stream-charts-bar-chart'
|
|
9
|
+
export const TOOLTIP_PROVIDER_ID = STREAM_CHARTS_BAR_CHART_ID + '-tooltip-provider'
|
|
10
|
+
export const BAR_CHART_TOOLTIP_PROVIDER_IDS: BarChartElementId = {
|
|
11
|
+
currentValue: TOOLTIP_PROVIDER_ID + '-current-value',
|
|
12
|
+
meanValue: TOOLTIP_PROVIDER_ID + '-mean-value',
|
|
13
|
+
minMax: TOOLTIP_PROVIDER_ID + '-min-max',
|
|
14
|
+
windowedMeanValue: TOOLTIP_PROVIDER_ID + '-windowed-min-max',
|
|
15
|
+
windowedMinMax: TOOLTIP_PROVIDER_ID + '-windowed-mean'
|
|
16
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Canvas has no per-shape mouse events (no SVG `.on("mouseover", ...)` equivalent) -- everything is
|
|
2
|
+
// just pixels on a bitmap. So instead of attaching a handler to each `<path>`/`<circle>`, plots
|
|
3
|
+
// register their drawn geometry (in canvas/pixel coordinates) here, and a single `mousemove`
|
|
4
|
+
// listener on the shared canvas element hit-tests the mouse position against that geometry to
|
|
5
|
+
// figure out which series (if any) the mouse is over.
|
|
6
|
+
|
|
7
|
+
/** A single (x, y) point in canvas drawing coordinates (i.e. already includes the plot's margin offset). */
|
|
8
|
+
export type Point = [x: number, y: number]
|
|
9
|
+
|
|
10
|
+
/** An axis-aligned rectangle, in canvas coordinates. */
|
|
11
|
+
export interface Rect {
|
|
12
|
+
x: number
|
|
13
|
+
y: number
|
|
14
|
+
width: number
|
|
15
|
+
height: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The screen-space geometry for one series, as last drawn, used for hit-testing on `mousemove`.
|
|
20
|
+
* Points/segments/rects are in the same canvas coordinate space the series was drawn in
|
|
21
|
+
* (margin-offset already applied).
|
|
22
|
+
*/
|
|
23
|
+
export interface SeriesGeometry {
|
|
24
|
+
/** the points that make up the series, in drawing order (ignored when `segments`/`rects` is set) */
|
|
25
|
+
points: Array<Point>
|
|
26
|
+
/**
|
|
27
|
+
* When set, `points` is hit-tested as a single *connected* polyline (mouse must be within
|
|
28
|
+
* `hitRadius` pixels of a line segment between consecutive points). When unset and
|
|
29
|
+
* `segments`/`rects` is also unset, `points` are hit-tested individually as circles of radius
|
|
30
|
+
* `hitRadius` (e.g. for marker/bar-style plots where there's no connecting line).
|
|
31
|
+
*/
|
|
32
|
+
asLine?: boolean
|
|
33
|
+
/**
|
|
34
|
+
* A set of *disjoint* line segments (e.g. one per raster spike) that are hit-tested
|
|
35
|
+
* independently -- unlike `asLine`, consecutive entries are NOT assumed to connect to each
|
|
36
|
+
* other. Takes precedence over `points`/`asLine` when set.
|
|
37
|
+
*/
|
|
38
|
+
segments?: Array<[Point, Point]>
|
|
39
|
+
/**
|
|
40
|
+
* A set of axis-aligned rectangles (e.g. bar-chart bars), hit-tested as filled regions (exact
|
|
41
|
+
* containment, not a `hitRadius` proximity test). Takes precedence over `segments`/`points`.
|
|
42
|
+
*/
|
|
43
|
+
rects?: Array<Rect>
|
|
44
|
+
/** how close (in pixels) the mouse must be to register a hit (ignored when `rects` is set) */
|
|
45
|
+
hitRadius: number
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Squared distance from a point to a line segment (avoids a sqrt when just comparing distances).
|
|
50
|
+
* @param px The point's x-coordinate
|
|
51
|
+
* @param py The point's y-coordinate
|
|
52
|
+
* @param x1 The x-coordinate of the segment's start
|
|
53
|
+
* @param y1 The y-coordinate of the segment's start
|
|
54
|
+
* @param x2 The x-coordinate of the segment's end
|
|
55
|
+
* @param y2 The y-coordinate of the segment's end
|
|
56
|
+
* @return The squared distance from the point to the nearest point on the segment
|
|
57
|
+
*/
|
|
58
|
+
function distanceSquaredToSegment(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number {
|
|
59
|
+
const dx = x2 - x1
|
|
60
|
+
const dy = y2 - y1
|
|
61
|
+
const lengthSquared = dx * dx + dy * dy
|
|
62
|
+
if (lengthSquared === 0) {
|
|
63
|
+
const ddx = px - x1
|
|
64
|
+
const ddy = py - y1
|
|
65
|
+
return ddx * ddx + ddy * ddy
|
|
66
|
+
}
|
|
67
|
+
// project point onto the segment, clamped to the segment's extent
|
|
68
|
+
let t = ((px - x1) * dx + (py - y1) * dy) / lengthSquared
|
|
69
|
+
t = Math.max(0, Math.min(1, t))
|
|
70
|
+
const closestX = x1 + t * dx
|
|
71
|
+
const closestY = y1 + t * dy
|
|
72
|
+
const ddx = px - closestX
|
|
73
|
+
const ddy = py - closestY
|
|
74
|
+
return ddx * ddx + ddy * ddy
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The result of a hit-test: which series was hit, and the index of the specific point (for
|
|
79
|
+
* point/polyline geometry) or segment (for disjoint-segment geometry) that matched -- so callers
|
|
80
|
+
* can look up the specific datum involved (e.g. for a tooltip) rather than just the series name.
|
|
81
|
+
*/
|
|
82
|
+
export interface SeriesHit {
|
|
83
|
+
/** the name of the series that was hit */
|
|
84
|
+
name: string
|
|
85
|
+
/**
|
|
86
|
+
* the index of the point (for point or polyline geometry -- for a polyline, whichever end of
|
|
87
|
+
* the hit segment is nearer the mouse), segment, or rect that was hit
|
|
88
|
+
*/
|
|
89
|
+
index: number
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Finds the series (and specific point/segment within it) hit by the given mouse position.
|
|
94
|
+
* Entries are checked in *reverse* insertion order -- i.e. most-recently-added first -- and the
|
|
95
|
+
* first entry with any qualifying match wins, matching normal DOM/SVG hit-testing (the topmost
|
|
96
|
+
* element captures the pointer) rather than picking whichever entry happens to report the smallest
|
|
97
|
+
* geometric distance across all entries.
|
|
98
|
+
*
|
|
99
|
+
* This distinction matters whenever two entries visually overlap: e.g. a bar-chart's value-line
|
|
100
|
+
* segment is drawn on top of (and can extend slightly beyond) its min/max bar's rect. A rect is a
|
|
101
|
+
* containment test -- any point inside it is unambiguously "hit," with no notion of "how close" --
|
|
102
|
+
* so comparing it against a segment's proximity-based distance would let the rect win everywhere
|
|
103
|
+
* the two overlap, even dead-center on the line, since 0 distance beats any nonzero one. Since
|
|
104
|
+
* plots insert geometry in the same order they draw it, checking entries topmost-first resolves
|
|
105
|
+
* this the way it looks on screen: whichever shape is drawn last (visually on top) claims the
|
|
106
|
+
* pointer first, and only falls through to earlier (lower) entries where it doesn't match at all.
|
|
107
|
+
*
|
|
108
|
+
* Within a single entry (e.g. Scatter's many polyline segments, or Raster's many disjoint spikes)
|
|
109
|
+
* the closest qualifying point/segment still wins, since there's no z-order to speak of among
|
|
110
|
+
* pieces of the same drawn shape.
|
|
111
|
+
* @param mouseX The mouse's x-coordinate, in the same canvas coordinate space the geometry was recorded in
|
|
112
|
+
* @param mouseY The mouse's y-coordinate, in the same canvas coordinate space the geometry was recorded in
|
|
113
|
+
* @param geometry A `map(series_name -> SeriesGeometry)` as last drawn, in draw order
|
|
114
|
+
* @return The hit series and matched index, or `undefined` if the mouse isn't over any series
|
|
115
|
+
*/
|
|
116
|
+
export function seriesAt(mouseX: number, mouseY: number, geometry: Map<string, SeriesGeometry>): SeriesHit | undefined {
|
|
117
|
+
const entries = Array.from(geometry.entries()).reverse()
|
|
118
|
+
|
|
119
|
+
for (const [name, {points, asLine, segments, rects, hitRadius}] of entries) {
|
|
120
|
+
const hitRadiusSquared = hitRadius * hitRadius
|
|
121
|
+
|
|
122
|
+
if (rects !== undefined) {
|
|
123
|
+
const index = rects.findIndex(rect =>
|
|
124
|
+
mouseX >= rect.x && mouseX <= rect.x + rect.width &&
|
|
125
|
+
mouseY >= rect.y && mouseY <= rect.y + rect.height
|
|
126
|
+
)
|
|
127
|
+
if (index >= 0) return {name, index}
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (segments !== undefined) {
|
|
132
|
+
let bestIndex = -1
|
|
133
|
+
let bestDistanceSquared = Infinity
|
|
134
|
+
segments.forEach(([[x1, y1], [x2, y2]], index) => {
|
|
135
|
+
const distanceSquared = distanceSquaredToSegment(mouseX, mouseY, x1, y1, x2, y2)
|
|
136
|
+
if (distanceSquared <= hitRadiusSquared && distanceSquared < bestDistanceSquared) {
|
|
137
|
+
bestDistanceSquared = distanceSquared
|
|
138
|
+
bestIndex = index
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
if (bestIndex >= 0) return {name, index: bestIndex}
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (points.length === 0) continue
|
|
146
|
+
|
|
147
|
+
if (asLine) {
|
|
148
|
+
let bestIndex = -1
|
|
149
|
+
let bestDistanceSquared = Infinity
|
|
150
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
151
|
+
const [x1, y1] = points[i]
|
|
152
|
+
const [x2, y2] = points[i + 1]
|
|
153
|
+
const distanceSquared = distanceSquaredToSegment(mouseX, mouseY, x1, y1, x2, y2)
|
|
154
|
+
if (distanceSquared <= hitRadiusSquared && distanceSquared < bestDistanceSquared) {
|
|
155
|
+
bestDistanceSquared = distanceSquared
|
|
156
|
+
// attribute the hit to whichever endpoint of the segment is nearer
|
|
157
|
+
const toStart = (mouseX - x1) ** 2 + (mouseY - y1) ** 2
|
|
158
|
+
const toEnd = (mouseX - x2) ** 2 + (mouseY - y2) ** 2
|
|
159
|
+
bestIndex = toStart <= toEnd ? i : i + 1
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (bestIndex >= 0) return {name, index: bestIndex}
|
|
163
|
+
continue
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let bestIndex = -1
|
|
167
|
+
let bestDistanceSquared = Infinity
|
|
168
|
+
points.forEach(([x, y], index) => {
|
|
169
|
+
const distanceSquared = (mouseX - x) ** 2 + (mouseY - y) ** 2
|
|
170
|
+
if (distanceSquared <= hitRadiusSquared && distanceSquared < bestDistanceSquared) {
|
|
171
|
+
bestDistanceSquared = distanceSquared
|
|
172
|
+
bestIndex = index
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
if (bestIndex >= 0) return {name, index: bestIndex}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return undefined
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Converts a `MouseEvent` (as received by a `canvas.addEventListener('mousemove', ...)` handler)
|
|
183
|
+
* into canvas-local coordinates, accounting for the canvas's on-page position and any CSS scaling
|
|
184
|
+
* between the canvas's backing-store size and its displayed size.
|
|
185
|
+
* @param event The mouse event
|
|
186
|
+
* @param canvas The canvas element the event was dispatched to
|
|
187
|
+
* @return The `[x, y]` position of the event, in the canvas's own CSS-pixel coordinate space
|
|
188
|
+
* (i.e. the same space `ctx` drawing calls use once the devicePixelRatio transform is applied)
|
|
189
|
+
*/
|
|
190
|
+
export function canvasLocalPoint(event: MouseEvent, canvas: HTMLCanvasElement): Point {
|
|
191
|
+
const rect = canvas.getBoundingClientRect()
|
|
192
|
+
const scaleX = rect.width > 0 ? canvas.clientWidth / rect.width : 1
|
|
193
|
+
const scaleY = rect.height > 0 ? canvas.clientHeight / rect.height : 1
|
|
194
|
+
return [
|
|
195
|
+
(event.clientX - rect.left) * scaleX,
|
|
196
|
+
(event.clientY - rect.top) * scaleY
|
|
197
|
+
]
|
|
198
|
+
}
|