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,21 +1,17 @@
|
|
|
1
|
-
import {BaseAxis,
|
|
1
|
+
import {type BaseAxis, type SeriesStyle} from "../axes/axes";
|
|
2
|
+
import {useHoveredSeries} from "../hooks/useHoveredSeries";
|
|
3
|
+
import {useInitialData} from "../hooks/useDataSource";
|
|
2
4
|
import {BaseAxisRange} from "../axes/BaseAxisRange";
|
|
3
5
|
import {usePlotDimensions} from "../hooks/usePlotDimensions";
|
|
4
6
|
import {useChart} from "../hooks/useChart";
|
|
5
|
-
import {
|
|
6
|
-
import React, {useCallback, useEffect, useMemo, useRef, useState} from "react";
|
|
7
|
+
import React, {useCallback, useEffect, useMemo, useRef} from "react";
|
|
7
8
|
import {createPortal} from "react-dom";
|
|
8
9
|
import * as d3 from "d3";
|
|
10
|
+
import {defaultLegendStyle, LegendLocation} from "./constants";
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
TOP_RIGHT = "top-right",
|
|
14
|
-
BOTTOM_LEFT = "bottom-left",
|
|
15
|
-
BOTTOM_RIGHT = "bottom-right",
|
|
16
|
-
EXTERNAL_CONTAINER = "external-container"
|
|
17
|
-
}
|
|
18
|
-
|
|
12
|
+
/**
|
|
13
|
+
* The style of the legend's box and entries
|
|
14
|
+
*/
|
|
19
15
|
export interface LegendStyle {
|
|
20
16
|
/** Font size for the legend labels */
|
|
21
17
|
fontSize: number
|
|
@@ -45,30 +41,15 @@ export interface LegendStyle {
|
|
|
45
41
|
swatchHeight: number
|
|
46
42
|
/** Gap between the swatch and the label text */
|
|
47
43
|
swatchLabelGap: number
|
|
48
|
-
/** Maximum height of the legend before it starts scrolling (in pixels). If not provided, defaults to the plot height. */
|
|
44
|
+
/** Maximum height of the legend before it starts scrolling (in pixels). If not provided, defaults to a little less than the plot height. */
|
|
49
45
|
maxHeight?: number
|
|
50
46
|
/** Duration of the visibility transition in milliseconds */
|
|
51
47
|
transitionDuration: number
|
|
52
48
|
}
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
fontColor: "#d2933f",
|
|
58
|
-
backgroundColor: "#202020",
|
|
59
|
-
backgroundOpacity: 0.85,
|
|
60
|
-
borderColor: "#d2933f",
|
|
61
|
-
borderWidth: 1,
|
|
62
|
-
borderOpacity: 0.7,
|
|
63
|
-
borderRadius: 4,
|
|
64
|
-
padding: 8,
|
|
65
|
-
rowGap: 6,
|
|
66
|
-
swatchWidth: 16,
|
|
67
|
-
swatchHeight: 3,
|
|
68
|
-
swatchLabelGap: 6,
|
|
69
|
-
transitionDuration: 350,
|
|
70
|
-
}
|
|
71
|
-
|
|
50
|
+
/**
|
|
51
|
+
* The properties of the {@link Legend}
|
|
52
|
+
*/
|
|
72
53
|
export interface Props {
|
|
73
54
|
/** Whether the legend is visible */
|
|
74
55
|
visible: boolean
|
|
@@ -88,20 +69,39 @@ export interface Props {
|
|
|
88
69
|
offset?: { x: number; y: number }
|
|
89
70
|
/**
|
|
90
71
|
* When provided, the legend renders as an HTML element portal into this
|
|
91
|
-
* external container instead of
|
|
92
|
-
* however you like — the legend fills it.
|
|
72
|
+
* external container instead of as an overlay on the chart canvas. Position the
|
|
73
|
+
* container however you like — the legend fills it.
|
|
93
74
|
*/
|
|
94
75
|
container?: React.RefObject<HTMLElement | null>
|
|
95
76
|
}
|
|
96
77
|
|
|
97
|
-
const LEGEND_CONTAINER_ID_PREFIX = "stream-charts-legend"
|
|
98
|
-
|
|
99
78
|
/**
|
|
100
79
|
* A legend component that can be placed inside any `<Chart>` alongside any Plot.
|
|
101
80
|
* It automatically reads the series names from the initial data and their colors
|
|
102
81
|
* from the `seriesStyles` map (falling back to the chart's base `color`).
|
|
103
82
|
* The legend respects the active `seriesFilter`, showing only the matching series.
|
|
104
83
|
*
|
|
84
|
+
* Renders as an HTML overlay (a React portal) rather than as SVG elements -- either into the
|
|
85
|
+
* `container` prop, when supplied, or (the default) into the chart's own canvas overlay wrapper
|
|
86
|
+
* (the `position: relative` `<div>` that {@link Chart} wraps the `<canvas>` in), absolutely
|
|
87
|
+
* positioned against the plot area using `location`/`offset`. This replaces the old version's two
|
|
88
|
+
* separate rendering paths (an SVG-internal legend with a hand-rolled scrollbar/clip-path/wheel
|
|
89
|
+
* handler, and an HTML-portal legend for the external-container case) with one: the SVG path's
|
|
90
|
+
* custom scrolling machinery existed only because SVG has no native scrolling or text
|
|
91
|
+
* auto-sizing -- an HTML `<div>` with `overflowY: 'auto'` gets both for free, which is exactly
|
|
92
|
+
* what the already-existing external-container path relied on.
|
|
93
|
+
*
|
|
94
|
+
* Hovering over an entry highlights its series (through the chart's shared hovered-series state),
|
|
95
|
+
* and hovering over a series in the plot highlights its entry.
|
|
96
|
+
* @param props The properties of the legend
|
|
97
|
+
* @return The legend (rendered into a portal), or `null` when it isn't visible, there are no
|
|
98
|
+
* series to show, or there's nowhere (yet) to render it into
|
|
99
|
+
* @template D The type of the series' datum
|
|
100
|
+
* @template S The type of the series style
|
|
101
|
+
* @template TM The type of the tooltip metadata
|
|
102
|
+
* @template AR The type of the axis range
|
|
103
|
+
* @template A The type of the axis
|
|
104
|
+
*
|
|
105
105
|
* @example
|
|
106
106
|
* ```tsx
|
|
107
107
|
* <Chart ...>
|
|
@@ -123,20 +123,15 @@ export function Legend<D, S extends SeriesStyle, TM, AR extends BaseAxisRange, A
|
|
|
123
123
|
container: externalContainer
|
|
124
124
|
} = props
|
|
125
125
|
|
|
126
|
-
const {
|
|
126
|
+
const {
|
|
127
|
+
canvas,
|
|
128
|
+
color,
|
|
129
|
+
seriesStyles,
|
|
130
|
+
seriesFilter,
|
|
131
|
+
} = useChart<D, S, TM, AR, A>()
|
|
132
|
+
const {hoveredSeriesName, setHoveredSeriesName} = useHoveredSeries()
|
|
127
133
|
const {margin, plotDimensions} = usePlotDimensions()
|
|
128
|
-
const {initialData} = useInitialData<
|
|
129
|
-
|
|
130
|
-
// the mouse over series name interferes with scrolling, so we keep track of the
|
|
131
|
-
// scrolling state so the series-name mouse-over can be disabled during scrolling
|
|
132
|
-
const wheelTimeoutRef = useRef<NodeJS.Timeout>(undefined)
|
|
133
|
-
const isWheelingRef = useRef(false)
|
|
134
|
-
|
|
135
|
-
const scrollYRef = useRef<number>(0)
|
|
136
|
-
|
|
137
|
-
// keep track of whether the mouse is in the legend so that we can restore the legend
|
|
138
|
-
// opacity when the mouse leaves and is not hovering over a series
|
|
139
|
-
const [mouseInLegend, setMouseInLegend] = useState<boolean>(false)
|
|
134
|
+
const {initialData} = useInitialData<D>()
|
|
140
135
|
|
|
141
136
|
const legendStyle = useMemo<LegendStyle>(
|
|
142
137
|
() => ({
|
|
@@ -147,53 +142,20 @@ export function Legend<D, S extends SeriesStyle, TM, AR extends BaseAxisRange, A
|
|
|
147
142
|
[style, plotDimensions.height]
|
|
148
143
|
)
|
|
149
144
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const [hoveredSeriesName, setHoveredSeriesName] = useState<string | null>(null)
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
const handlerId = `legend-${chartId}`
|
|
160
|
-
mouse.registerMouseOverHandler(handlerId, seriesName => setHoveredSeriesName(seriesName))
|
|
161
|
-
mouse.registerMouseLeaveHandler(handlerId, () => setHoveredSeriesName(null))
|
|
162
|
-
return () => {
|
|
163
|
-
mouse.unregisterMouseOverHandler(handlerId)
|
|
164
|
-
mouse.unregisterMouseLeaveHandler(handlerId)
|
|
165
|
-
}
|
|
166
|
-
}, [chartId, mouse])
|
|
167
|
-
|
|
168
|
-
// Keep a ref so D3 closures in the SVG legend always read current styles
|
|
169
|
-
const seriesStylesRef = useRef<Map<string, S>>(seriesStyles)
|
|
170
|
-
seriesStylesRef.current = seriesStyles
|
|
171
|
-
|
|
172
|
-
const highlightSeriesInPlot = useCallback<(name: string) => void>(name => {
|
|
173
|
-
hoveredSeriesRef.current = name
|
|
174
|
-
if (!container) return
|
|
175
|
-
const {
|
|
176
|
-
highlightColor,
|
|
177
|
-
highlightWidth
|
|
178
|
-
} = (seriesStylesRef.current.get(name) as SeriesLineStyle | undefined) || defaultLineStyle()
|
|
179
|
-
d3.select(container)
|
|
180
|
-
.selectAll<SVGPathElement, unknown>(`path[data-series-name="${name}"], line[data-series-name="${name}"]`)
|
|
181
|
-
.attr('stroke', highlightColor)
|
|
182
|
-
.attr('stroke-width', highlightWidth)
|
|
183
|
-
}, [container, hoveredSeriesRef])
|
|
145
|
+
const highlightSeriesInPlot = useCallback<(name: string) => void>(
|
|
146
|
+
name => {
|
|
147
|
+
setHoveredSeriesName(name)
|
|
148
|
+
if (!canvas) return
|
|
149
|
+
},
|
|
150
|
+
[canvas, setHoveredSeriesName]
|
|
151
|
+
)
|
|
184
152
|
|
|
185
|
-
const restoreSeriesInPlot = useCallback<(name: string) => void>(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
} = (seriesStylesRef.current.get(name) as SeriesLineStyle | undefined) || defaultLineStyle()
|
|
192
|
-
d3.select(container)
|
|
193
|
-
.selectAll<SVGPathElement, unknown>(`path[data-series-name="${name}"], line[data-series-name="${name}"]`)
|
|
194
|
-
.attr('stroke', color)
|
|
195
|
-
.attr('stroke-width', lineWidth)
|
|
196
|
-
}, [container, hoveredSeriesRef])
|
|
153
|
+
const restoreSeriesInPlot = useCallback<(name: string) => void>(
|
|
154
|
+
() => {
|
|
155
|
+
if (!canvas) return
|
|
156
|
+
},
|
|
157
|
+
[canvas]
|
|
158
|
+
)
|
|
197
159
|
|
|
198
160
|
// Derive the filtered list of series names
|
|
199
161
|
const visibleSeriesNames = useMemo<Array<string>>(
|
|
@@ -201,400 +163,157 @@ export function Legend<D, S extends SeriesStyle, TM, AR extends BaseAxisRange, A
|
|
|
201
163
|
[initialData, seriesFilter]
|
|
202
164
|
)
|
|
203
165
|
|
|
166
|
+
// A `container` prop that never resolves to a mounted element is a caller-attributable
|
|
167
|
+
// misconfiguration (unlike a not-yet-attached `canvas`, which is normal/transient on first
|
|
168
|
+
// mount) -- surface it once, rather than silently rendering nothing forever with no clue why.
|
|
169
|
+
// Gated on `visible && visibleSeriesNames.length > 0` -- i.e. only when we'd actually attempt
|
|
170
|
+
// to render -- since a container legitimately un-mounted alongside `visible: false` (a common
|
|
171
|
+
// pattern: hide the legend and its container together) is not a misconfiguration and shouldn't
|
|
172
|
+
// warn. Depending on `canvas` too (not just `externalContainer`, whose identity is otherwise
|
|
173
|
+
// stable across renders) gives this a few extra chances to reassess as the chart's own canvas
|
|
174
|
+
// surface settles, before concluding the ref is genuinely never going to attach.
|
|
175
|
+
const hasWarnedMissingContainerRef = useRef(false)
|
|
204
176
|
useEffect(
|
|
205
177
|
() => {
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
178
|
+
if (
|
|
179
|
+
visible &&
|
|
180
|
+
visibleSeriesNames.length > 0 &&
|
|
181
|
+
externalContainer &&
|
|
182
|
+
externalContainer.current === null &&
|
|
183
|
+
!hasWarnedMissingContainerRef.current
|
|
184
|
+
) {
|
|
185
|
+
console.warn(
|
|
186
|
+
'Legend: the "container" prop was provided, but its .current is null, so the legend has ' +
|
|
187
|
+
'nothing to render into and will render nothing. Make sure the ref is attached to an ' +
|
|
188
|
+
'element that actually mounts.'
|
|
189
|
+
)
|
|
190
|
+
hasWarnedMissingContainerRef.current = true
|
|
215
191
|
}
|
|
216
|
-
|
|
217
|
-
if (!visible || visibleSeriesNames.length === 0) {
|
|
218
|
-
svg.select(`#${legendId}`).remove()
|
|
219
|
-
return
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Remove any existing legend (before we potentially redraw) or just reuse?
|
|
223
|
-
// Usually, redrawing is safer if we want to ensure everything is in the right place.
|
|
224
|
-
// But if we're transitioning from visible: false to true, the old one might be gone.
|
|
225
|
-
// Let's just remove without transition for redrawing, except when explicitly making it invisible.
|
|
226
|
-
svg.select(`#${legendId}`).remove()
|
|
227
|
-
|
|
228
|
-
const {
|
|
229
|
-
fontSize,
|
|
230
|
-
fontFamily,
|
|
231
|
-
fontColor,
|
|
232
|
-
backgroundColor,
|
|
233
|
-
backgroundOpacity,
|
|
234
|
-
borderColor,
|
|
235
|
-
borderWidth,
|
|
236
|
-
borderOpacity,
|
|
237
|
-
borderRadius,
|
|
238
|
-
padding,
|
|
239
|
-
rowGap,
|
|
240
|
-
swatchWidth,
|
|
241
|
-
swatchHeight,
|
|
242
|
-
swatchLabelGap,
|
|
243
|
-
maxHeight,
|
|
244
|
-
} = legendStyle
|
|
245
|
-
|
|
246
|
-
const rowHeight = Math.max(swatchHeight, fontSize)
|
|
247
|
-
const totalRows = visibleSeriesNames.length
|
|
248
|
-
const contentHeight = totalRows * rowHeight + (totalRows - 1) * rowGap
|
|
249
|
-
const totalContentHeight = contentHeight + 2 * padding
|
|
250
|
-
const boxHeight = maxHeight !== undefined ? Math.min(totalContentHeight, maxHeight) : totalContentHeight
|
|
251
|
-
|
|
252
|
-
// Use a temporary hidden SVG text element to measure max label width
|
|
253
|
-
const tempText = svg
|
|
254
|
-
.append<SVGTextElement>("text")
|
|
255
|
-
.style("font-size", `${fontSize}px`)
|
|
256
|
-
.style("font-family", fontFamily)
|
|
257
|
-
.style("visibility", "hidden")
|
|
258
|
-
|
|
259
|
-
let maxLabelWidth = 0
|
|
260
|
-
visibleSeriesNames.forEach(name => {
|
|
261
|
-
tempText.text(name)
|
|
262
|
-
const w = tempText.node()?.getBBox().width ?? name.length * (fontSize * 0.6)
|
|
263
|
-
if (w > maxLabelWidth) maxLabelWidth = w
|
|
264
|
-
})
|
|
265
|
-
tempText.remove()
|
|
266
|
-
|
|
267
|
-
const boxWidth = padding + swatchWidth + swatchLabelGap + maxLabelWidth + padding
|
|
268
|
-
|
|
269
|
-
// Determine the (x, y) position of the legend box within the SVG (plot area coordinates)
|
|
270
|
-
const plotLeft = margin.left
|
|
271
|
-
const plotTop = margin.top
|
|
272
|
-
const plotRight = margin.left + plotDimensions.width
|
|
273
|
-
const plotBottom = margin.top + plotDimensions.height
|
|
274
|
-
|
|
275
|
-
let boxX: number
|
|
276
|
-
let boxY: number
|
|
277
|
-
|
|
278
|
-
switch (location) {
|
|
279
|
-
case LegendLocation.TOP_LEFT:
|
|
280
|
-
boxX = plotLeft + offset.x
|
|
281
|
-
boxY = plotTop + offset.y
|
|
282
|
-
break
|
|
283
|
-
case LegendLocation.TOP_RIGHT:
|
|
284
|
-
boxX = plotRight - boxWidth - offset.x
|
|
285
|
-
boxY = plotTop + offset.y
|
|
286
|
-
break
|
|
287
|
-
case LegendLocation.BOTTOM_LEFT:
|
|
288
|
-
boxX = plotLeft + offset.x
|
|
289
|
-
boxY = plotBottom - boxHeight - offset.y
|
|
290
|
-
break
|
|
291
|
-
case LegendLocation.BOTTOM_RIGHT:
|
|
292
|
-
default:
|
|
293
|
-
boxX = plotRight - boxWidth - offset.x
|
|
294
|
-
boxY = plotBottom - boxHeight - offset.y
|
|
295
|
-
break
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Create the legend container group
|
|
299
|
-
const legendG = svg
|
|
300
|
-
.append<SVGGElement>("g")
|
|
301
|
-
.attr("id", legendId)
|
|
302
|
-
.attr("transform", `translate(${boxX}, ${boxY})`)
|
|
303
|
-
.style("opacity", 0)
|
|
304
|
-
.on("mouseover", () => {
|
|
305
|
-
setMouseInLegend(true)
|
|
306
|
-
})
|
|
307
|
-
.on("mouseleave", () => {
|
|
308
|
-
setMouseInLegend(false)
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
// Apply transition for shimmering effect
|
|
312
|
-
legendG
|
|
313
|
-
.style("transition", `opacity ${transitionDuration}ms ease-in-out`)
|
|
314
|
-
.style("opacity", 1)
|
|
315
|
-
|
|
316
|
-
// Background box
|
|
317
|
-
legendG
|
|
318
|
-
.append("rect")
|
|
319
|
-
.attr("x", 0)
|
|
320
|
-
.attr("y", 0)
|
|
321
|
-
.attr("width", boxWidth)
|
|
322
|
-
.attr("height", boxHeight)
|
|
323
|
-
.attr("rx", borderRadius)
|
|
324
|
-
.attr("fill", backgroundColor)
|
|
325
|
-
.attr("fill-opacity", backgroundOpacity)
|
|
326
|
-
.attr("stroke", borderColor)
|
|
327
|
-
.attr("stroke-width", borderWidth)
|
|
328
|
-
.attr("stroke-opacity", borderOpacity)
|
|
329
|
-
|
|
330
|
-
const innerG = legendG
|
|
331
|
-
.append("g")
|
|
332
|
-
.attr("class", "legend-content")
|
|
333
|
-
.attr("transform", `translate(0, ${-scrollYRef.current})`)
|
|
334
|
-
|
|
335
|
-
// If we have a max height and the content is taller, we'd need a scrollbar.
|
|
336
|
-
// In SVG, we can use a clipPath and handle scroll events manually, or use foreignObject.
|
|
337
|
-
// foreignObject is generally better for this if we want real scrollbars.
|
|
338
|
-
const isScrolling = maxHeight !== undefined && totalContentHeight > maxHeight
|
|
339
|
-
|
|
340
|
-
if (isScrolling) {
|
|
341
|
-
const clipId = `legend-clip-${chartId}`
|
|
342
|
-
// Remove existing clipPath for this legend to avoid duplicates
|
|
343
|
-
svg.select(`#${clipId}`).remove()
|
|
344
|
-
//
|
|
345
|
-
svg.append("defs")
|
|
346
|
-
.append("clipPath")
|
|
347
|
-
.attr("id", clipId)
|
|
348
|
-
.attr("clipPathUnits", "userSpaceOnUse")
|
|
349
|
-
.append("rect")
|
|
350
|
-
.attr("x", 0)
|
|
351
|
-
.attr("y", 0)
|
|
352
|
-
.attr("width", boxWidth)
|
|
353
|
-
.attr("height", boxHeight)
|
|
354
|
-
|
|
355
|
-
legendG.attr("clip-path", `url(#${clipId})`)
|
|
356
|
-
|
|
357
|
-
// Simple scroll handling via mouse wheel
|
|
358
|
-
legendG.on("wheel", (event: WheelEvent) => {
|
|
359
|
-
event.preventDefault()
|
|
360
|
-
// scrollBarVisibleRef.current = true
|
|
361
|
-
isWheelingRef.current = true
|
|
362
|
-
const maxScroll = totalContentHeight - boxHeight
|
|
363
|
-
scrollYRef.current = Math.max(0, Math.min(maxScroll, scrollYRef.current + event.deltaY))
|
|
364
|
-
innerG.attr("transform", `translate(0, ${-scrollYRef.current})`)
|
|
365
|
-
|
|
366
|
-
// Clear the existing timer if the user is still wheeling
|
|
367
|
-
clearTimeout(wheelTimeoutRef.current);
|
|
368
|
-
|
|
369
|
-
// Set a new timer to fire after 100-200ms of inactivity
|
|
370
|
-
wheelTimeoutRef.current = setTimeout(() => {
|
|
371
|
-
isWheelingRef.current = false
|
|
372
|
-
// scrollBarVisibleRef.current = false
|
|
373
|
-
console.log(`Wheel movement has ended. ${isWheelingRef.current ? "Still wheeling." : "No longer wheeling."}`);
|
|
374
|
-
}, 150);
|
|
375
|
-
}, {passive: false})
|
|
376
|
-
|
|
377
|
-
// Visual scrollbar (optional but good for visibility)
|
|
378
|
-
const scrollbarWidth = 4
|
|
379
|
-
const scrollbarHeight = (boxHeight / totalContentHeight) * boxHeight - padding
|
|
380
|
-
const scrollbar = legendG.append("rect")
|
|
381
|
-
.attr("class", "legend-scrollbar")
|
|
382
|
-
.attr("x", boxWidth - scrollbarWidth - 2)
|
|
383
|
-
.attr("y", calculateScrollbarY(totalContentHeight, boxHeight, scrollYRef.current, scrollbarHeight, padding))
|
|
384
|
-
.attr("width", scrollbarWidth)
|
|
385
|
-
.attr("height", scrollbarHeight)
|
|
386
|
-
.attr("rx", scrollbarWidth / 2)
|
|
387
|
-
.style("fill-opacity", mouseInLegend ? 0.25 : 0)
|
|
388
|
-
.attr("fill", fontColor)
|
|
389
|
-
|
|
390
|
-
legendG.on("wheel.scrollbar", (_: WheelEvent) => {
|
|
391
|
-
scrollbar.attr("y", calculateScrollbarY(totalContentHeight, boxHeight, scrollYRef.current, scrollbarHeight, padding))
|
|
392
|
-
})
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// Legend rows
|
|
396
|
-
visibleSeriesNames.forEach((name, i) => {
|
|
397
|
-
const seriesColor = seriesStyles.get(name)?.color ?? color
|
|
398
|
-
const rowY = padding + i * (rowHeight + rowGap)
|
|
399
|
-
const swatchMidY = rowY + rowHeight / 2
|
|
400
|
-
|
|
401
|
-
const rowG = innerG
|
|
402
|
-
.append("g")
|
|
403
|
-
.attr("class", "legend-row")
|
|
404
|
-
.attr("data-series-name", name)
|
|
405
|
-
.style("cursor", "default")
|
|
406
|
-
|
|
407
|
-
// Color swatch — a short horizontal line to mimic series appearance
|
|
408
|
-
rowG
|
|
409
|
-
.append("line")
|
|
410
|
-
.attr("x1", padding)
|
|
411
|
-
.attr("y1", swatchMidY)
|
|
412
|
-
.attr("x2", padding + swatchWidth)
|
|
413
|
-
.attr("y2", swatchMidY)
|
|
414
|
-
.attr("stroke", seriesColor)
|
|
415
|
-
.attr("stroke-width", swatchHeight)
|
|
416
|
-
.attr("stroke-linecap", "round")
|
|
417
|
-
|
|
418
|
-
// Series name label
|
|
419
|
-
rowG
|
|
420
|
-
.append("text")
|
|
421
|
-
.attr("x", padding + swatchWidth + swatchLabelGap)
|
|
422
|
-
.attr("y", swatchMidY)
|
|
423
|
-
.attr("dominant-baseline", "middle")
|
|
424
|
-
.attr("data-series-name", name)
|
|
425
|
-
.style("font-size", `${fontSize}px`)
|
|
426
|
-
.style("font-family", fontFamily)
|
|
427
|
-
.style("fill", fontColor)
|
|
428
|
-
.text(name)
|
|
429
|
-
|
|
430
|
-
// keep this at the end
|
|
431
|
-
rowG
|
|
432
|
-
.append("rect")
|
|
433
|
-
.attr("x", 0)
|
|
434
|
-
.attr("width", boxWidth)
|
|
435
|
-
.attr("y", padding + i * (rowHeight + rowGap) - rowGap)
|
|
436
|
-
.attr("height", rowHeight + rowGap)
|
|
437
|
-
.style("fill", backgroundColor)
|
|
438
|
-
.style("fill-opacity", 0)
|
|
439
|
-
.on("mouseover", () => {
|
|
440
|
-
if (isWheelingRef.current) return
|
|
441
|
-
setHoveredSeriesName(prevName => {
|
|
442
|
-
// restore any previous names in case the events
|
|
443
|
-
// get out of order, this prevents multiple series
|
|
444
|
-
// being highlighted when the mouse moves quickly
|
|
445
|
-
if (prevName && prevName !== name) {
|
|
446
|
-
restoreSeriesInPlot(prevName)
|
|
447
|
-
}
|
|
448
|
-
return name
|
|
449
|
-
})
|
|
450
|
-
highlightSeriesInPlot(name)
|
|
451
|
-
})
|
|
452
|
-
.on("mouseleave", () => {
|
|
453
|
-
setHoveredSeriesName(null)
|
|
454
|
-
restoreSeriesInPlot(name)
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
})
|
|
458
192
|
},
|
|
459
|
-
[
|
|
460
|
-
visible, container, externalContainer, chartId, visibleSeriesNames,
|
|
461
|
-
legendStyle, location, offset, margin, plotDimensions, color,
|
|
462
|
-
seriesStyles, highlightSeriesInPlot, restoreSeriesInPlot, mouseInLegend
|
|
463
|
-
]
|
|
193
|
+
[externalContainer, canvas, visible, visibleSeriesNames.length]
|
|
464
194
|
)
|
|
465
195
|
|
|
466
|
-
|
|
467
|
-
useEffect(
|
|
468
|
-
() => {
|
|
469
|
-
if (!container || externalContainer) return
|
|
470
|
-
const legendG = d3.select(container).select(`#${LEGEND_CONTAINER_ID_PREFIX}-${chartId}`)
|
|
471
|
-
if (!legendG.empty()) {
|
|
472
|
-
const FADE_BACK_OPACITY = 0.35
|
|
473
|
-
legendG.selectAll<SVGGElement, unknown>("g.legend-row")
|
|
474
|
-
.attr("transition", `opacity ${350}ms ease-in-out`)
|
|
475
|
-
.style("opacity", function (): number {
|
|
476
|
-
const seriesName = d3.select(this).attr("data-series-name")
|
|
477
|
-
if (mouseInLegend) {
|
|
478
|
-
return hoveredSeriesName !== null && seriesName === hoveredSeriesName ? 1 : FADE_BACK_OPACITY
|
|
479
|
-
} else if (hoveredSeriesName !== null && seriesName !== hoveredSeriesName) {
|
|
480
|
-
return FADE_BACK_OPACITY
|
|
481
|
-
} else {
|
|
482
|
-
return 1
|
|
483
|
-
}
|
|
484
|
-
})
|
|
485
|
-
legendG.selectAll<SVGTextElement, unknown>("text[data-series-name]")
|
|
486
|
-
.style("font-weight", function (): string {
|
|
487
|
-
const seriesName: string = d3.select(this).attr("data-series-name")
|
|
488
|
-
return hoveredSeriesName !== null && seriesName === hoveredSeriesName ? "bold" : "normal"
|
|
489
|
-
})
|
|
490
|
-
}
|
|
491
|
-
},
|
|
492
|
-
[hoveredSeriesName, container, externalContainer, chartId, mouseInLegend]
|
|
493
|
-
)
|
|
196
|
+
if (!visible || visibleSeriesNames.length === 0) return null
|
|
494
197
|
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
fontFamily,
|
|
500
|
-
fontColor,
|
|
501
|
-
backgroundColor,
|
|
502
|
-
backgroundOpacity,
|
|
503
|
-
borderColor,
|
|
504
|
-
borderWidth,
|
|
505
|
-
borderOpacity,
|
|
506
|
-
borderRadius,
|
|
507
|
-
padding,
|
|
508
|
-
rowGap,
|
|
509
|
-
swatchWidth,
|
|
510
|
-
swatchHeight,
|
|
511
|
-
swatchLabelGap,
|
|
512
|
-
maxHeight,
|
|
513
|
-
transitionDuration,
|
|
514
|
-
} = legendStyle
|
|
198
|
+
// the portal target: the caller-supplied external container, or (by default) the chart's own
|
|
199
|
+
// canvas overlay wrapper -- the `position: relative` div Chart.tsx wraps the <canvas> in
|
|
200
|
+
const portalTarget = externalContainer?.current ?? canvas?.parentElement ?? null
|
|
201
|
+
if (portalTarget === null) return null
|
|
515
202
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
203
|
+
const {
|
|
204
|
+
fontSize,
|
|
205
|
+
fontFamily,
|
|
206
|
+
fontColor,
|
|
207
|
+
backgroundColor,
|
|
208
|
+
backgroundOpacity,
|
|
209
|
+
borderColor,
|
|
210
|
+
borderWidth,
|
|
211
|
+
borderOpacity,
|
|
212
|
+
borderRadius,
|
|
213
|
+
padding,
|
|
214
|
+
rowGap,
|
|
215
|
+
swatchWidth,
|
|
216
|
+
swatchHeight,
|
|
217
|
+
swatchLabelGap,
|
|
218
|
+
maxHeight,
|
|
219
|
+
transitionDuration,
|
|
220
|
+
} = legendStyle
|
|
221
|
+
|
|
222
|
+
const bg = d3.color(backgroundColor) as d3.RGBColor | undefined
|
|
223
|
+
const bgWithOpacity = bg
|
|
224
|
+
? `rgba(${bg.r},${bg.g},${bg.b},${backgroundOpacity})`
|
|
225
|
+
: backgroundColor
|
|
226
|
+
const bd = d3.color(borderColor) as d3.RGBColor | undefined
|
|
227
|
+
const bdWithOpacity = bd
|
|
228
|
+
? `rgba(${bd.r},${bd.g},${bd.b},${borderOpacity})`
|
|
229
|
+
: borderColor
|
|
230
|
+
|
|
231
|
+
// when rendering into our own overlay (no external container), anchor the box to the
|
|
232
|
+
// corresponding corner of the *plot area* (inside the margins), matching the old SVG
|
|
233
|
+
// version's positioning intent -- but via CSS `top`/`right`/`bottom`/`left` instead of a
|
|
234
|
+
// manually-computed pixel (x, y), since we don't need to know the box's own width/height
|
|
235
|
+
// ahead of time the way the old version's manual layout math did
|
|
236
|
+
const anchorStyle: React.CSSProperties = externalContainer ? {} : (() => {
|
|
237
|
+
switch (location) {
|
|
238
|
+
case LegendLocation.TOP_LEFT:
|
|
239
|
+
return {position: 'absolute', top: margin.top + offset.y, left: margin.left + offset.x}
|
|
240
|
+
case LegendLocation.TOP_RIGHT:
|
|
241
|
+
return {position: 'absolute', top: margin.top + offset.y, right: margin.right + offset.x}
|
|
242
|
+
case LegendLocation.BOTTOM_LEFT:
|
|
243
|
+
return {position: 'absolute', bottom: margin.bottom + offset.y, left: margin.left + offset.x}
|
|
244
|
+
case LegendLocation.BOTTOM_RIGHT:
|
|
245
|
+
case LegendLocation.EXTERNAL_CONTAINER:
|
|
246
|
+
default:
|
|
247
|
+
return {position: 'absolute', bottom: margin.bottom + offset.y, right: margin.right + offset.x}
|
|
541
248
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
setHoveredSeriesName(name)
|
|
564
|
-
highlightSeriesInPlot(name)
|
|
565
|
-
}}
|
|
566
|
-
onMouseLeave={() => {
|
|
567
|
-
setHoveredSeriesName(null)
|
|
568
|
-
restoreSeriesInPlot(name)
|
|
569
|
-
}}
|
|
570
|
-
>
|
|
571
|
-
<span style={{
|
|
572
|
-
display: "inline-block",
|
|
573
|
-
width: swatchWidth,
|
|
574
|
-
height: swatchHeight,
|
|
575
|
-
backgroundColor: seriesColor,
|
|
576
|
-
borderRadius: swatchHeight / 2,
|
|
577
|
-
flexShrink: 0,
|
|
578
|
-
}}/>
|
|
579
|
-
<span style={{
|
|
580
|
-
height: rowGap + fontSize,
|
|
581
|
-
alignItems: "center",
|
|
582
|
-
display: "inline-flex"
|
|
583
|
-
}}>{name}</span>
|
|
584
|
-
</div>
|
|
585
|
-
)
|
|
586
|
-
})}
|
|
587
|
-
</div>,
|
|
588
|
-
externalContainer.current
|
|
589
|
-
)
|
|
249
|
+
})()
|
|
250
|
+
|
|
251
|
+
const boxStyle: React.CSSProperties = {
|
|
252
|
+
...anchorStyle,
|
|
253
|
+
display: "inline-flex",
|
|
254
|
+
flexDirection: "column",
|
|
255
|
+
backgroundColor: bgWithOpacity,
|
|
256
|
+
border: `${borderWidth}px solid ${bdWithOpacity}`,
|
|
257
|
+
borderRadius,
|
|
258
|
+
padding,
|
|
259
|
+
maxHeight,
|
|
260
|
+
overflowY: "auto",
|
|
261
|
+
fontFamily,
|
|
262
|
+
fontSize,
|
|
263
|
+
color: fontColor,
|
|
264
|
+
boxSizing: "border-box",
|
|
265
|
+
opacity: visible ? 1 : 0,
|
|
266
|
+
transition: visible ? `opacity ${transitionDuration}ms ease-in-out` : "none",
|
|
267
|
+
pointerEvents: visible ? "auto" : "none",
|
|
268
|
+
whiteSpace: "nowrap",
|
|
269
|
+
zIndex: 10,
|
|
590
270
|
}
|
|
591
271
|
|
|
592
|
-
|
|
272
|
+
const anyHovered = hoveredSeriesName !== null
|
|
273
|
+
return createPortal(
|
|
274
|
+
<div style={boxStyle}>
|
|
275
|
+
{visibleSeriesNames.map(name => {
|
|
276
|
+
const seriesColor = seriesStyles.get(name)?.color ?? color
|
|
277
|
+
const isHovered = name === hoveredSeriesName
|
|
278
|
+
const rowStyle: React.CSSProperties = {
|
|
279
|
+
display: "flex",
|
|
280
|
+
alignItems: "center",
|
|
281
|
+
gap: swatchLabelGap,
|
|
282
|
+
opacity: anyHovered && !isHovered ? 0.35 : 1,
|
|
283
|
+
fontWeight: isHovered ? "bold" : "normal",
|
|
284
|
+
transition: "opacity 0.15s, font-weight 0s",
|
|
285
|
+
height: rowGap + fontSize,
|
|
286
|
+
}
|
|
287
|
+
return (
|
|
288
|
+
<div
|
|
289
|
+
key={name}
|
|
290
|
+
style={{...rowStyle, cursor: "default"}}
|
|
291
|
+
onMouseEnter={() => {
|
|
292
|
+
setHoveredSeriesName(name)
|
|
293
|
+
highlightSeriesInPlot(name)
|
|
294
|
+
}}
|
|
295
|
+
onMouseLeave={() => {
|
|
296
|
+
setHoveredSeriesName(null)
|
|
297
|
+
restoreSeriesInPlot(name)
|
|
298
|
+
}}
|
|
299
|
+
>
|
|
300
|
+
<span style={{
|
|
301
|
+
display: "inline-block",
|
|
302
|
+
width: swatchWidth,
|
|
303
|
+
height: swatchHeight,
|
|
304
|
+
backgroundColor: seriesColor,
|
|
305
|
+
borderRadius: swatchHeight / 2,
|
|
306
|
+
flexShrink: 0,
|
|
307
|
+
}}/>
|
|
308
|
+
<span style={{
|
|
309
|
+
height: rowGap + fontSize,
|
|
310
|
+
alignItems: "center",
|
|
311
|
+
display: "inline-flex"
|
|
312
|
+
}}>{name}</span>
|
|
313
|
+
</div>
|
|
314
|
+
)
|
|
315
|
+
})}
|
|
316
|
+
</div>,
|
|
317
|
+
portalTarget
|
|
318
|
+
)
|
|
593
319
|
}
|
|
594
|
-
|
|
595
|
-
function calculateScrollbarY(totalContentHeight: number, boxHeight: number, scrollY: number, scrollbarHeight: number, padding: number): number {
|
|
596
|
-
const maxScroll = totalContentHeight - boxHeight
|
|
597
|
-
const scrollPercent = scrollY / maxScroll
|
|
598
|
-
const scrollbarMaxY = boxHeight - scrollbarHeight - 4 - padding
|
|
599
|
-
return Math.max(padding, 2 + scrollPercent * scrollbarMaxY)
|
|
600
|
-
}
|