stream-charts 1.0.0 → 1.1.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 (271) hide show
  1. package/README.md +758 -345
  2. package/changes.md +10 -0
  3. package/dist/src/app/charts/Chart.d.ts +116 -87
  4. package/dist/src/app/charts/Chart.js +96 -101
  5. package/dist/src/app/charts/Chart.js.map +1 -1
  6. package/dist/src/app/charts/axes/AxesState.d.ts +64 -0
  7. package/dist/src/app/charts/axes/AxesState.js +97 -0
  8. package/dist/src/app/charts/axes/AxesState.js.map +1 -0
  9. package/dist/src/app/charts/axes/AxesState.test.js +30 -0
  10. package/dist/src/app/charts/axes/AxesState.test.js.map +1 -0
  11. package/dist/src/app/charts/axes/AxisInterval.d.ts +92 -0
  12. package/dist/src/app/charts/axes/AxisInterval.js +126 -0
  13. package/dist/src/app/charts/axes/AxisInterval.js.map +1 -0
  14. package/dist/src/app/charts/axes/AxisInterval.test.js +120 -0
  15. package/dist/src/app/charts/axes/AxisInterval.test.js.map +1 -0
  16. package/dist/src/app/charts/axes/BaseAxisRange.d.ts +83 -0
  17. package/dist/src/app/charts/axes/BaseAxisRange.js +58 -0
  18. package/dist/src/app/charts/axes/BaseAxisRange.js.map +1 -0
  19. package/dist/src/app/charts/axes/ContinuousAxis.d.ts +22 -0
  20. package/dist/src/app/charts/axes/ContinuousAxis.js +96 -0
  21. package/dist/src/app/charts/axes/ContinuousAxis.js.map +1 -0
  22. package/dist/src/app/charts/axes/ContinuousAxisRange.d.ts +59 -0
  23. package/dist/src/app/charts/axes/ContinuousAxisRange.js +84 -0
  24. package/dist/src/app/charts/axes/ContinuousAxisRange.js.map +1 -0
  25. package/dist/src/app/charts/axes/ContinuousAxisRange.test.js +47 -0
  26. package/dist/src/app/charts/axes/ContinuousAxisRange.test.js.map +1 -0
  27. package/dist/src/app/charts/axes/OrdinalAxis.d.ts +23 -0
  28. package/dist/src/app/charts/axes/OrdinalAxis.js +124 -0
  29. package/dist/src/app/charts/axes/OrdinalAxis.js.map +1 -0
  30. package/dist/src/app/charts/axes/OrdinalAxisRange.d.ts +69 -0
  31. package/dist/src/app/charts/axes/OrdinalAxisRange.js +100 -0
  32. package/dist/src/app/charts/axes/OrdinalAxisRange.js.map +1 -0
  33. package/dist/src/app/charts/axes/OrdinalAxisRange.test.js +48 -0
  34. package/dist/src/app/charts/axes/OrdinalAxisRange.test.js.map +1 -0
  35. package/dist/src/app/charts/axes/axes.d.ts +391 -0
  36. package/dist/src/app/charts/axes/axes.js +1046 -0
  37. package/dist/src/app/charts/axes/axes.js.map +1 -0
  38. package/dist/src/app/charts/d3types.d.ts +10 -10
  39. package/dist/src/app/charts/filters/regexFilter.d.ts +9 -0
  40. package/dist/src/app/charts/filters/regexFilter.js +18 -0
  41. package/dist/src/app/charts/filters/regexFilter.js.map +1 -0
  42. package/dist/src/app/charts/filters/regexFilter.test.d.ts +1 -0
  43. package/dist/src/app/charts/filters/regexFilter.test.js +11 -0
  44. package/dist/src/app/charts/filters/regexFilter.test.js.map +1 -0
  45. package/dist/src/app/charts/hooks/useAxes.d.ts +144 -0
  46. package/dist/src/app/charts/hooks/useAxes.js +187 -0
  47. package/dist/src/app/charts/hooks/useAxes.js.map +1 -0
  48. package/dist/src/app/charts/hooks/useChart.d.ts +30 -201
  49. package/dist/src/app/charts/hooks/useChart.js +33 -134
  50. package/dist/src/app/charts/hooks/useChart.js.map +1 -1
  51. package/dist/src/app/charts/hooks/useDataObservable.d.ts +74 -0
  52. package/dist/src/app/charts/hooks/useDataObservable.js +76 -0
  53. package/dist/src/app/charts/hooks/useDataObservable.js.map +1 -0
  54. package/dist/src/app/charts/hooks/useInitialData.d.ts +38 -0
  55. package/dist/src/app/charts/hooks/useInitialData.js +29 -0
  56. package/dist/src/app/charts/hooks/useInitialData.js.map +1 -0
  57. package/dist/src/app/charts/hooks/useMouse.d.ts +53 -0
  58. package/dist/src/app/charts/hooks/useMouse.js +65 -0
  59. package/dist/src/app/charts/hooks/useMouse.js.map +1 -0
  60. package/dist/src/app/charts/hooks/usePlotDimensions.d.ts +34 -0
  61. package/dist/src/app/charts/hooks/usePlotDimensions.js +73 -0
  62. package/dist/src/app/charts/hooks/usePlotDimensions.js.map +1 -0
  63. package/dist/src/app/charts/hooks/useTooltip.d.ts +64 -0
  64. package/dist/src/app/charts/hooks/useTooltip.js +52 -0
  65. package/dist/src/app/charts/hooks/useTooltip.js.map +1 -0
  66. package/dist/src/app/charts/observables/ChartData.d.ts +23 -0
  67. package/dist/src/app/charts/observables/ChartData.js +20 -0
  68. package/dist/src/app/charts/observables/ChartData.js.map +1 -0
  69. package/dist/src/app/charts/observables/iterates.d.ts +52 -0
  70. package/dist/src/app/charts/observables/iterates.js +121 -0
  71. package/dist/src/app/charts/observables/iterates.js.map +1 -0
  72. package/dist/src/app/charts/observables/iterates.test.d.ts +1 -0
  73. package/dist/src/app/charts/observables/iterates.test.js +180 -0
  74. package/dist/src/app/charts/observables/iterates.test.js.map +1 -0
  75. package/dist/src/app/charts/observables/ordinals.d.ts +75 -0
  76. package/dist/src/app/charts/observables/ordinals.js +141 -0
  77. package/dist/src/app/charts/observables/ordinals.js.map +1 -0
  78. package/dist/src/app/charts/observables/ordinals.test.d.ts +1 -0
  79. package/dist/src/app/charts/observables/ordinals.test.js +102 -0
  80. package/dist/src/app/charts/observables/ordinals.test.js.map +1 -0
  81. package/dist/src/app/charts/plots/BarPlot.d.ts +81 -0
  82. package/dist/src/app/charts/plots/BarPlot.js +557 -0
  83. package/dist/src/app/charts/plots/BarPlot.js.map +1 -0
  84. package/dist/src/app/charts/plots/PoincarePlot.d.ts +78 -0
  85. package/dist/src/app/charts/plots/PoincarePlot.js +504 -0
  86. package/dist/src/app/charts/plots/PoincarePlot.js.map +1 -0
  87. package/dist/src/app/charts/{RasterPlot.d.ts → plots/RasterPlot.d.ts} +1 -1
  88. package/dist/src/app/charts/{RasterPlot.js → plots/RasterPlot.js} +152 -133
  89. package/dist/src/app/charts/plots/RasterPlot.js.map +1 -0
  90. package/dist/src/app/charts/{ScatterPlot.d.ts → plots/ScatterPlot.d.ts} +10 -8
  91. package/dist/src/app/charts/plots/ScatterPlot.js +379 -0
  92. package/dist/src/app/charts/plots/ScatterPlot.js.map +1 -0
  93. package/dist/src/app/charts/{plot.d.ts → plots/plot.d.ts} +12 -14
  94. package/dist/src/app/charts/{plot.js → plots/plot.js} +19 -17
  95. package/dist/src/app/charts/plots/plot.js.map +1 -0
  96. package/dist/src/app/charts/series/baseSeries.d.ts +38 -0
  97. package/dist/src/app/charts/series/baseSeries.js +36 -0
  98. package/dist/src/app/charts/series/baseSeries.js.map +1 -0
  99. package/dist/src/app/charts/series/datumSeries.test.d.ts +1 -0
  100. package/dist/src/app/charts/series/datumSeries.test.js +50 -0
  101. package/dist/src/app/charts/series/datumSeries.test.js.map +1 -0
  102. package/dist/src/app/charts/series/iterateSeries.d.ts +42 -0
  103. package/dist/src/app/charts/series/iterateSeries.js +34 -0
  104. package/dist/src/app/charts/series/iterateSeries.js.map +1 -0
  105. package/dist/src/app/charts/series/ordinalSeries.d.ts +54 -0
  106. package/dist/src/app/charts/series/ordinalSeries.js +98 -0
  107. package/dist/src/app/charts/series/ordinalSeries.js.map +1 -0
  108. package/dist/src/app/charts/series/timeSeries.d.ts +30 -0
  109. package/dist/src/app/charts/series/timeSeries.js +19 -0
  110. package/dist/src/app/charts/series/timeSeries.js.map +1 -0
  111. package/dist/src/app/charts/{chartData.d.ts → series/timeSeriesChartData.d.ts} +11 -6
  112. package/dist/src/app/charts/series/timeSeriesChartData.js +32 -0
  113. package/dist/src/app/charts/series/timeSeriesChartData.js.map +1 -0
  114. package/dist/src/app/charts/styling/barPlotStyle.d.ts +41 -0
  115. package/dist/src/app/charts/styling/barPlotStyle.js +84 -0
  116. package/dist/src/app/charts/styling/barPlotStyle.js.map +1 -0
  117. package/dist/src/app/charts/{margins.d.ts → styling/margins.d.ts} +7 -5
  118. package/dist/src/app/charts/{margins.js → styling/margins.js} +19 -9
  119. package/dist/src/app/charts/styling/margins.js.map +1 -0
  120. package/dist/src/app/charts/styling/margins.test.d.ts +1 -0
  121. package/dist/src/app/charts/styling/margins.test.js +19 -0
  122. package/dist/src/app/charts/styling/margins.test.js.map +1 -0
  123. package/dist/src/app/charts/styling/svgStyle.d.ts +76 -0
  124. package/dist/src/app/charts/styling/svgStyle.js +84 -0
  125. package/dist/src/app/charts/styling/svgStyle.js.map +1 -0
  126. package/dist/src/app/charts/subscriptions/subscription.test.d.ts +1 -0
  127. package/dist/src/app/charts/subscriptions/subscription.test.js +395 -0
  128. package/dist/src/app/charts/subscriptions/subscription.test.js.map +1 -0
  129. package/dist/src/app/charts/subscriptions/subscriptions.d.ts +100 -0
  130. package/dist/src/app/charts/subscriptions/subscriptions.js +449 -0
  131. package/dist/src/app/charts/subscriptions/subscriptions.js.map +1 -0
  132. package/dist/src/app/charts/tooltips/BarPlotTooltipContent.d.ts +90 -0
  133. package/dist/src/app/charts/tooltips/BarPlotTooltipContent.js +302 -0
  134. package/dist/src/app/charts/tooltips/BarPlotTooltipContent.js.map +1 -0
  135. package/dist/src/app/charts/tooltips/PoincarePlotTooltipContent.d.ts +100 -0
  136. package/dist/src/app/charts/tooltips/PoincarePlotTooltipContent.js +190 -0
  137. package/dist/src/app/charts/tooltips/PoincarePlotTooltipContent.js.map +1 -0
  138. package/dist/src/app/charts/{RasterPlotTooltipContent.js → tooltips/RasterPlotTooltipContent.js} +40 -44
  139. package/dist/src/app/charts/tooltips/RasterPlotTooltipContent.js.map +1 -0
  140. package/dist/src/app/charts/tooltips/ScatterPlotTooltipContent.js +154 -0
  141. package/dist/src/app/charts/tooltips/ScatterPlotTooltipContent.js.map +1 -0
  142. package/dist/src/app/charts/{Tooltip.d.ts → tooltips/Tooltip.d.ts} +4 -2
  143. package/dist/src/app/charts/{Tooltip.js → tooltips/Tooltip.js} +23 -28
  144. package/dist/src/app/charts/tooltips/Tooltip.js.map +1 -0
  145. package/dist/src/app/charts/{tooltipUtils.d.ts → tooltips/tooltipUtils.d.ts} +17 -11
  146. package/dist/src/app/charts/{tooltipUtils.js → tooltips/tooltipUtils.js} +52 -25
  147. package/dist/src/app/charts/tooltips/tooltipUtils.js.map +1 -0
  148. package/dist/src/app/charts/{Tracker.d.ts → trackers/Tracker.d.ts} +6 -5
  149. package/dist/src/app/charts/trackers/Tracker.js +60 -0
  150. package/dist/src/app/charts/trackers/Tracker.js.map +1 -0
  151. package/dist/src/app/charts/{trackerUtils.d.ts → trackers/trackerUtils.d.ts} +13 -8
  152. package/dist/src/app/charts/trackers/trackerUtils.js +359 -0
  153. package/dist/src/app/charts/trackers/trackerUtils.js.map +1 -0
  154. package/dist/src/app/charts/utils.d.ts +22 -32
  155. package/dist/src/app/charts/utils.js +36 -37
  156. package/dist/src/app/charts/utils.js.map +1 -1
  157. package/dist/src/index.d.ts +48 -15
  158. package/dist/src/index.js +71 -15
  159. package/dist/src/index.js.map +1 -1
  160. package/package.json +30 -20
  161. package/src/app/charts/Chart.tsx +334 -0
  162. package/src/app/charts/axes/AxesState.test.ts +34 -0
  163. package/src/app/charts/axes/AxesState.ts +112 -0
  164. package/src/app/charts/axes/AxisInterval.test.ts +143 -0
  165. package/src/app/charts/axes/AxisInterval.ts +139 -0
  166. package/src/app/charts/axes/BaseAxisRange.ts +113 -0
  167. package/src/app/charts/axes/ContinuousAxis.tsx +192 -0
  168. package/src/app/charts/axes/ContinuousAxisRange.test.ts +55 -0
  169. package/src/app/charts/axes/ContinuousAxisRange.ts +96 -0
  170. package/src/app/charts/axes/OrdinalAxis.tsx +223 -0
  171. package/src/app/charts/axes/OrdinalAxisRange.test.ts +55 -0
  172. package/src/app/charts/axes/OrdinalAxisRange.ts +112 -0
  173. package/src/app/charts/axes/axes.ts +1569 -0
  174. package/src/app/charts/d3types.ts +16 -0
  175. package/src/app/charts/filters/regexFilter.test.ts +13 -0
  176. package/src/app/charts/filters/regexFilter.ts +17 -0
  177. package/src/app/charts/hooks/useAxes.tsx +341 -0
  178. package/src/app/charts/hooks/useChart.tsx +159 -0
  179. package/src/app/charts/hooks/useDataObservable.tsx +175 -0
  180. package/src/app/charts/hooks/useInitialData.tsx +65 -0
  181. package/src/app/charts/hooks/useMouse.tsx +125 -0
  182. package/src/app/charts/hooks/usePlotDimensions.tsx +120 -0
  183. package/src/app/charts/hooks/useTooltip.tsx +112 -0
  184. package/src/app/charts/observables/ChartData.ts +31 -0
  185. package/src/app/charts/observables/iterates.test.ts +201 -0
  186. package/src/app/charts/observables/iterates.ts +203 -0
  187. package/src/app/charts/observables/ordinals.test.ts +135 -0
  188. package/src/app/charts/observables/ordinals.ts +248 -0
  189. package/src/app/charts/plots/BarPlot.tsx +1088 -0
  190. package/src/app/charts/plots/PoincarePlot.tsx +832 -0
  191. package/src/app/charts/plots/RasterPlot.tsx +676 -0
  192. package/src/app/charts/plots/ScatterPlot.tsx +653 -0
  193. package/src/app/charts/plots/plot.ts +75 -0
  194. package/src/app/charts/series/baseSeries.ts +52 -0
  195. package/src/app/charts/series/datumSeries.test.ts +60 -0
  196. package/src/app/charts/series/iterateSeries.ts +56 -0
  197. package/src/app/charts/series/ordinalSeries.ts +164 -0
  198. package/src/app/charts/series/timeSeries.ts +40 -0
  199. package/src/app/charts/series/timeSeriesChartData.ts +68 -0
  200. package/src/app/charts/styling/barPlotStyle.ts +126 -0
  201. package/src/app/charts/styling/margins.test.ts +22 -0
  202. package/src/app/charts/styling/margins.ts +58 -0
  203. package/src/app/charts/styling/svgStyle.ts +118 -0
  204. package/src/app/charts/subscriptions/subscription.test.ts +499 -0
  205. package/src/app/charts/subscriptions/subscriptions.ts +635 -0
  206. package/src/app/charts/tooltips/BarPlotTooltipContent.tsx +440 -0
  207. package/src/app/charts/tooltips/PoincarePlotTooltipContent.tsx +352 -0
  208. package/src/app/charts/tooltips/RasterPlotTooltipContent.tsx +274 -0
  209. package/src/app/charts/tooltips/ScatterPlotTooltipContent.tsx +319 -0
  210. package/src/app/charts/tooltips/Tooltip.tsx +148 -0
  211. package/src/app/charts/tooltips/tooltipUtils.ts +216 -0
  212. package/src/app/charts/trackers/Tracker.tsx +129 -0
  213. package/src/app/charts/trackers/trackerUtils.ts +494 -0
  214. package/src/app/charts/utils.ts +109 -0
  215. package/dist/src/app/charts/CategoryAxis.d.ts +0 -20
  216. package/dist/src/app/charts/CategoryAxis.js +0 -112
  217. package/dist/src/app/charts/CategoryAxis.js.map +0 -1
  218. package/dist/src/app/charts/ContinuousAxis.d.ts +0 -16
  219. package/dist/src/app/charts/ContinuousAxis.js +0 -186
  220. package/dist/src/app/charts/ContinuousAxis.js.map +0 -1
  221. package/dist/src/app/charts/RasterPlot.js.map +0 -1
  222. package/dist/src/app/charts/RasterPlotTooltipContent.js.map +0 -1
  223. package/dist/src/app/charts/ScatterPlot.js +0 -351
  224. package/dist/src/app/charts/ScatterPlot.js.map +0 -1
  225. package/dist/src/app/charts/ScatterPlotTooltipContent.js +0 -163
  226. package/dist/src/app/charts/ScatterPlotTooltipContent.js.map +0 -1
  227. package/dist/src/app/charts/Tooltip.js.map +0 -1
  228. package/dist/src/app/charts/Tracker.js +0 -65
  229. package/dist/src/app/charts/Tracker.js.map +0 -1
  230. package/dist/src/app/charts/axes.d.ts +0 -132
  231. package/dist/src/app/charts/axes.js +0 -265
  232. package/dist/src/app/charts/axes.js.map +0 -1
  233. package/dist/src/app/charts/chartData.js +0 -32
  234. package/dist/src/app/charts/chartData.js.map +0 -1
  235. package/dist/src/app/charts/continuousAxisRangeFor.d.ts +0 -20
  236. package/dist/src/app/charts/continuousAxisRangeFor.js +0 -68
  237. package/dist/src/app/charts/continuousAxisRangeFor.js.map +0 -1
  238. package/dist/src/app/charts/datumSeries.d.ts +0 -59
  239. package/dist/src/app/charts/datumSeries.js +0 -55
  240. package/dist/src/app/charts/datumSeries.js.map +0 -1
  241. package/dist/src/app/charts/datumSeries.test.js +0 -50
  242. package/dist/src/app/charts/datumSeries.test.js.map +0 -1
  243. package/dist/src/app/charts/hooks/AxesState.d.ts +0 -37
  244. package/dist/src/app/charts/hooks/AxesState.js +0 -44
  245. package/dist/src/app/charts/hooks/AxesState.js.map +0 -1
  246. package/dist/src/app/charts/margins.js.map +0 -1
  247. package/dist/src/app/charts/margins.test.js +0 -14
  248. package/dist/src/app/charts/margins.test.js.map +0 -1
  249. package/dist/src/app/charts/plot.js.map +0 -1
  250. package/dist/src/app/charts/regexFilter.d.ts +0 -9
  251. package/dist/src/app/charts/regexFilter.js +0 -17
  252. package/dist/src/app/charts/regexFilter.js.map +0 -1
  253. package/dist/src/app/charts/regexFilter.test.js +0 -11
  254. package/dist/src/app/charts/regexFilter.test.js.map +0 -1
  255. package/dist/src/app/charts/subscriptions.d.ts +0 -43
  256. package/dist/src/app/charts/subscriptions.js +0 -213
  257. package/dist/src/app/charts/subscriptions.js.map +0 -1
  258. package/dist/src/app/charts/svgStyle.d.ts +0 -27
  259. package/dist/src/app/charts/svgStyle.js +0 -32
  260. package/dist/src/app/charts/svgStyle.js.map +0 -1
  261. package/dist/src/app/charts/timeRange.test.js +0 -54
  262. package/dist/src/app/charts/timeRange.test.js.map +0 -1
  263. package/dist/src/app/charts/tooltipUtils.js.map +0 -1
  264. package/dist/src/app/charts/trackerUtils.js +0 -130
  265. package/dist/src/app/charts/trackerUtils.js.map +0 -1
  266. /package/dist/src/app/charts/{datumSeries.test.d.ts → axes/AxesState.test.d.ts} +0 -0
  267. /package/dist/src/app/charts/{margins.test.d.ts → axes/AxisInterval.test.d.ts} +0 -0
  268. /package/dist/src/app/charts/{regexFilter.test.d.ts → axes/ContinuousAxisRange.test.d.ts} +0 -0
  269. /package/dist/src/app/charts/{timeRange.test.d.ts → axes/OrdinalAxisRange.test.d.ts} +0 -0
  270. /package/dist/src/app/charts/{RasterPlotTooltipContent.d.ts → tooltips/RasterPlotTooltipContent.d.ts} +0 -0
  271. /package/dist/src/app/charts/{ScatterPlotTooltipContent.d.ts → tooltips/ScatterPlotTooltipContent.d.ts} +0 -0
@@ -0,0 +1,112 @@
1
+ import {BaseAxis} from "./axes";
2
+ import {Optional} from "result-fn";
3
+
4
+ /**
5
+ * Holds the information to allow mapping axes names to the underlying axes objects.
6
+ * These objects hold the axis ID, its location on the chart (i.e. left, right, bottom, upper)
7
+ * and the underlying d3 selection objects for managing the axes. Axis objects that extend
8
+ * the `BaseAxis` class may have additional properties.
9
+ * @typeParam A The type of the axes (must extend `BaseAxis`)
10
+ */
11
+ export class AxesState<A extends BaseAxis> {
12
+ readonly axes: Map<string, A>
13
+
14
+ private constructor(axes: Map<string, A>) {
15
+ this.axes = axes
16
+ }
17
+
18
+ /**
19
+ * Creates a new axes state from the specified map of axes.
20
+ * @param axes Mapping of the axes ID's to the axes.
21
+ * @return A new axes-state object.
22
+ */
23
+ static from<A extends BaseAxis>(axes: Map<string, A>): AxesState<A> {
24
+ return new AxesState<A>(axes)
25
+ }
26
+
27
+ /**
28
+ * Creates an empty axes-state object.
29
+ * @return A new axes-state object.
30
+ */
31
+ static empty<A extends BaseAxis>(): AxesState<A> {
32
+ return new AxesState<A>(new Map<string, A>())
33
+ }
34
+
35
+ /**
36
+ * @return `true` if the axes state is empty, `false` otherwise.
37
+ */
38
+ isEmpty(): boolean {
39
+ return this.axes.size === 0
40
+ }
41
+
42
+ /**
43
+ * Creates a deep copy of the current axes state.
44
+ * @return A deep copy of the current axes state.
45
+ */
46
+ copy(): AxesState<A> {
47
+ return new AxesState<A>(
48
+ new Map<string, A>(Array.from(this.axes.entries())
49
+ .map(([id, axis]) => [id, {...axis}])
50
+ )
51
+ )
52
+ }
53
+
54
+ /**
55
+ * Adds an axis to the current axis state and returns a new axis state. This is an internal state
56
+ * management function. This should generally not be used. Instead, use the {@link UseChartValues.addXAxis}
57
+ * and {@link UseChartValues.addYAxis} functions to add axes.
58
+ * @param axis The axis to add
59
+ * @param id The ID of the axis to add
60
+ * @return An updated axes state that has the new axis
61
+ * @see UseChartValues.addXAxis
62
+ * @see UseChartValues.addYAxis
63
+ */
64
+ addAxis(axis: A, id: string): AxesState<A> {
65
+ const updatedAxes = this.axes.set(id, axis)
66
+ return new AxesState<A>(updatedAxes)
67
+ }
68
+
69
+ /**
70
+ * Attempts to retrieve the x-axis for the specified ID
71
+ * @param axisId The unique ID of the axis
72
+ * @return The axis, or undefined if no axis with the specified ID is found
73
+ */
74
+ axisFor(axisId: string): Optional<A> {
75
+ const axis = this.axes.get(axisId)
76
+ // when there is no axis for the specified ID and there is at least
77
+ // one axis, then just use that...it is the default axis
78
+ if (axis === undefined && this.axes.size >= 1) {
79
+ return Optional.of(Array.from(this.axes.values())[0])
80
+ }
81
+ return Optional.ofNullable(axis)
82
+ }
83
+
84
+ /**
85
+ * Returns the default axis
86
+ * @return The default axis
87
+ * @see axisDefaultId
88
+ */
89
+ defaultAxis(): Optional<A> {
90
+ const axes = Array.from(this.axes.values())
91
+ return axes.length > 0 ?
92
+ Optional.of(axes[0]) :
93
+ Optional.empty()
94
+ }
95
+
96
+ /**
97
+ * @return An array holding all existing the x-axis IDs
98
+ */
99
+ axisIds(): Array<string> {
100
+ return Array.from(this.axes.keys())
101
+ }
102
+
103
+ /**
104
+ * @return The default name of the x-axis (in case only on default axis was added)
105
+ */
106
+ axisDefaultId(): Optional<string> {
107
+ const ids = Array.from(this.axes.keys())
108
+ return ids.length > 0 ?
109
+ Optional.of(ids[0]) :
110
+ Optional.empty()
111
+ }
112
+ }
@@ -0,0 +1,143 @@
1
+ import {AxisInterval, copyRangeMap} from "./AxisInterval";
2
+
3
+ describe('AxisInterval', () => {
4
+
5
+ describe('AxisInterval creation', () => {
6
+ it('should create an AxisInterval with valid start and end values', () => {
7
+ const interval = AxisInterval.from(1, 5);
8
+ expect(interval.start).toBe(1);
9
+ expect(interval.end).toBe(5);
10
+ });
11
+
12
+ it('should create an AxisInterval with correct start and end when the start is greater than the end', () => {
13
+ const interval = AxisInterval.from(5, 1);
14
+ expect(interval.start).toBe(1);
15
+ expect(interval.end).toBe(5);
16
+ })
17
+
18
+ it('should create an AxisInterval from a tuple holding start and end values', () => {
19
+ const interval = AxisInterval.as([1, 5]);
20
+ expect(interval.start).toBe(1);
21
+ expect(interval.end).toBe(5);
22
+ })
23
+
24
+ it('should create an empty AxisInterval', () => {
25
+ const interval = AxisInterval.empty();
26
+ expect(interval.start).toBeNaN()
27
+ expect(interval.end).toBeNaN()
28
+ })
29
+
30
+ it('should create an empty AxisInterval with start and end NaN', () => {
31
+ const interval = AxisInterval.from(NaN, NaN);
32
+ expect(interval.start).toBeNaN()
33
+ expect(interval.end).toBeNaN()
34
+ })
35
+
36
+ it('should create a new copy of an existing AxisInterval', () => {
37
+ const interval = AxisInterval.from(1, 5);
38
+ const copy = interval.copy();
39
+ expect(copy.start).toBe(1);
40
+ expect(copy.end).toBe(5);
41
+ expect(copy).not.toBe(interval);
42
+ })
43
+ })
44
+
45
+ describe('AxisInterval comparison', () => {
46
+ const interval1 = AxisInterval.from(1, 5);
47
+ const interval2 = AxisInterval.from(1, 5);
48
+ const interval3 = AxisInterval.from(2, 5);
49
+ const emptyInterval = AxisInterval.empty();
50
+
51
+ it('should return true when comparing two AxisIntervals with the same start and end values', () => {
52
+ expect(interval1.equals(interval2)).toBe(true)
53
+ expect(interval1.equalsInterval(1, 5)).toBe(true)
54
+ });
55
+
56
+ it('should return not-equal when comparing two AxisIntervals with different start and end values', () => {
57
+ expect(interval1.equals(interval3)).toBe(false)
58
+ expect(interval1.equalsInterval(1, 3)).toBe(false)
59
+ })
60
+
61
+ it('should return true when comparing two empty intervals', () => {
62
+ expect(AxisInterval.empty().equals(emptyInterval)).toBe(true)
63
+ })
64
+ })
65
+
66
+ describe('AxisInterval conversion', () => {
67
+ it('should convert an AxisInterval to a tuple', () => {
68
+ const interval = AxisInterval.from(1, 5);
69
+ const tuple = interval.asTuple();
70
+ expect(tuple).toEqual([1, 5]);
71
+ })
72
+
73
+ it('should map an AxisInterval to a new AxisInterval', () => {
74
+ const interval = AxisInterval.from(1, 5)
75
+ const mappedInterval = interval.map((start, end) => ([start * 2, end * 3]))
76
+
77
+ expect(mappedInterval.start).toBe(2);
78
+ expect(mappedInterval.end).toBe(15);
79
+ expect(mappedInterval).not.toBe(interval);
80
+ })
81
+
82
+ it('should calculate the measure of an AxisInterval', () => {
83
+ const interval = AxisInterval.from(1, 5)
84
+ expect(interval.measure()).toBe(4);
85
+ })
86
+
87
+ it('should calculate the measure of an empty AxisInterval', () => {
88
+ const interval = AxisInterval.empty()
89
+ expect(interval.measure()).toBe(0);
90
+ })
91
+
92
+ it('should translate the start of the AxisInterval', () => {
93
+ const interval = AxisInterval.from(1, 5)
94
+ const translatedInterval = interval.translateStart(12)
95
+ expect(translatedInterval.start).toBe(5);
96
+ expect(translatedInterval.end).toBe(13);
97
+ expect(translatedInterval).not.toBe(interval);
98
+ })
99
+
100
+ it('should translate the start of an empty interval into an empty interval', () => {
101
+ expect(AxisInterval.empty().translateStart(12)).toEqual(AxisInterval.empty())
102
+ })
103
+
104
+ it('should translate the end of the AxisInterval', () => {
105
+ const interval = AxisInterval.from(1, 5)
106
+ const translatedInterval = interval.translateEnd(-12)
107
+ expect(translatedInterval.start).toBe(-7);
108
+ expect(translatedInterval.end).toBe(1);
109
+ expect(translatedInterval).not.toBe(interval);
110
+ })
111
+
112
+ it('should translate the end of an empty interval into an empty interval', () => {
113
+ expect(AxisInterval.empty().translateEnd(12)).toEqual(AxisInterval.empty())
114
+ })
115
+
116
+ it('should translate an AxisInterval', () => {
117
+ const interval = AxisInterval.from(1, 5)
118
+ const translatedInterval = interval.translate(-12)
119
+ expect(translatedInterval.start).toBe(-11);
120
+ expect(translatedInterval.end).toBe(-7);
121
+ expect(translatedInterval).not.toBe(interval);
122
+ })
123
+
124
+ it('should translate an empty interval into an empty interval', () => {
125
+ expect(AxisInterval.empty().translate(12)).toEqual(AxisInterval.empty())
126
+ })
127
+ })
128
+
129
+ describe('Copy a range map', () => {
130
+ it('should create a copy of a range map', () => {
131
+ const ranges = new Map<string, AxisInterval>([
132
+ ['a', AxisInterval.from(1, 5)],
133
+ ['b', AxisInterval.from(10, 20)]
134
+ ])
135
+ const copy = copyRangeMap(ranges)
136
+
137
+ expect(copy).not.toBe(ranges)
138
+ expect(copy.size).toBe(ranges.size)
139
+ expect(copy.get('a')).toEqual(ranges.get('a'))
140
+ expect(copy.get('b')).toEqual(ranges.get('b'))
141
+ })
142
+ })
143
+ })
@@ -0,0 +1,139 @@
1
+ /**
2
+ * The range of an axis is the physical (start, end) pixels on the screen for the axis.
3
+ * This is the pixel-space of the axis (where as the domain is the data-space of the axis,
4
+ * for example, the tick values).
5
+ */
6
+ export class AxisInterval {
7
+ private constructor(readonly start: number, readonly end: number) {}
8
+
9
+ /**
10
+ * Creates an axis interval from the specified start and end values
11
+ * @param start The axis-range start value
12
+ * @param end The axis-range end value
13
+ * @return The axis-interval
14
+ */
15
+ static from(start: number, end: number): AxisInterval {
16
+ return new AxisInterval(Math.min(start, end), Math.max(start, end))
17
+ }
18
+
19
+ /**
20
+ * Creates an axis interval from the specified tuple
21
+ * @param tuple The tuple to convert
22
+ * @return The axis-interval
23
+ */
24
+ static as(tuple: [start: number, end: number]): AxisInterval {
25
+ return AxisInterval.from(tuple[0], tuple[1])
26
+ }
27
+
28
+ /**
29
+ * Creates an empty axis interval
30
+ * @return An empty axis interval
31
+ */
32
+ static empty(): AxisInterval {
33
+ return new AxisInterval(NaN, NaN)
34
+ }
35
+
36
+ /**
37
+ * @return `true` if the axis interval is empty, `false` otherwise
38
+ */
39
+ isEmpty(): boolean {
40
+ return isNaN(this.start) || isNaN(this.end)
41
+ }
42
+
43
+ /**
44
+ * @return `true` if the axis interval is not empty, `false` otherwise
45
+ */
46
+ isNotEmpty(): boolean {
47
+ return !this.isEmpty()
48
+ }
49
+
50
+ /**
51
+ * @return `true` if the specified axis interval is equal to this one, `false` otherwise
52
+ */
53
+ equalsInterval(start: number, end: number): boolean {
54
+ return (this.start === start && this.end === end) || (this.isEmpty() && isNaN(start) && isNaN(end))
55
+ }
56
+
57
+ /**
58
+ * Determines whether the specified axis interval is equal to this one.
59
+ * @param other The other axis interval to compare to
60
+ * @return `true` if the specified axis interval is equal to this one, `false` otherwise.
61
+ */
62
+ equals(other: AxisInterval): boolean {
63
+ return this.equalsInterval(other.start, other.end)
64
+ }
65
+
66
+ /**
67
+ * Creates a copy of the specified axis interval
68
+ * @return A copy of the specified axis interval
69
+ */
70
+ copy(): AxisInterval {
71
+ return AxisInterval.from(this.start, this.end)
72
+ }
73
+
74
+ /**
75
+ * Converts the axis interval to a tuple
76
+ * @return The axis interval as a tuple
77
+ */
78
+ asTuple(): [start: number, end: number] {
79
+ return [this.start, this.end]
80
+ }
81
+
82
+ /**
83
+ * Applies the specified function to the axis interval and returns the result
84
+ * @param fn The function to apply to the axis interval
85
+ * @return The result of the function application
86
+ */
87
+ map(fn: (start: number, end: number) => [start: number, end: number]): AxisInterval {
88
+ const [start, end] = fn(this.start, this.end)
89
+ return AxisInterval.from(start, end)
90
+ }
91
+
92
+ /**
93
+ * Calculates the measure (end - start) of the specified axis interval.
94
+ * The measure of an empty axis interval is 0.
95
+ * @return The measure (end - start) of the specified axis interval
96
+ */
97
+ measure(): number {
98
+ return this.isNotEmpty() ? this.end - this.start : 0
99
+ }
100
+
101
+ /**
102
+ * Updates the start value of the specified axis interval
103
+ * @param delta The amount by which to update the start value
104
+ * @return A new axis interval
105
+ */
106
+ translateStart(delta: number): AxisInterval {
107
+ return this.isNotEmpty() ? AxisInterval.from(this.start + delta, this.end) : AxisInterval.empty()
108
+ }
109
+
110
+ /**
111
+ * Updates the end value of the specified axis interval
112
+ * @param delta The amount by which to update the end value
113
+ * @return The new axis interval
114
+ */
115
+ translateEnd(delta: number): AxisInterval {
116
+ return this.isNotEmpty() ? AxisInterval.from(this.start, this.end + delta) : AxisInterval.empty()
117
+ }
118
+
119
+ /**
120
+ * Translates the specified axis interval by the specified delta.
121
+ * @param delta The amount by which to translate the axis interval
122
+ * @return The new axis interval
123
+ */
124
+ translate(delta: number): AxisInterval {
125
+ return this.isNotEmpty() ? AxisInterval.from(this.start + delta, this.end + delta) : AxisInterval.empty()
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Creates a copy of the specified map(axis_id, (start, end))
131
+ * @param ranges The ranges map to copy
132
+ * @return A copy of the specified map(axis_id, (start, end))
133
+ */
134
+ export function copyRangeMap(ranges: Map<string, AxisInterval>): Map<string, AxisInterval> {
135
+ return new Map(Array.from(ranges.entries())
136
+ .map(([id, range]) => [id, range.copy()])
137
+ )
138
+ }
139
+
@@ -0,0 +1,113 @@
1
+ import {AxisInterval} from "./AxisInterval";
2
+
3
+ /**
4
+ * An immutable axis range that holds the current range and the original (no zoom) range.
5
+ */
6
+ export abstract class BaseAxisRange {
7
+ readonly current: AxisInterval
8
+ // the range when there is no zoom, which is the interval (0, width | height)
9
+ readonly original: AxisInterval
10
+
11
+ /**
12
+ * @param start The axis-range start value.
13
+ * @param end The axis-range end value.
14
+ * @param [originalStart = start] The optional original axis-range start value. Defaults to the start value if not specified.
15
+ * @param [originalEnd = end] The optional original axis-range end value. Defaults to the end value if not specified.
16
+ * @protected
17
+ */
18
+ protected constructor(start: number, end: number, originalStart: number = start, originalEnd: number = end) {
19
+ this.current = AxisInterval.from(start, end)
20
+ this.original = AxisInterval.from(originalStart, originalEnd)
21
+ }
22
+
23
+ /**
24
+ * Determines whether the specified (start, end) interval matches the original interval
25
+ * @param start The start of the interval
26
+ * @param end The end of the interval
27
+ * @return `true` if the specified interval matches the original interval; `false` otherwise
28
+ */
29
+ matchesOriginal(start: number, end: number): boolean {
30
+ return this.original.equalsInterval(start, end)
31
+ }
32
+
33
+ /**
34
+ * Returns the current distance between the start and end of the range.
35
+ */
36
+ get currentDistance(): number {
37
+ return this.current.measure()
38
+ }
39
+
40
+ /**
41
+ * Returns the original (e.g. before any zooming or panning) distance between the start and end of the range.
42
+ */
43
+ get originalDistance(): number {
44
+ return this.original.measure()
45
+ }
46
+
47
+ /**
48
+ * The ratio between the current and original distance.
49
+ */
50
+ get scaleFactor(): number {
51
+ return this.currentDistance / this.originalDistance
52
+ }
53
+
54
+ /**
55
+ * Scales the range using the current scale-factor (closure on `scaleFactor`)
56
+ * @param factor The factor used to update the range
57
+ * @param value The current value being scaled
58
+ * @return The new range, represented by an array holding the start and end value
59
+ */
60
+ protected scaledRange(factor: number, value: number): AxisInterval {
61
+ const dtStart = value - this.current.start
62
+ const dtEnd = this.current.end - value
63
+ const start = value - dtStart * factor / this.scaleFactor
64
+ const end = value + dtEnd * factor / this.scaleFactor
65
+ return AxisInterval.from(start, end)
66
+ }
67
+
68
+ /**
69
+ *
70
+ * Scales the axis-range by the specified scale factor from the specified {@link value}. The equations
71
+ * are written so that the zooming (scaling) occurs at the specified {@link value}, and expands/contracts equally
72
+ * from that {@link value}.
73
+ * @param factor The scale factor
74
+ * @param value The time from which to scale the interval
75
+ * @return A new continuous-axis range with updated values
76
+ */
77
+ abstract scale(factor: number, value: number): BaseAxisRange
78
+
79
+ /**
80
+ * Scales the axis-range by the specified scale factor, but constrains the range to the specified
81
+ * {@link constraint} min and max. The equations are written so that the zooming (scaling) occurs
82
+ * at the specified {@link value}, and expands/contracts equally from that {@link value}.
83
+ * @param factor The scale factor
84
+ * @param value The value at which the zoom is initiated
85
+ * @param constraint The min and max range
86
+ * @return A new continuous-axis range with updated values
87
+ */
88
+ abstract constrainedScale(factor: number, value: number, constraint: [min: number, max: number]): BaseAxisRange
89
+
90
+ /**
91
+ * Translates the axis-range by the specified amount
92
+ * @param amount The amount by which to translate the axis-range
93
+ * @param [constraints] Optional constraint interval in which the axis range must be within
94
+ * @return An updated {@link ContinuousAxisRange} that has been translated by the specified amount
95
+ */
96
+ abstract translate(amount: number, constraints?: [start: number, end: number]): BaseAxisRange
97
+
98
+ /**
99
+ * Updates the axis-range based on the new start and end values
100
+ * @param start The new start of the axis-range
101
+ * @param end The new end of the axis range
102
+ * @return The updated axis-range type, with all other values unchanged
103
+ */
104
+ abstract update(start: number, end: number): BaseAxisRange
105
+
106
+ /**
107
+ * Updates the original range with the new start and end values.
108
+ * @param start The new value for the start of the original range
109
+ * @param end The new value for the end of the original range
110
+ * @return The updated original range.
111
+ */
112
+ abstract updateOriginal(start: number, end: number): BaseAxisRange
113
+ }