stream-charts 1.2.0 → 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.
Files changed (463) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +809 -1022
  3. package/changes.md +40 -0
  4. package/dist/app/charts/Chart.d.ts +35 -139
  5. package/dist/app/charts/Chart.d.ts.map +1 -0
  6. package/dist/app/charts/Chart.js +74 -65
  7. package/dist/app/charts/Chart.js.map +1 -1
  8. package/dist/app/charts/axes/AxesState.d.ts +26 -18
  9. package/dist/app/charts/axes/AxesState.d.ts.map +1 -0
  10. package/dist/app/charts/axes/AxesState.js +26 -24
  11. package/dist/app/charts/axes/AxesState.js.map +1 -1
  12. package/dist/app/charts/axes/AxisInterval.d.ts +44 -26
  13. package/dist/app/charts/axes/AxisInterval.d.ts.map +1 -0
  14. package/dist/app/charts/axes/AxisInterval.js +48 -29
  15. package/dist/app/charts/axes/AxisInterval.js.map +1 -1
  16. package/dist/app/charts/axes/BaseAxisRange.d.ts +46 -22
  17. package/dist/app/charts/axes/BaseAxisRange.d.ts.map +1 -0
  18. package/dist/app/charts/axes/BaseAxisRange.js +17 -12
  19. package/dist/app/charts/axes/BaseAxisRange.js.map +1 -1
  20. package/dist/app/charts/axes/ContinuousAxis.d.ts +47 -6
  21. package/dist/app/charts/axes/ContinuousAxis.d.ts.map +1 -0
  22. package/dist/app/charts/axes/ContinuousAxis.js +160 -27
  23. package/dist/app/charts/axes/ContinuousAxis.js.map +1 -1
  24. package/dist/app/charts/axes/ContinuousAxisRange.d.ts +29 -10
  25. package/dist/app/charts/axes/ContinuousAxisRange.d.ts.map +1 -0
  26. package/dist/app/charts/axes/ContinuousAxisRange.js +29 -11
  27. package/dist/app/charts/axes/ContinuousAxisRange.js.map +1 -1
  28. package/dist/app/charts/axes/EmptyAxis.d.ts +5 -2
  29. package/dist/app/charts/axes/EmptyAxis.d.ts.map +1 -0
  30. package/dist/app/charts/axes/EmptyAxis.js +30 -9
  31. package/dist/app/charts/axes/EmptyAxis.js.map +1 -1
  32. package/dist/app/charts/axes/OrdinalAxis.d.ts +5 -3
  33. package/dist/app/charts/axes/OrdinalAxis.d.ts.map +1 -0
  34. package/dist/app/charts/axes/OrdinalAxis.js +39 -16
  35. package/dist/app/charts/axes/OrdinalAxis.js.map +1 -1
  36. package/dist/app/charts/axes/OrdinalAxisRange.d.ts +76 -13
  37. package/dist/app/charts/axes/OrdinalAxisRange.d.ts.map +1 -0
  38. package/dist/app/charts/axes/OrdinalAxisRange.js +95 -16
  39. package/dist/app/charts/axes/OrdinalAxisRange.js.map +1 -1
  40. package/dist/app/charts/axes/autoScale.d.ts +111 -0
  41. package/dist/app/charts/axes/autoScale.d.ts.map +1 -0
  42. package/dist/app/charts/axes/autoScale.js +188 -0
  43. package/dist/app/charts/axes/autoScale.js.map +1 -0
  44. package/dist/app/charts/axes/axes.d.ts +273 -150
  45. package/dist/app/charts/axes/axes.d.ts.map +1 -0
  46. package/dist/app/charts/axes/axes.js +808 -583
  47. package/dist/app/charts/axes/axes.js.map +1 -1
  48. package/dist/app/charts/d3types.d.ts +40 -11
  49. package/dist/app/charts/d3types.d.ts.map +1 -0
  50. package/dist/app/charts/d3types.js +3 -0
  51. package/dist/app/charts/d3types.js.map +1 -1
  52. package/dist/app/charts/datasources/StreamingDataSource.d.ts +149 -0
  53. package/dist/app/charts/datasources/StreamingDataSource.d.ts.map +1 -0
  54. package/dist/app/charts/datasources/StreamingDataSource.js +110 -0
  55. package/dist/app/charts/datasources/StreamingDataSource.js.map +1 -0
  56. package/dist/app/charts/datasources/iteratesDataSource.d.ts +73 -0
  57. package/dist/app/charts/datasources/iteratesDataSource.d.ts.map +1 -0
  58. package/dist/app/charts/datasources/iteratesDataSource.js +87 -0
  59. package/dist/app/charts/datasources/iteratesDataSource.js.map +1 -0
  60. package/dist/app/charts/datasources/ordinalDataSource.d.ts +75 -0
  61. package/dist/app/charts/datasources/ordinalDataSource.d.ts.map +1 -0
  62. package/dist/app/charts/datasources/ordinalDataSource.js +135 -0
  63. package/dist/app/charts/datasources/ordinalDataSource.js.map +1 -0
  64. package/dist/app/charts/datasources/outlierDataSource.d.ts +53 -0
  65. package/dist/app/charts/datasources/outlierDataSource.d.ts.map +1 -0
  66. package/dist/app/charts/datasources/outlierDataSource.js +57 -0
  67. package/dist/app/charts/datasources/outlierDataSource.js.map +1 -0
  68. package/dist/app/charts/datasources/timeSeriesDataSource.d.ts +77 -0
  69. package/dist/app/charts/datasources/timeSeriesDataSource.d.ts.map +1 -0
  70. package/dist/app/charts/datasources/timeSeriesDataSource.js +85 -0
  71. package/dist/app/charts/datasources/timeSeriesDataSource.js.map +1 -0
  72. package/dist/app/charts/filters/regexFilter.d.ts +31 -4
  73. package/dist/app/charts/filters/regexFilter.d.ts.map +1 -0
  74. package/dist/app/charts/filters/regexFilter.js +38 -4
  75. package/dist/app/charts/filters/regexFilter.js.map +1 -1
  76. package/dist/app/charts/hooks/AxesProvider.d.ts +21 -0
  77. package/dist/app/charts/hooks/AxesProvider.d.ts.map +1 -0
  78. package/dist/app/charts/hooks/AxesProvider.js +213 -0
  79. package/dist/app/charts/hooks/AxesProvider.js.map +1 -0
  80. package/dist/app/charts/hooks/CanvasSurfaceProvider.d.ts +25 -0
  81. package/dist/app/charts/hooks/CanvasSurfaceProvider.d.ts.map +1 -0
  82. package/dist/app/charts/hooks/CanvasSurfaceProvider.js +76 -0
  83. package/dist/app/charts/hooks/CanvasSurfaceProvider.js.map +1 -0
  84. package/dist/app/charts/hooks/ChartProvider.d.ts +40 -0
  85. package/dist/app/charts/hooks/ChartProvider.d.ts.map +1 -0
  86. package/dist/app/charts/hooks/ChartProvider.js +33 -0
  87. package/dist/app/charts/hooks/ChartProvider.js.map +1 -0
  88. package/dist/app/charts/hooks/InteractionProvider.d.ts +23 -0
  89. package/dist/app/charts/hooks/InteractionProvider.d.ts.map +1 -0
  90. package/dist/app/charts/hooks/InteractionProvider.js +60 -0
  91. package/dist/app/charts/hooks/InteractionProvider.js.map +1 -0
  92. package/dist/app/charts/hooks/PlotDimensionsProvider.d.ts +16 -0
  93. package/dist/app/charts/hooks/PlotDimensionsProvider.d.ts.map +1 -0
  94. package/dist/app/charts/hooks/PlotDimensionsProvider.js +76 -0
  95. package/dist/app/charts/hooks/PlotDimensionsProvider.js.map +1 -0
  96. package/dist/app/charts/hooks/defaultAxesValues.d.ts +11 -0
  97. package/dist/app/charts/hooks/defaultAxesValues.d.ts.map +1 -0
  98. package/dist/app/charts/hooks/defaultAxesValues.js +36 -0
  99. package/dist/app/charts/hooks/defaultAxesValues.js.map +1 -0
  100. package/dist/app/charts/hooks/defaultMouseValues.d.ts +9 -0
  101. package/dist/app/charts/hooks/defaultMouseValues.d.ts.map +1 -0
  102. package/dist/app/charts/hooks/defaultMouseValues.js +23 -0
  103. package/dist/app/charts/hooks/defaultMouseValues.js.map +1 -0
  104. package/dist/app/charts/hooks/defaultPlotDimensions.d.ts +13 -0
  105. package/dist/app/charts/hooks/defaultPlotDimensions.d.ts.map +1 -0
  106. package/dist/app/charts/hooks/defaultPlotDimensions.js +23 -0
  107. package/dist/app/charts/hooks/defaultPlotDimensions.js.map +1 -0
  108. package/dist/app/charts/hooks/defaultTooltipValues.d.ts +9 -0
  109. package/dist/app/charts/hooks/defaultTooltipValues.d.ts.map +1 -0
  110. package/dist/app/charts/hooks/defaultTooltipValues.js +21 -0
  111. package/dist/app/charts/hooks/defaultTooltipValues.js.map +1 -0
  112. package/dist/app/charts/hooks/defaultUseChartValues.d.ts +14 -0
  113. package/dist/app/charts/hooks/defaultUseChartValues.d.ts.map +1 -0
  114. package/dist/app/charts/hooks/defaultUseChartValues.js +30 -0
  115. package/dist/app/charts/hooks/defaultUseChartValues.js.map +1 -0
  116. package/dist/app/charts/hooks/useAxes.d.ts +49 -36
  117. package/dist/app/charts/hooks/useAxes.d.ts.map +1 -0
  118. package/dist/app/charts/hooks/useAxes.js +16 -176
  119. package/dist/app/charts/hooks/useAxes.js.map +1 -1
  120. package/dist/app/charts/hooks/useCanvasSurface.d.ts +25 -0
  121. package/dist/app/charts/hooks/useCanvasSurface.d.ts.map +1 -0
  122. package/dist/app/charts/hooks/useCanvasSurface.js +18 -0
  123. package/dist/app/charts/hooks/useCanvasSurface.js.map +1 -0
  124. package/dist/app/charts/hooks/useChart.d.ts +30 -44
  125. package/dist/app/charts/hooks/useChart.d.ts.map +1 -0
  126. package/dist/app/charts/hooks/useChart.js +26 -48
  127. package/dist/app/charts/hooks/useChart.js.map +1 -1
  128. package/dist/app/charts/hooks/useDataSource.d.ts +68 -0
  129. package/dist/app/charts/hooks/useDataSource.d.ts.map +1 -0
  130. package/dist/app/charts/hooks/useDataSource.js +63 -0
  131. package/dist/app/charts/hooks/useDataSource.js.map +1 -0
  132. package/dist/app/charts/hooks/useHoveredSeries.d.ts +25 -0
  133. package/dist/app/charts/hooks/useHoveredSeries.d.ts.map +1 -0
  134. package/dist/app/charts/hooks/useHoveredSeries.js +15 -0
  135. package/dist/app/charts/hooks/useHoveredSeries.js.map +1 -0
  136. package/dist/app/charts/hooks/useMouse.d.ts +46 -22
  137. package/dist/app/charts/hooks/useMouse.d.ts.map +1 -0
  138. package/dist/app/charts/hooks/useMouse.js +12 -56
  139. package/dist/app/charts/hooks/useMouse.js.map +1 -1
  140. package/dist/app/charts/hooks/usePlotDimensions.d.ts +25 -13
  141. package/dist/app/charts/hooks/usePlotDimensions.d.ts.map +1 -0
  142. package/dist/app/charts/hooks/usePlotDimensions.js +6 -62
  143. package/dist/app/charts/hooks/usePlotDimensions.js.map +1 -1
  144. package/dist/app/charts/hooks/useTooltip.d.ts +24 -26
  145. package/dist/app/charts/hooks/useTooltip.d.ts.map +1 -0
  146. package/dist/app/charts/hooks/useTooltip.js +12 -42
  147. package/dist/app/charts/hooks/useTooltip.js.map +1 -1
  148. package/dist/app/charts/index.d.ts +66 -0
  149. package/dist/app/charts/index.d.ts.map +1 -0
  150. package/dist/app/charts/index.js +87 -0
  151. package/dist/app/charts/index.js.map +1 -0
  152. package/dist/app/charts/legends/Legend.d.ts +33 -12
  153. package/dist/app/charts/legends/Legend.d.ts.map +1 -0
  154. package/dist/app/charts/legends/Legend.js +138 -379
  155. package/dist/app/charts/legends/Legend.js.map +1 -1
  156. package/dist/app/charts/legends/constants.d.ts +19 -0
  157. package/dist/app/charts/legends/constants.d.ts.map +1 -0
  158. package/dist/app/charts/legends/constants.js +34 -0
  159. package/dist/app/charts/legends/constants.js.map +1 -0
  160. package/dist/app/charts/observables/ChartData.d.ts +1 -0
  161. package/dist/app/charts/observables/ChartData.d.ts.map +1 -0
  162. package/dist/app/charts/observables/iterates.d.ts +13 -7
  163. package/dist/app/charts/observables/iterates.d.ts.map +1 -0
  164. package/dist/app/charts/observables/iterates.js +42 -9
  165. package/dist/app/charts/observables/iterates.js.map +1 -1
  166. package/dist/app/charts/observables/ordinals.d.ts +70 -12
  167. package/dist/app/charts/observables/ordinals.d.ts.map +1 -0
  168. package/dist/app/charts/observables/ordinals.js +127 -48
  169. package/dist/app/charts/observables/ordinals.js.map +1 -1
  170. package/dist/app/charts/observables/outliers.d.ts +18 -0
  171. package/dist/app/charts/observables/outliers.d.ts.map +1 -0
  172. package/dist/app/charts/observables/outliers.js +2 -0
  173. package/dist/app/charts/observables/outliers.js.map +1 -0
  174. package/dist/app/charts/plots/BarPlot.d.ts +87 -13
  175. package/dist/app/charts/plots/BarPlot.d.ts.map +1 -0
  176. package/dist/app/charts/plots/BarPlot.js +603 -356
  177. package/dist/app/charts/plots/BarPlot.js.map +1 -1
  178. package/dist/app/charts/plots/OutlierPlot.d.ts +123 -0
  179. package/dist/app/charts/plots/OutlierPlot.d.ts.map +1 -0
  180. package/dist/app/charts/plots/OutlierPlot.js +430 -0
  181. package/dist/app/charts/plots/OutlierPlot.js.map +1 -0
  182. package/dist/app/charts/plots/PoincarePlot.d.ts +92 -14
  183. package/dist/app/charts/plots/PoincarePlot.d.ts.map +1 -0
  184. package/dist/app/charts/plots/PoincarePlot.js +523 -364
  185. package/dist/app/charts/plots/PoincarePlot.js.map +1 -1
  186. package/dist/app/charts/plots/RasterPlot.d.ts +31 -10
  187. package/dist/app/charts/plots/RasterPlot.d.ts.map +1 -0
  188. package/dist/app/charts/plots/RasterPlot.js +198 -306
  189. package/dist/app/charts/plots/RasterPlot.js.map +1 -1
  190. package/dist/app/charts/plots/ScatterPlot.d.ts +77 -21
  191. package/dist/app/charts/plots/ScatterPlot.d.ts.map +1 -0
  192. package/dist/app/charts/plots/ScatterPlot.js +359 -302
  193. package/dist/app/charts/plots/ScatterPlot.js.map +1 -1
  194. package/dist/app/charts/plots/autoScaleYAxes.d.ts +43 -0
  195. package/dist/app/charts/plots/autoScaleYAxes.d.ts.map +1 -0
  196. package/dist/app/charts/plots/autoScaleYAxes.js +71 -0
  197. package/dist/app/charts/plots/autoScaleYAxes.js.map +1 -0
  198. package/dist/app/charts/plots/colorizedLine.d.ts +61 -0
  199. package/dist/app/charts/plots/colorizedLine.d.ts.map +1 -0
  200. package/dist/app/charts/plots/colorizedLine.js +157 -0
  201. package/dist/app/charts/plots/colorizedLine.js.map +1 -0
  202. package/dist/app/charts/plots/constants.d.ts +7 -0
  203. package/dist/app/charts/plots/constants.d.ts.map +1 -0
  204. package/dist/app/charts/plots/constants.js +11 -0
  205. package/dist/app/charts/plots/constants.js.map +1 -0
  206. package/dist/app/charts/plots/hitTesting.d.ts +88 -0
  207. package/dist/app/charts/plots/hitTesting.d.ts.map +1 -0
  208. package/dist/app/charts/plots/hitTesting.js +136 -0
  209. package/dist/app/charts/plots/hitTesting.js.map +1 -0
  210. package/dist/app/charts/plots/plot.d.ts +52 -16
  211. package/dist/app/charts/plots/plot.d.ts.map +1 -0
  212. package/dist/app/charts/plots/plot.js +108 -35
  213. package/dist/app/charts/plots/plot.js.map +1 -1
  214. package/dist/app/charts/plots/useCanvasZoomPan.d.ts +119 -0
  215. package/dist/app/charts/plots/useCanvasZoomPan.d.ts.map +1 -0
  216. package/dist/app/charts/plots/useCanvasZoomPan.js +113 -0
  217. package/dist/app/charts/plots/useCanvasZoomPan.js.map +1 -0
  218. package/dist/app/charts/plots/useStreamingTimeAxes.d.ts +103 -0
  219. package/dist/app/charts/plots/useStreamingTimeAxes.d.ts.map +1 -0
  220. package/dist/app/charts/plots/useStreamingTimeAxes.js +257 -0
  221. package/dist/app/charts/plots/useStreamingTimeAxes.js.map +1 -0
  222. package/dist/app/charts/series/baseSeries.d.ts +60 -8
  223. package/dist/app/charts/series/baseSeries.d.ts.map +1 -0
  224. package/dist/app/charts/series/baseSeries.js +53 -8
  225. package/dist/app/charts/series/baseSeries.js.map +1 -1
  226. package/dist/app/charts/series/iterateSeries.d.ts +9 -8
  227. package/dist/app/charts/series/iterateSeries.d.ts.map +1 -0
  228. package/dist/app/charts/series/iterateSeries.js +7 -7
  229. package/dist/app/charts/series/iterateSeries.js.map +1 -1
  230. package/dist/app/charts/series/ordinalSeries.d.ts +27 -13
  231. package/dist/app/charts/series/ordinalSeries.d.ts.map +1 -0
  232. package/dist/app/charts/series/ordinalSeries.js +29 -15
  233. package/dist/app/charts/series/ordinalSeries.js.map +1 -1
  234. package/dist/app/charts/series/outlierSeries.d.ts +142 -0
  235. package/dist/app/charts/series/outlierSeries.d.ts.map +1 -0
  236. package/dist/app/charts/series/outlierSeries.js +82 -0
  237. package/dist/app/charts/series/outlierSeries.js.map +1 -0
  238. package/dist/app/charts/series/timeSeries.d.ts +13 -9
  239. package/dist/app/charts/series/timeSeries.d.ts.map +1 -0
  240. package/dist/app/charts/series/timeSeries.js +6 -3
  241. package/dist/app/charts/series/timeSeries.js.map +1 -1
  242. package/dist/app/charts/series/timeSeriesChartData.d.ts +18 -10
  243. package/dist/app/charts/series/timeSeriesChartData.d.ts.map +1 -0
  244. package/dist/app/charts/series/timeSeriesChartData.js +28 -14
  245. package/dist/app/charts/series/timeSeriesChartData.js.map +1 -1
  246. package/dist/app/charts/styling/barPlotStyle.d.ts +46 -2
  247. package/dist/app/charts/styling/barPlotStyle.d.ts.map +1 -0
  248. package/dist/app/charts/styling/barPlotStyle.js +37 -3
  249. package/dist/app/charts/styling/barPlotStyle.js.map +1 -1
  250. package/dist/app/charts/styling/canvasStyle.d.ts +53 -0
  251. package/dist/app/charts/styling/canvasStyle.d.ts.map +1 -0
  252. package/dist/app/charts/styling/canvasStyle.js +71 -0
  253. package/dist/app/charts/styling/canvasStyle.js.map +1 -0
  254. package/dist/app/charts/styling/margins.d.ts +21 -2
  255. package/dist/app/charts/styling/margins.d.ts.map +1 -0
  256. package/dist/app/charts/styling/margins.js +25 -4
  257. package/dist/app/charts/styling/margins.js.map +1 -1
  258. package/dist/app/charts/styling/svgStyle.d.ts +10 -56
  259. package/dist/app/charts/styling/svgStyle.d.ts.map +1 -0
  260. package/dist/app/charts/styling/svgStyle.js +3 -78
  261. package/dist/app/charts/styling/svgStyle.js.map +1 -1
  262. package/dist/app/charts/subscriptions/viewDrivers.d.ts +124 -0
  263. package/dist/app/charts/subscriptions/viewDrivers.d.ts.map +1 -0
  264. package/dist/app/charts/subscriptions/viewDrivers.js +338 -0
  265. package/dist/app/charts/subscriptions/viewDrivers.js.map +1 -0
  266. package/dist/app/charts/tooltips/BarPlotTooltipContent.d.ts +12 -78
  267. package/dist/app/charts/tooltips/BarPlotTooltipContent.d.ts.map +1 -0
  268. package/dist/app/charts/tooltips/BarPlotTooltipContent.js +65 -257
  269. package/dist/app/charts/tooltips/BarPlotTooltipContent.js.map +1 -1
  270. package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.d.ts +9 -0
  271. package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.d.ts.map +1 -0
  272. package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.js +16 -0
  273. package/dist/app/charts/tooltips/DefaultOutlierTooltipContent.js.map +1 -0
  274. package/dist/app/charts/tooltips/OutlierPlotTooltipContent.d.ts +30 -0
  275. package/dist/app/charts/tooltips/OutlierPlotTooltipContent.d.ts.map +1 -0
  276. package/dist/app/charts/tooltips/OutlierPlotTooltipContent.js +26 -0
  277. package/dist/app/charts/tooltips/OutlierPlotTooltipContent.js.map +1 -0
  278. package/dist/app/charts/tooltips/PoincarePlotTooltipContent.d.ts +22 -72
  279. package/dist/app/charts/tooltips/PoincarePlotTooltipContent.d.ts.map +1 -0
  280. package/dist/app/charts/tooltips/PoincarePlotTooltipContent.js +104 -171
  281. package/dist/app/charts/tooltips/PoincarePlotTooltipContent.js.map +1 -1
  282. package/dist/app/charts/tooltips/RasterPlotTooltipContent.d.ts +32 -8
  283. package/dist/app/charts/tooltips/RasterPlotTooltipContent.d.ts.map +1 -0
  284. package/dist/app/charts/tooltips/RasterPlotTooltipContent.js +62 -115
  285. package/dist/app/charts/tooltips/RasterPlotTooltipContent.js.map +1 -1
  286. package/dist/app/charts/tooltips/ScatterPlotTooltipContent.d.ts +39 -12
  287. package/dist/app/charts/tooltips/ScatterPlotTooltipContent.d.ts.map +1 -0
  288. package/dist/app/charts/tooltips/ScatterPlotTooltipContent.js +162 -134
  289. package/dist/app/charts/tooltips/ScatterPlotTooltipContent.js.map +1 -1
  290. package/dist/app/charts/tooltips/Tooltip.d.ts +27 -32
  291. package/dist/app/charts/tooltips/Tooltip.d.ts.map +1 -0
  292. package/dist/app/charts/tooltips/Tooltip.js +37 -81
  293. package/dist/app/charts/tooltips/Tooltip.js.map +1 -1
  294. package/dist/app/charts/tooltips/TooltipContent.d.ts +81 -0
  295. package/dist/app/charts/tooltips/TooltipContent.d.ts.map +1 -0
  296. package/dist/app/charts/tooltips/TooltipContent.js +99 -0
  297. package/dist/app/charts/tooltips/TooltipContent.js.map +1 -0
  298. package/dist/app/charts/tooltips/tooltipUtils.d.ts +186 -36
  299. package/dist/app/charts/tooltips/tooltipUtils.d.ts.map +1 -0
  300. package/dist/app/charts/tooltips/tooltipUtils.js +277 -48
  301. package/dist/app/charts/tooltips/tooltipUtils.js.map +1 -1
  302. package/dist/app/charts/tooltips/useOutlierTooltip.d.ts +59 -0
  303. package/dist/app/charts/tooltips/useOutlierTooltip.d.ts.map +1 -0
  304. package/dist/app/charts/tooltips/useOutlierTooltip.js +16 -0
  305. package/dist/app/charts/tooltips/useOutlierTooltip.js.map +1 -0
  306. package/dist/app/charts/tooltips/useTooltipPlacement.d.ts +51 -0
  307. package/dist/app/charts/tooltips/useTooltipPlacement.d.ts.map +1 -0
  308. package/dist/app/charts/tooltips/useTooltipPlacement.js +52 -0
  309. package/dist/app/charts/tooltips/useTooltipPlacement.js.map +1 -0
  310. package/dist/app/charts/tooltips/useTooltipStyle.d.ts +11 -0
  311. package/dist/app/charts/tooltips/useTooltipStyle.d.ts.map +1 -0
  312. package/dist/app/charts/tooltips/useTooltipStyle.js +14 -0
  313. package/dist/app/charts/tooltips/useTooltipStyle.js.map +1 -0
  314. package/dist/app/charts/trackers/Tracker.d.ts +22 -6
  315. package/dist/app/charts/trackers/Tracker.d.ts.map +1 -0
  316. package/dist/app/charts/trackers/Tracker.js +36 -22
  317. package/dist/app/charts/trackers/Tracker.js.map +1 -1
  318. package/dist/app/charts/trackers/trackerUtils.d.ts +40 -18
  319. package/dist/app/charts/trackers/trackerUtils.d.ts.map +1 -0
  320. package/dist/app/charts/trackers/trackerUtils.js +213 -300
  321. package/dist/app/charts/trackers/trackerUtils.js.map +1 -1
  322. package/dist/app/charts/utils.d.ts +72 -33
  323. package/dist/app/charts/utils.d.ts.map +1 -0
  324. package/dist/app/charts/utils.js +87 -42
  325. package/dist/app/charts/utils.js.map +1 -1
  326. package/dist/index.d.ts +2 -45
  327. package/dist/index.d.ts.map +1 -0
  328. package/dist/index.js +2 -72
  329. package/dist/index.js.map +1 -1
  330. package/package.json +87 -46
  331. package/src/app/charts/Chart.tsx +132 -168
  332. package/src/app/charts/axes/AxesState.ts +27 -29
  333. package/src/app/charts/axes/AxisInterval.ts +57 -32
  334. package/src/app/charts/axes/BaseAxisRange.ts +47 -27
  335. package/src/app/charts/axes/ContinuousAxis.tsx +235 -39
  336. package/src/app/charts/axes/ContinuousAxisRange.ts +29 -11
  337. package/src/app/charts/axes/EmptyAxis.tsx +52 -17
  338. package/src/app/charts/axes/OrdinalAxis.tsx +54 -28
  339. package/src/app/charts/axes/OrdinalAxisRange.ts +96 -16
  340. package/src/app/charts/axes/autoScale.ts +244 -0
  341. package/src/app/charts/axes/axes.ts +954 -735
  342. package/src/app/charts/d3types.ts +42 -13
  343. package/src/app/charts/datasources/StreamingDataSource.ts +214 -0
  344. package/src/app/charts/datasources/iteratesDataSource.ts +122 -0
  345. package/src/app/charts/datasources/ordinalDataSource.ts +205 -0
  346. package/src/app/charts/datasources/outlierDataSource.ts +90 -0
  347. package/src/app/charts/datasources/timeSeriesDataSource.ts +133 -0
  348. package/src/app/charts/filters/regexFilter.ts +45 -5
  349. package/src/app/charts/hooks/AxesProvider.tsx +301 -0
  350. package/src/app/charts/hooks/CanvasSurfaceProvider.tsx +117 -0
  351. package/src/app/charts/hooks/ChartProvider.tsx +79 -0
  352. package/src/app/charts/hooks/InteractionProvider.tsx +88 -0
  353. package/src/app/charts/hooks/PlotDimensionsProvider.tsx +109 -0
  354. package/src/app/charts/hooks/defaultAxesValues.ts +40 -0
  355. package/src/app/charts/hooks/defaultMouseValues.ts +24 -0
  356. package/src/app/charts/hooks/defaultPlotDimensions.ts +27 -0
  357. package/src/app/charts/hooks/defaultTooltipValues.tsx +23 -0
  358. package/src/app/charts/hooks/defaultUseChartValues.tsx +36 -0
  359. package/src/app/charts/hooks/useAxes.tsx +60 -228
  360. package/src/app/charts/hooks/useCanvasSurface.tsx +35 -0
  361. package/src/app/charts/hooks/useChart.tsx +47 -106
  362. package/src/app/charts/hooks/useDataSource.tsx +106 -0
  363. package/src/app/charts/hooks/useHoveredSeries.tsx +33 -0
  364. package/src/app/charts/hooks/useMouse.tsx +58 -82
  365. package/src/app/charts/hooks/usePlotDimensions.tsx +25 -89
  366. package/src/app/charts/hooks/useTooltip.tsx +32 -63
  367. package/src/app/charts/index.ts +213 -0
  368. package/src/app/charts/legends/Legend.tsx +198 -479
  369. package/src/app/charts/legends/constants.ts +37 -0
  370. package/src/app/charts/observables/iterates.ts +32 -12
  371. package/src/app/charts/observables/ordinals.ts +141 -67
  372. package/src/app/charts/observables/outliers.ts +20 -0
  373. package/src/app/charts/plots/BarPlot.tsx +784 -666
  374. package/src/app/charts/plots/OutlierPlot.tsx +685 -0
  375. package/src/app/charts/plots/PoincarePlot.tsx +707 -489
  376. package/src/app/charts/plots/RasterPlot.tsx +253 -445
  377. package/src/app/charts/plots/ScatterPlot.tsx +480 -463
  378. package/src/app/charts/plots/autoScaleYAxes.ts +102 -0
  379. package/src/app/charts/plots/colorizedLine.ts +185 -0
  380. package/src/app/charts/plots/constants.ts +16 -0
  381. package/src/app/charts/plots/hitTesting.ts +198 -0
  382. package/src/app/charts/plots/plot.ts +138 -44
  383. package/src/app/charts/plots/useCanvasZoomPan.ts +240 -0
  384. package/src/app/charts/plots/useStreamingTimeAxes.ts +384 -0
  385. package/src/app/charts/series/baseSeries.ts +81 -14
  386. package/src/app/charts/series/iterateSeries.ts +8 -8
  387. package/src/app/charts/series/ordinalSeries.ts +35 -20
  388. package/src/app/charts/series/outlierSeries.ts +188 -0
  389. package/src/app/charts/series/timeSeries.ts +14 -12
  390. package/src/app/charts/series/timeSeriesChartData.ts +31 -17
  391. package/src/app/charts/styling/barPlotStyle.ts +48 -5
  392. package/src/app/charts/styling/canvasStyle.ts +86 -0
  393. package/src/app/charts/styling/margins.ts +28 -4
  394. package/src/app/charts/styling/svgStyle.ts +10 -91
  395. package/src/app/charts/subscriptions/viewDrivers.ts +447 -0
  396. package/src/app/charts/tooltips/BarPlotTooltipContent.tsx +156 -380
  397. package/src/app/charts/tooltips/DefaultOutlierTooltipContent.tsx +40 -0
  398. package/src/app/charts/tooltips/OutlierPlotTooltipContent.tsx +67 -0
  399. package/src/app/charts/tooltips/PoincarePlotTooltipContent.tsx +229 -292
  400. package/src/app/charts/tooltips/RasterPlotTooltipContent.tsx +164 -217
  401. package/src/app/charts/tooltips/ScatterPlotTooltipContent.tsx +373 -236
  402. package/src/app/charts/tooltips/Tooltip.tsx +58 -124
  403. package/src/app/charts/tooltips/TooltipContent.tsx +177 -0
  404. package/src/app/charts/tooltips/tooltipUtils.ts +359 -61
  405. package/src/app/charts/tooltips/useOutlierTooltip.tsx +68 -0
  406. package/src/app/charts/tooltips/useTooltipPlacement.ts +86 -0
  407. package/src/app/charts/tooltips/useTooltipStyle.ts +15 -0
  408. package/src/app/charts/trackers/Tracker.tsx +68 -33
  409. package/src/app/charts/trackers/trackerUtils.ts +263 -376
  410. package/src/app/charts/utils.ts +90 -48
  411. package/src/index.ts +2 -322
  412. package/dist/app/charts/axes/AxesState.test.d.ts +0 -1
  413. package/dist/app/charts/axes/AxesState.test.js +0 -30
  414. package/dist/app/charts/axes/AxesState.test.js.map +0 -1
  415. package/dist/app/charts/axes/AxisInterval.test.d.ts +0 -1
  416. package/dist/app/charts/axes/AxisInterval.test.js +0 -120
  417. package/dist/app/charts/axes/AxisInterval.test.js.map +0 -1
  418. package/dist/app/charts/axes/ContinuousAxisRange.test.d.ts +0 -1
  419. package/dist/app/charts/axes/ContinuousAxisRange.test.js +0 -47
  420. package/dist/app/charts/axes/ContinuousAxisRange.test.js.map +0 -1
  421. package/dist/app/charts/axes/OrdinalAxisRange.test.d.ts +0 -1
  422. package/dist/app/charts/axes/OrdinalAxisRange.test.js +0 -48
  423. package/dist/app/charts/axes/OrdinalAxisRange.test.js.map +0 -1
  424. package/dist/app/charts/filters/regexFilter.test.d.ts +0 -1
  425. package/dist/app/charts/filters/regexFilter.test.js +0 -11
  426. package/dist/app/charts/filters/regexFilter.test.js.map +0 -1
  427. package/dist/app/charts/hooks/useDataObservable.d.ts +0 -72
  428. package/dist/app/charts/hooks/useDataObservable.js +0 -74
  429. package/dist/app/charts/hooks/useDataObservable.js.map +0 -1
  430. package/dist/app/charts/hooks/useInitialData.d.ts +0 -36
  431. package/dist/app/charts/hooks/useInitialData.js +0 -28
  432. package/dist/app/charts/hooks/useInitialData.js.map +0 -1
  433. package/dist/app/charts/observables/iterates.test.d.ts +0 -1
  434. package/dist/app/charts/observables/iterates.test.js +0 -180
  435. package/dist/app/charts/observables/iterates.test.js.map +0 -1
  436. package/dist/app/charts/observables/ordinals.test.d.ts +0 -1
  437. package/dist/app/charts/observables/ordinals.test.js +0 -102
  438. package/dist/app/charts/observables/ordinals.test.js.map +0 -1
  439. package/dist/app/charts/series/datumSeries.test.d.ts +0 -1
  440. package/dist/app/charts/series/datumSeries.test.js +0 -50
  441. package/dist/app/charts/series/datumSeries.test.js.map +0 -1
  442. package/dist/app/charts/styling/margins.test.d.ts +0 -1
  443. package/dist/app/charts/styling/margins.test.js +0 -19
  444. package/dist/app/charts/styling/margins.test.js.map +0 -1
  445. package/dist/app/charts/subscriptions/subscription.test.d.ts +0 -1
  446. package/dist/app/charts/subscriptions/subscription.test.js +0 -395
  447. package/dist/app/charts/subscriptions/subscription.test.js.map +0 -1
  448. package/dist/app/charts/subscriptions/subscriptions.d.ts +0 -100
  449. package/dist/app/charts/subscriptions/subscriptions.js +0 -449
  450. package/dist/app/charts/subscriptions/subscriptions.js.map +0 -1
  451. package/src/app/charts/axes/AxesState.test.ts +0 -34
  452. package/src/app/charts/axes/AxisInterval.test.ts +0 -143
  453. package/src/app/charts/axes/ContinuousAxisRange.test.ts +0 -55
  454. package/src/app/charts/axes/OrdinalAxisRange.test.ts +0 -55
  455. package/src/app/charts/filters/regexFilter.test.ts +0 -13
  456. package/src/app/charts/hooks/useDataObservable.tsx +0 -170
  457. package/src/app/charts/hooks/useInitialData.tsx +0 -64
  458. package/src/app/charts/observables/iterates.test.ts +0 -201
  459. package/src/app/charts/observables/ordinals.test.ts +0 -135
  460. package/src/app/charts/series/datumSeries.test.ts +0 -60
  461. package/src/app/charts/styling/margins.test.ts +0 -22
  462. package/src/app/charts/subscriptions/subscription.test.ts +0 -499
  463. package/src/app/charts/subscriptions/subscriptions.ts +0 -635
@@ -8,18 +8,24 @@ export interface Margin {
8
8
  left: number
9
9
  }
10
10
 
11
+ /**
12
+ * @return Margins of 0 on every side
13
+ */
11
14
  export function noMargins(): Margin {
12
15
  return {top: 0, bottom: 0, left: 0, right: 0}
13
16
  }
14
17
 
18
+ /**
19
+ * A width and height (in pixels)
20
+ */
15
21
  export interface Dimensions {
16
22
  readonly width: number
17
23
  readonly height: number
18
24
  }
19
25
 
20
26
  /**
21
- * Given the dimensions of the plot (width, height) based on the container's width and height,
22
- * and the plot's margins. Calculates the dimensions of the actual plot by subtracting the margins.
27
+ * Calculates the dimensions of the actual plot from the container's width and height, and the
28
+ * plot's margins, by subtracting the margins (never less than 0).
23
29
  * @param containerWidth The overall width of the container (plot and margins)
24
30
  * @param containerHeight The overall height of the container (plot and margins)
25
31
  * @param plotMargins The margins around the plot (top, bottom, left, right)
@@ -28,9 +34,15 @@ export interface Dimensions {
28
34
  * @see containerDimensionsFrom
29
35
  */
30
36
  export function plotDimensionsFrom(containerWidth: number, containerHeight: number, plotMargins: Margin): Dimensions {
37
+ // floor at zero -- margins larger than the container would otherwise produce negative
38
+ // width/height, which propagates into D3 scale ranges, tracker/tooltip clamping math, and
39
+ // canvas draw coordinates as silent garbage. Mirrors the same Math.max(0, ...) convention
40
+ // already used defensively at some (but not all) points of use, e.g. plot.ts's
41
+ // resizeCanvasTo/clipToArea -- clamping here makes Dimensions a non-negative invariant for
42
+ // every downstream consumer instead of relying on each one to remember to clamp itself.
31
43
  return {
32
- width: containerWidth - plotMargins.left - plotMargins.right,
33
- height: containerHeight - plotMargins.top - plotMargins.bottom
44
+ width: Math.max(0, containerWidth - plotMargins.left - plotMargins.right),
45
+ height: Math.max(0, containerHeight - plotMargins.top - plotMargins.bottom)
34
46
  }
35
47
  }
36
48
 
@@ -49,10 +61,22 @@ export function containerDimensionsFrom(plotDimensions: Dimensions, plotMargin:
49
61
  }
50
62
  }
51
63
 
64
+ /**
65
+ * Whether two dimensions have the same width and height
66
+ * @param dimension1 The first dimensions
67
+ * @param dimension2 The second dimensions
68
+ * @return `true` when the widths and heights are equal; `false` otherwise
69
+ */
52
70
  export function dimensionsEqual(dimension1: Dimensions, dimension2: Dimensions) {
53
71
  return dimension1.height === dimension2.height && dimension1.width === dimension2.width
54
72
  }
55
73
 
74
+ /**
75
+ * Whether two dimensions differ in width or height (the negation of {@link dimensionsEqual})
76
+ * @param dimension1 The first dimensions
77
+ * @param dimension2 The second dimensions
78
+ * @return `true` when the widths or heights differ; `false` otherwise
79
+ */
56
80
  export function dimensionsNotEqual(dimension1: Dimensions, dimension2: Dimensions) {
57
81
  return !dimensionsEqual(dimension1, dimension2)
58
82
  }
@@ -1,118 +1,37 @@
1
- import * as d3 from "d3";
2
- import {BaseType} from "d3";
3
-
1
+ /**
2
+ * CSS style properties for the chart's container element (the canvas -- named for the SVG
3
+ * element it used to be)
4
+ */
4
5
  export interface SvgStyle {
5
6
  height?: string | number;
6
7
  width?: string | number;
7
8
  outline?: string;
8
9
 
9
- [propName: string]: any;
10
+ [propName: string]: string | number | undefined;
10
11
  }
11
12
 
13
+ /**
14
+ * The default container style: full width, anchored at the top left
15
+ */
12
16
  export const initialSvgStyle: SvgStyle = {
13
17
  width: '100%',
14
- // display: "inline-block",
15
- // position: "floating",
16
18
  top: 0,
17
19
  left: 0
18
- };
19
-
20
- /**
21
- * Grabs the client-width of the svg element, or 1 if the svg element hasn't yet
22
- * been initialized. The client-width is a read-only property returns the width of
23
- * the html element, including horizontal padding and borders, as an integer. The reason
24
- * that we return 1 when the svg element hasn't yet been initialized, is so that the
25
- * aspect (width / height) is 1.
26
- * @param {SVGElement | null} svg The svg element
27
- * @return {number} The client width of the svg
28
- */
29
- export function grabWidth(svg: SVGElement | null): number {
30
- return svg !== null ? svg.clientWidth : 1;
31
20
  }
32
21
 
33
22
  /**
34
- * Grabs the client-height of the svg element, or 1 if the svg element hasn't yet
35
- * been initialized. The client-height is a read-only property returns the height of
36
- * the html element, including vertical padding and borders, as an integer. The reason
37
- * that we return 1 when the svg element hasn't yet been initialized, is so that the
38
- * aspect (width / height) is 1.
39
- * @param {SVGElement | null} svg The svg element
40
- * @return {number} The client height of the svg
23
+ * The style of a stroke (used by the bar plot's styles)
41
24
  */
42
- export function grabHeight(svg: SVGElement | null): number {
43
- return svg !== null ? svg.clientHeight : 1;
44
- }
45
-
46
-
47
- export const STROKE_COLOR: string = "stroke"
48
- export const STROKE_WIDTH: string = "stroke-width"
49
- export const STROKE_OPACITY: string = "stroke-opacity"
50
-
51
25
  export interface SvgStrokeStyle {
52
26
  readonly color: string
53
27
  readonly width: number
54
28
  readonly opacity: number
55
29
  }
56
30
 
57
- export function updateSvgStrokeColor(current: SvgStrokeStyle, color: string) {
58
- return {...current, color};
59
- }
60
-
61
- export function updateSvgStrokeWidth(current: SvgStrokeStyle, width: number) {
62
- return {...current, width};
63
- }
64
-
65
- export function updateSvgStrokeOpacity(current: SvgStrokeStyle, opacity: number) {
66
- return {...current, opacity};
67
- }
68
-
69
31
  /**
70
- *
71
- * @param style
72
- * @param selection
73
- * @template E The SVG element (e.g. SVGRectElement, SVGLineElement, etc)
74
- * @template D The datum type
75
- * @template The SVG G element
32
+ * The style of a fill (used by the bar plot's styles)
76
33
  */
77
- export function applyStrokeStylesTo<E extends BaseType, D, G extends BaseType = SVGGElement>(
78
- selection: d3.Selection<E, D, G, any>,
79
- style: Partial<SvgStrokeStyle>
80
- ): d3.Selection<E, D, G, any> {
81
- if (style.color !== undefined) selection.style(STROKE_COLOR, style.color)
82
- if (style.width !== undefined) selection.style(STROKE_WIDTH, style.width)
83
- if (style.opacity !== undefined) selection.style(STROKE_OPACITY, style.opacity)
84
- return selection
85
- }
86
-
87
- const FILL_COLOR: string = "fill"
88
- const FILL_OPACITY: string = "fill-opacity"
89
-
90
34
  export interface SvgFillStyle {
91
35
  readonly color: string
92
36
  readonly opacity: number
93
37
  }
94
-
95
- export function updateSvgFillColor(current: SvgFillStyle, color: string): SvgFillStyle {
96
- return {...current, color}
97
- }
98
-
99
- export function updateSvgFillOpacity(current: SvgFillStyle, opacity: number): SvgFillStyle {
100
- return {...current, opacity}
101
- }
102
-
103
- /**
104
- *
105
- * @param style
106
- * @param selection
107
- * @template E The SVG element (e.g. SVGRectElement, SVGLineElement, etc)
108
- * @template D The datum type
109
- * @template The SVG G element
110
- */
111
- export function applyFillStylesTo<E extends BaseType, D, G extends BaseType = SVGGElement>(
112
- selection: d3.Selection<E, D, G, any>,
113
- style: Partial<SvgFillStyle>
114
- ): d3.Selection<E, D, G, any> {
115
- if (style.color !== undefined) selection.style(FILL_COLOR, style.color)
116
- if (style.opacity !== undefined) selection.style(FILL_OPACITY, style.opacity)
117
- return selection
118
- }
@@ -0,0 +1,447 @@
1
+ import {interval, type Observable, type OperatorFunction, Subscription} from "rxjs";
2
+ import {bufferCount, bufferTime, map, mergeAll, mergeWith} from "rxjs/operators";
3
+ import {continuousAxisRanges, type ContinuousNumericAxis} from "../axes/axes";
4
+ import {AxesState} from "../axes/AxesState";
5
+ import {ContinuousAxisRange} from "../axes/ContinuousAxisRange";
6
+ import type {AxesAssignment} from "../plots/plot";
7
+ import type {ChartData} from "../observables/ChartData";
8
+ import type {TimeSeriesChartData} from "../series/timeSeriesChartData";
9
+ import type {OutlierChartData} from "../observables/outliers";
10
+ import type {OrdinalChartData} from "../observables/ordinals";
11
+ import type {IterateChartData} from "../observables/iterates";
12
+ import type {StreamingDataSource} from "../datasources/StreamingDataSource";
13
+ import {currentTimesByGroup, type TimeGroupFor} from "../datasources/timeSeriesDataSource";
14
+ import {iteratesCurrentTime} from "../datasources/iteratesDataSource";
15
+
16
+ /*
17
+ * View drivers: the *view* half of a streaming plot.
18
+ *
19
+ * A {@link StreamingDataSource} (owned by the application) ingests the stream and keeps the series.
20
+ * A view driver (owned by one mounted plot) listens to the source's `chartDataUpdatesObservable` and keeps that plot's
21
+ * view in step with the data -- advancing the visible time-window (auto-scroll, cadence) and asking
22
+ * the plot to redraw. A plot creates its driver when it mounts and *always* unsubscribes it when it
23
+ * unmounts. Nothing here ever outlives the plot that created it, and nothing here ever mutates the
24
+ * series, so there is never a reason to keep a driver alive across a remount, adopt one, or defer
25
+ * its teardown.
26
+ *
27
+ * (Before v2, a plot's single subscription did both the ingestion and the view work, which tied
28
+ * the data's lifetime to the plot's -- see the data sources for the ingestion half.)
29
+ */
30
+
31
+ /**
32
+ * The behavior of the time window when data is added to the chart: `SCROLL` slides the window
33
+ * forward (keeping its width) as new data passes its end; `SQUEEZE` keeps the window's start
34
+ * pinned and widens it instead.
35
+ * Note: a const object rather than an enum, to support `erasableSyntaxOnly`
36
+ */
37
+ export const TimeWindowBehavior = {
38
+ SCROLL: "SCROLL",
39
+ SQUEEZE: "SQUEEZE"
40
+ } as const
41
+
42
+ export type TimeWindowBehavior = (typeof TimeWindowBehavior)[keyof typeof TimeWindowBehavior];
43
+
44
+ /**
45
+ * The part of a data source a view driver needs
46
+ */
47
+ export type ViewDriverSource<CD extends ChartData> = Pick<StreamingDataSource<CD, unknown>, 'chartDataUpdatesObservable' | 'latestTime'>
48
+
49
+ /**
50
+ * Batches the source's updates for rendering. When the source's own emission period is known,
51
+ * batches by a fixed count (`windowingTime / dataUpdatePeriod`) rather than by wall-clock time:
52
+ * `bufferTime` and the source's own timer are two independent clocks, so ordinary timer jitter can
53
+ * shift a tick across a buffer boundary, making the number of ticks per flush vary and the
54
+ * auto-scroll uneven. Counting emissions directly is immune to that jitter.
55
+ * @param windowingTime The time (ms) over which to batch updates
56
+ * @param dataUpdatePeriod The period (ms) at which the source emits, when known
57
+ * @return The batching operator
58
+ */
59
+ function renderBatching<CD>(windowingTime: number, dataUpdatePeriod?: number): OperatorFunction<CD, Array<CD>> {
60
+ return dataUpdatePeriod !== undefined && dataUpdatePeriod > 0 ?
61
+ bufferCount<CD>(Math.max(1, Math.round(windowingTime / dataUpdatePeriod))) :
62
+ bufferTime<CD>(windowingTime)
63
+ }
64
+
65
+ /**
66
+ * Advances the visible window for the specified axis (in place, within `timesWindows`) so its
67
+ * right edge sits at `targetTime`, preserving the window's current width (but never starting
68
+ * before 0, in which case the window stays at [0, width] until the time passes its width) -- but only once
69
+ * `targetTime` actually exceeds the window's current right edge. This gate is what lets a user
70
+ * pan/zoom the window ahead of the current time and watch the data catch up to it before scrolling
71
+ * resumes. Leaves `.original` untouched (zoom math is incremental, so it doesn't depend on it).
72
+ * @param timesWindows A `map(axis_id -> range)` updated in place
73
+ * @param axisId The axis to advance
74
+ * @param targetTime The time the axis's right edge should advance to
75
+ */
76
+ function advanceAxisRangeInMapTo(timesWindows: Map<string, ContinuousAxisRange>, axisId: string, targetTime: number): void {
77
+ const range = timesWindows.get(axisId)
78
+ if (range === undefined) return
79
+ const [startTime, endTime] = range.current.asTuple()
80
+ if (endTime < targetTime) {
81
+ const timeWindow = endTime - startTime
82
+ timesWindows.set(axisId, range.update(Math.max(0, targetTime - timeWindow), Math.max(targetTime, timeWindow)))
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Advances a range to a target time when new data arrives: SCROLL slides the window (width
88
+ * preserved); SQUEEZE pins the window's start at `initialStart` so the window widens instead.
89
+ * @param range The range to advance
90
+ * @param targetTime The time the range's right edge should advance to
91
+ * @param timeWindowBehavior Whether to scroll or squeeze
92
+ * @param initialStart The pinned start time for SQUEEZE mode (ignored for SCROLL)
93
+ * @return The advanced range, with `.original` unchanged
94
+ */
95
+ function scrollOrSqueezeRangeTo(
96
+ range: ContinuousAxisRange,
97
+ targetTime: number,
98
+ timeWindowBehavior: TimeWindowBehavior,
99
+ initialStart?: number,
100
+ ): ContinuousAxisRange {
101
+ const [startTime, endTime] = range.current.asTuple()
102
+ const timeWindow = endTime - startTime
103
+ const newStart = timeWindowBehavior === TimeWindowBehavior.SQUEEZE && initialStart !== undefined ?
104
+ initialStart :
105
+ Math.max(0, targetTime - timeWindow)
106
+ return range.update(newStart, Math.max(targetTime, timeWindow))
107
+ }
108
+
109
+ /**
110
+ * @param axisAssignments The assignment of the series to their x- and y-axes
111
+ * @param xAxesState The current state of the x-axes (for the default x-axis)
112
+ * @return A {@link TimeGroupFor} that groups series by their assigned x-axis (or the default x-axis)
113
+ */
114
+ function xAxisGroupFor(axisAssignments: Map<string, AxesAssignment>, xAxesState: AxesState<ContinuousNumericAxis>): TimeGroupFor {
115
+ return name => axisAssignments.get(name)?.xAxis || xAxesState.axisDefaultId().getOrElse("")
116
+ }
117
+
118
+ /**
119
+ * Re-syncs every x-axis to the data's ground-truth time whenever the page becomes visible again.
120
+ * Browsers pause `requestAnimationFrame` and throttle timers for hidden pages (including a macOS
121
+ * Spaces switch), and the cadence and data timers don't resume in lockstep, so without this an
122
+ * axis can lag behind until whichever clock fell behind organically catches up.
123
+ * @param dataSource The data source (for the data's ground-truth time)
124
+ * @param xAxesState The current state of the x-axes
125
+ * @param timesWindows A `map(axis_id -> range)` of the x-axes' windows, updated in place
126
+ * @param setCurrentTime Records the current time for an axis
127
+ * @param updateTimingAndPlot Redraws the plot for the (advanced) time-windows
128
+ * @return The teardown for the listener, to add to the driver's subscription
129
+ */
130
+ function resyncOnVisible(
131
+ dataSource: ViewDriverSource<ChartData>,
132
+ xAxesState: AxesState<ContinuousNumericAxis>,
133
+ timesWindows: Map<string, ContinuousAxisRange>,
134
+ setCurrentTime: (axisId: string, end: number) => void,
135
+ updateTimingAndPlot: (ranges: Map<string, ContinuousAxisRange>) => void,
136
+ ): () => void {
137
+ if (typeof document === 'undefined') return () => {
138
+ }
139
+ const resyncAxesOnVisible = (): void => {
140
+ if (document.visibilityState !== 'visible') return
141
+ const groundTruthTime = dataSource.latestTime()
142
+ if (!isFinite(groundTruthTime)) return
143
+ xAxesState.axisIds().forEach(axisId => {
144
+ advanceAxisRangeInMapTo(timesWindows, axisId, groundTruthTime)
145
+ setCurrentTime(axisId, groundTruthTime)
146
+ })
147
+ updateTimingAndPlot(timesWindows)
148
+ }
149
+ document.addEventListener('visibilitychange', resyncAxesOnVisible)
150
+ return () => document.removeEventListener('visibilitychange', resyncAxesOnVisible)
151
+ }
152
+
153
+ /**
154
+ * Marks a cadence tick in a view driver's stream of updates (rather than disguising the tick as an
155
+ * empty chunk of chart data)
156
+ */
157
+ const CADENCE_TICK = Symbol('cadence-tick')
158
+ type CadenceTick = typeof CADENCE_TICK
159
+
160
+ /**
161
+ * The cadence ticks merged, unbuffered, with the batched data updates. Cadence ticks must not go
162
+ * through the render batching, or each batch would deliver its cadence ticks in one burst,
163
+ * collapsing the smooth per-tick scroll down to the batch rate. (The ticks carry no time: the
164
+ * driver projects the stream time from its own wall-clock anchor, so throttled ticks don't make it
165
+ * fall permanently behind.)
166
+ * @param updates$ The data source's updates
167
+ * @param windowingTime The time (ms) over which the data updates are batched
168
+ * @param cadencePeriod The time (ms) between cadence ticks
169
+ * @return The data updates (each batch flattened back into single updates), merged with the
170
+ * cadence ticks
171
+ */
172
+ function withCadence<CD>(updates$: Observable<CD>, windowingTime: number, cadencePeriod: number): Observable<CD | CadenceTick> {
173
+ const cadence = interval(cadencePeriod).pipe(map((): CadenceTick => CADENCE_TICK))
174
+ return updates$.pipe(
175
+ bufferTime<CD>(windowingTime),
176
+ mergeAll(),
177
+ mergeWith(cadence) as OperatorFunction<CD, CD | CadenceTick>
178
+ )
179
+ }
180
+
181
+ /**
182
+ * Tracks the best-known stream time and when it was measured, so a cadence tick can project the
183
+ * current stream time as `knownTime + (now - measuredAt)`. Seeded from the data source -- which
184
+ * kept ingesting while the plot was unmounted, so this is the true current time even right after
185
+ * a remount -- and corrected forward whenever real data overtakes the projection (but never
186
+ * backward, which would make cadence stutter by the data's processing latency on every tick).
187
+ * @param seedTime The best-known stream time to start from (`-Infinity` when there's no data yet)
188
+ * @return The anchor: `now()` projects the current stream time, `isKnown()` says whether there's a
189
+ * stream time to project from, and `correctTo(time)` moves the anchor forward to a later real time
190
+ */
191
+ function cadenceAnchor(seedTime: number) {
192
+ let knownTime = seedTime
193
+ let measuredAt = performance.now()
194
+ const now = (): number => knownTime + (performance.now() - measuredAt)
195
+ return {
196
+ now,
197
+ isKnown: (): boolean => isFinite(knownTime),
198
+ correctTo: (realTime: number): void => {
199
+ if (realTime > now()) {
200
+ knownTime = realTime
201
+ measuredAt = performance.now()
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Gives the current time ("now") of each x-axis that a chunk of chart data has new points for
209
+ * @template CD The type of the chart data
210
+ */
211
+ export type AxisTimesFor<CD> = (data: CD) => Map<string, number>
212
+
213
+ /**
214
+ * The x-axes' times for time-series chart data: each axis's time is the latest time of the
215
+ * series assigned to it (see {@link currentTimesByGroup}), falling back to the chunk's latest time
216
+ * @param axisAssignments The assignment of the series to their x- and y-axes
217
+ * @param xAxesState The current state of the x-axes (for the default x-axis)
218
+ * @return The x-axes' times for a chunk of chart data
219
+ */
220
+ export function timeSeriesAxisTimes(
221
+ axisAssignments: Map<string, AxesAssignment>,
222
+ xAxesState: AxesState<ContinuousNumericAxis>,
223
+ ): AxisTimesFor<TimeSeriesChartData> {
224
+ const groupFor = xAxisGroupFor(axisAssignments, xAxesState)
225
+ return data => {
226
+ const groupTimes = currentTimesByGroup(data, groupFor)
227
+ const times = new Map<string, number>()
228
+ data.newPoints.forEach((_, name) => {
229
+ const axisId = groupFor(name)
230
+ times.set(axisId, groupTimes.get(axisId) || data.maxTime)
231
+ })
232
+ return times
233
+ }
234
+ }
235
+
236
+ /**
237
+ * The x-axes' times for outlier chart data: each axis's time is the time of the newest datum, of
238
+ * the series assigned to it, in the chunk
239
+ * @param axisAssignments The assignment of the series to their x- and y-axes
240
+ * @param xAxesState The current state of the x-axes (for the default x-axis)
241
+ * @return The x-axes' times for a chunk of chart data
242
+ * @template M The type of the outlier series' measures
243
+ */
244
+ export function outlierAxisTimes<M extends readonly number[]>(
245
+ axisAssignments: Map<string, AxesAssignment>,
246
+ xAxesState: AxesState<ContinuousNumericAxis>,
247
+ ): AxisTimesFor<OutlierChartData<M>> {
248
+ const groupFor = xAxisGroupFor(axisAssignments, xAxesState)
249
+ return data => {
250
+ const times = new Map<string, number>()
251
+ data.newPoints.forEach((newData, name) => {
252
+ const axisId = groupFor(name)
253
+ let time = times.get(axisId) ?? -Infinity
254
+ for (const datum of newData) time = Math.max(time, datum.datum.x)
255
+ if (Number.isFinite(time)) times.set(axisId, time)
256
+ })
257
+ return times
258
+ }
259
+ }
260
+
261
+ /**
262
+ * The options of a time-axis view driver (see {@link timeAxisViewDriverFor})
263
+ */
264
+ export interface TimeAxisViewDriverOptions {
265
+ /**
266
+ * The time (ms) over which updates are batched before redrawing
267
+ */
268
+ windowingTime: number
269
+ /**
270
+ * The period (ms) at which the source emits, when known (see {@link renderBatching}); not
271
+ * used with cadence
272
+ */
273
+ dataUpdatePeriod?: number
274
+ /**
275
+ * The time (ms) between cadence ticks, which advance the axes smoothly between data arrivals.
276
+ * Without one, the axes only advance as data arrives.
277
+ */
278
+ cadencePeriod?: number
279
+ /**
280
+ * Whether the time axes scroll or squeeze as data passes their ends (without cadence).
281
+ * Defaults to SCROLL.
282
+ */
283
+ timeWindowBehavior?: TimeWindowBehavior
284
+ /**
285
+ * The pinned start time for each axis, for SQUEEZE
286
+ */
287
+ initialTimes?: Map<string, number>
288
+ }
289
+
290
+ /**
291
+ * The view driver for a plot whose x-axes are time (the scatter, raster, and outlier plots): it
292
+ * advances each x-axis's window as the data's time passes its end, records each axis's current
293
+ * time, and asks the plot to redraw.
294
+ *
295
+ * Without cadence, each axis's window advances (SCROLL or SQUEEZE) as new data passes its end.
296
+ * With cadence, cadence ticks advance every axis's window smoothly between data arrivals, to the
297
+ * stream time projected from a wall-clock anchor; real data (treated as ground truth) re-syncs the
298
+ * axes, and corrects the anchor when cadence has fallen behind. The driver also catches the axes up
299
+ * to the data source's latest time when it starts (e.g. after a remount), and whenever the page
300
+ * becomes visible again.
301
+ * @param dataSource The data source whose updates drive the view
302
+ * @param xAxesState The current state of the x-axes
303
+ * @param axisTimesFor Gives the current time of each x-axis that a chunk of data has new points for
304
+ * (e.g. {@link timeSeriesAxisTimes} or {@link outlierAxisTimes})
305
+ * @param updateTimingAndPlot Redraws the plot for the (advanced) time-windows
306
+ * @param setCurrentTime Records the current time for an axis
307
+ * @param options The batching, cadence, and time-window behavior
308
+ * @return The driver's subscription, to unsubscribe when the plot unmounts
309
+ * @template CD The type of the chart data
310
+ */
311
+ export function timeAxisViewDriverFor<CD extends ChartData>(
312
+ dataSource: ViewDriverSource<CD>,
313
+ xAxesState: AxesState<ContinuousNumericAxis>,
314
+ axisTimesFor: AxisTimesFor<CD>,
315
+ updateTimingAndPlot: (ranges: Map<string, ContinuousAxisRange>) => void,
316
+ setCurrentTime: (axisId: string, end: number) => void,
317
+ options: TimeAxisViewDriverOptions,
318
+ ): Subscription {
319
+ const {
320
+ windowingTime,
321
+ dataUpdatePeriod,
322
+ cadencePeriod,
323
+ timeWindowBehavior = TimeWindowBehavior.SCROLL,
324
+ initialTimes = new Map<string, number>(),
325
+ } = options
326
+
327
+ // built ONCE, here, and advanced in place on every update: the plot hands this same map
328
+ // back to its pan/zoom handlers (via `updateTimingAndPlot`), so their mutations land here too
329
+ // rather than being discarded by a rebuild
330
+ const timesWindows = continuousAxisRanges(xAxesState.axes)
331
+
332
+ if (cadencePeriod === undefined) {
333
+ return dataSource.chartDataUpdatesObservable
334
+ .pipe(renderBatching<CD>(windowingTime, dataUpdatePeriod))
335
+ .subscribe(dataList => dataList.forEach(data => {
336
+ axisTimesFor(data).forEach((currentAxisTime, axisId) => {
337
+ // record the axis' "now" on every update -- not only once the window starts
338
+ // scrolling -- since the plot's zoom pivots on it while streaming: before the
339
+ // data reaches the window's end, there would otherwise be no "now" to pivot on,
340
+ // and the zoom would pivot on the window's right edge, possibly leaving the
341
+ // data off-screen
342
+ setCurrentTime(axisId, currentAxisTime)
343
+ const range = timesWindows.get(axisId)
344
+ if (range !== undefined && range.current.end < currentAxisTime) {
345
+ timesWindows.set(axisId, scrollOrSqueezeRangeTo(range, currentAxisTime, timeWindowBehavior, initialTimes.get(axisId)))
346
+ }
347
+ })
348
+ updateTimingAndPlot(timesWindows)
349
+ }))
350
+ }
351
+
352
+ const anchor = cadenceAnchor(dataSource.latestTime())
353
+ const catchUp = (): void => {
354
+ if (!anchor.isKnown()) return
355
+ xAxesState.axisIds().forEach(axisId => advanceAxisRangeInMapTo(timesWindows, axisId, anchor.now()))
356
+ updateTimingAndPlot(timesWindows)
357
+ }
358
+
359
+ // catch the axes up to the current stream time right away, rather than leaving them where they
360
+ // were restored to until the first tick arrives (which, right after a remount, can take a
361
+ // noticeable while and would show up as "pause, then jump")
362
+ catchUp()
363
+
364
+ const subscription = withCadence(dataSource.chartDataUpdatesObservable, windowingTime, cadencePeriod)
365
+ .subscribe(update => {
366
+ if (update === CADENCE_TICK) {
367
+ // a cadence tick: advance every axis to the projected stream time
368
+ const cadenceTime = anchor.now()
369
+ xAxesState.axisIds().forEach(axisId => {
370
+ advanceAxisRangeInMapTo(timesWindows, axisId, cadenceTime)
371
+ setCurrentTime(axisId, cadenceTime)
372
+ })
373
+ } else {
374
+ // real data: re-sync each axis to the data's own time, and correct the cadence
375
+ // anchor if the data has overtaken it
376
+ axisTimesFor(update).forEach((currentAxisTime, axisId) => {
377
+ advanceAxisRangeInMapTo(timesWindows, axisId, currentAxisTime)
378
+ anchor.correctTo(currentAxisTime)
379
+ })
380
+ }
381
+ updateTimingAndPlot(timesWindows)
382
+ })
383
+
384
+ subscription.add(resyncOnVisible(dataSource, xAxesState, timesWindows, setCurrentTime, updateTimingAndPlot))
385
+
386
+ // one more catch-up on the next paint frame, narrowing the gap until the first real tick
387
+ // (whose scheduling can lag right after a route change, while React commits the new tree)
388
+ const catchUpFrame = requestAnimationFrame(catchUp)
389
+ subscription.add(() => cancelAnimationFrame(catchUpFrame))
390
+
391
+ return subscription
392
+ }
393
+
394
+ /**
395
+ * The view driver for an ordinal (bar) plot: reports the chart-wide current time and asks the
396
+ * plot to redraw as new data arrives. (The stats are kept by the data source.) Unlike the
397
+ * time-series drivers, it has no axis ranges to advance: an ordinal plot's axes don't scroll as
398
+ * data arrives, so its axes' ranges change only through the plot's own zoom, pan, and resize.
399
+ * @param dataSource The data source whose updates drive the view
400
+ * @param windowingTime The time (ms) over which updates are batched before redrawing
401
+ * @param updateTimingAndPlot Redraws the plot (and reports the chart time)
402
+ * @param setCurrentTime Records the chart-wide current time
403
+ * @param dataUpdatePeriod The period (ms) at which the source emits, when known (see {@link renderBatching})
404
+ * @return The driver's subscription, to unsubscribe when the plot unmounts
405
+ */
406
+ export function ordinalViewDriverFor(
407
+ dataSource: ViewDriverSource<OrdinalChartData>,
408
+ windowingTime: number,
409
+ updateTimingAndPlot: () => void,
410
+ setCurrentTime: (currentTime: number) => void,
411
+ dataUpdatePeriod?: number,
412
+ ): Subscription {
413
+ return dataSource.chartDataUpdatesObservable
414
+ .pipe(renderBatching<OrdinalChartData>(windowingTime, dataUpdatePeriod))
415
+ .subscribe(dataList => dataList.forEach(data => {
416
+ if (data.newPoints.size > 0) setCurrentTime(data.stats.maxDatum.time.time || NaN)
417
+ updateTimingAndPlot()
418
+ }))
419
+ }
420
+
421
+ /**
422
+ * The view driver for an iterates (Poincaré) plot: reports the current time and asks the plot to
423
+ * redraw as new data arrives (once the plot has both an x-axis and a y-axis).
424
+ * @param dataSource The data source whose updates drive the view
425
+ * @param windowingTime The time (ms) over which updates are batched before redrawing
426
+ * @param xAxesState The current state of the x-axes
427
+ * @param yAxesState The current state of the y-axes
428
+ * @param updateRangesAndPlot Updates the axes' ranges, and redraws the plot
429
+ * @param updateCurrentTime Records the current time (see {@link iteratesCurrentTime})
430
+ * @return The driver's subscription, to unsubscribe when the plot unmounts
431
+ */
432
+ export function iteratesViewDriverFor(
433
+ dataSource: ViewDriverSource<IterateChartData>,
434
+ windowingTime: number,
435
+ xAxesState: AxesState<ContinuousNumericAxis>,
436
+ yAxesState: AxesState<ContinuousNumericAxis>,
437
+ updateRangesAndPlot: () => void,
438
+ updateCurrentTime: (time: number) => void,
439
+ ): Subscription {
440
+ return dataSource.chartDataUpdatesObservable
441
+ .pipe(bufferTime<IterateChartData>(windowingTime))
442
+ .subscribe(dataList => dataList.forEach(data => {
443
+ if (data.newPoints.size > 0) updateCurrentTime(iteratesCurrentTime(data))
444
+ // (the original only redrew once both a default x-axis and a default y-axis existed)
445
+ if (xAxesState.axes.size > 0 && yAxesState.axes.size > 0) updateRangesAndPlot()
446
+ }))
447
+ }