@redsift/charts 9.2.3-patch → 9.2.3

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 (270) hide show
  1. package/coverage/clover.xml +1096 -0
  2. package/coverage/coverage-final.json +60 -0
  3. package/coverage/lcov-report/base.css +224 -0
  4. package/coverage/lcov-report/block-navigation.js +87 -0
  5. package/coverage/lcov-report/components/Arc/Arc.tsx.html +304 -0
  6. package/coverage/lcov-report/components/Arc/index.html +146 -0
  7. package/coverage/lcov-report/components/Arc/index.ts.html +94 -0
  8. package/coverage/lcov-report/components/Arc/styles.ts.html +208 -0
  9. package/coverage/lcov-report/components/Arcs/Arcs.tsx.html +409 -0
  10. package/coverage/lcov-report/components/Arcs/index.html +146 -0
  11. package/coverage/lcov-report/components/Arcs/index.ts.html +94 -0
  12. package/coverage/lcov-report/components/Arcs/styles.ts.html +106 -0
  13. package/coverage/lcov-report/components/Axis/Axis.tsx.html +754 -0
  14. package/coverage/lcov-report/components/Axis/computeTicks.ts.html +481 -0
  15. package/coverage/lcov-report/components/Axis/index.html +176 -0
  16. package/coverage/lcov-report/components/Axis/index.ts.html +94 -0
  17. package/coverage/lcov-report/components/Axis/styles.ts.html +148 -0
  18. package/coverage/lcov-report/components/Axis/types.ts.html +253 -0
  19. package/coverage/lcov-report/components/Bar/Bar.tsx.html +421 -0
  20. package/coverage/lcov-report/components/Bar/index.html +161 -0
  21. package/coverage/lcov-report/components/Bar/index.ts.html +94 -0
  22. package/coverage/lcov-report/components/Bar/styles.ts.html +247 -0
  23. package/coverage/lcov-report/components/Bar/types.ts.html +178 -0
  24. package/coverage/lcov-report/components/BarChart/BarChart.tsx.html +352 -0
  25. package/coverage/lcov-report/components/BarChart/EmptyBarChart.tsx.html +259 -0
  26. package/coverage/lcov-report/components/BarChart/LoadingBarChart.tsx.html +145 -0
  27. package/coverage/lcov-report/components/BarChart/RenderedBarChart.tsx.html +430 -0
  28. package/coverage/lcov-report/components/BarChart/index.html +206 -0
  29. package/coverage/lcov-report/components/BarChart/index.ts.html +94 -0
  30. package/coverage/lcov-report/components/BarChart/styles.ts.html +190 -0
  31. package/coverage/lcov-report/components/BarChart/utils.ts.html +145 -0
  32. package/coverage/lcov-report/components/BottomAxis/BottomAxis.tsx.html +247 -0
  33. package/coverage/lcov-report/components/BottomAxis/index.html +146 -0
  34. package/coverage/lcov-report/components/BottomAxis/index.ts.html +94 -0
  35. package/coverage/lcov-report/components/BottomAxis/styles.ts.html +139 -0
  36. package/coverage/lcov-report/components/ChartContainer/ChartContainer.tsx.html +361 -0
  37. package/coverage/lcov-report/components/ChartContainer/index.html +146 -0
  38. package/coverage/lcov-report/components/ChartContainer/index.ts.html +94 -0
  39. package/coverage/lcov-report/components/ChartContainer/intl/index.html +116 -0
  40. package/coverage/lcov-report/components/ChartContainer/intl/index.ts.html +106 -0
  41. package/coverage/lcov-report/components/ChartContainer/styles.ts.html +208 -0
  42. package/coverage/lcov-report/components/DataPoint/DataPoint.tsx.html +391 -0
  43. package/coverage/lcov-report/components/DataPoint/index.html +146 -0
  44. package/coverage/lcov-report/components/DataPoint/index.ts.html +94 -0
  45. package/coverage/lcov-report/components/DataPoint/styles.ts.html +109 -0
  46. package/coverage/lcov-report/components/Dot/Dot.tsx.html +232 -0
  47. package/coverage/lcov-report/components/Dot/index.html +146 -0
  48. package/coverage/lcov-report/components/Dot/index.ts.html +94 -0
  49. package/coverage/lcov-report/components/Dot/styles.ts.html +184 -0
  50. package/coverage/lcov-report/components/HorizontalBar/HorizontalBar.tsx.html +541 -0
  51. package/coverage/lcov-report/components/HorizontalBar/index.html +161 -0
  52. package/coverage/lcov-report/components/HorizontalBar/index.ts.html +94 -0
  53. package/coverage/lcov-report/components/HorizontalBar/styles.ts.html +187 -0
  54. package/coverage/lcov-report/components/HorizontalBar/types.ts.html +301 -0
  55. package/coverage/lcov-report/components/HorizontalBarChart/HorizontalBarChart.tsx.html +691 -0
  56. package/coverage/lcov-report/components/HorizontalBarChart/index.html +146 -0
  57. package/coverage/lcov-report/components/HorizontalBarChart/index.ts.html +94 -0
  58. package/coverage/lcov-report/components/HorizontalBarChart/styles.ts.html +196 -0
  59. package/coverage/lcov-report/components/HorizontalBarChart/types.ts.html +301 -0
  60. package/coverage/lcov-report/components/Legend/Legend.tsx.html +268 -0
  61. package/coverage/lcov-report/components/Legend/index.html +146 -0
  62. package/coverage/lcov-report/components/Legend/index.ts.html +94 -0
  63. package/coverage/lcov-report/components/Legend/styles.ts.html +130 -0
  64. package/coverage/lcov-report/components/LegendItem/LegendItem.tsx.html +325 -0
  65. package/coverage/lcov-report/components/LegendItem/index.html +146 -0
  66. package/coverage/lcov-report/components/LegendItem/index.ts.html +94 -0
  67. package/coverage/lcov-report/components/LegendItem/styles.ts.html +205 -0
  68. package/coverage/lcov-report/components/PieChart/EmptyPieChart.tsx.html +343 -0
  69. package/coverage/lcov-report/components/PieChart/LoadingPieChart.tsx.html +145 -0
  70. package/coverage/lcov-report/components/PieChart/PieChart.tsx.html +385 -0
  71. package/coverage/lcov-report/components/PieChart/RenderedPieChart.tsx.html +607 -0
  72. package/coverage/lcov-report/components/PieChart/index.html +221 -0
  73. package/coverage/lcov-report/components/PieChart/index.ts.html +94 -0
  74. package/coverage/lcov-report/components/PieChart/styles.ts.html +370 -0
  75. package/coverage/lcov-report/components/PieChart/types.ts.html +367 -0
  76. package/coverage/lcov-report/components/PieChart/utils.ts.html +199 -0
  77. package/coverage/lcov-report/components/ScatterPlot/EmptyScatterPlot.tsx.html +295 -0
  78. package/coverage/lcov-report/components/ScatterPlot/LoadingScatterPlot.tsx.html +145 -0
  79. package/coverage/lcov-report/components/ScatterPlot/RenderedScatterPlot.tsx.html +1048 -0
  80. package/coverage/lcov-report/components/ScatterPlot/ScatterPlot.tsx.html +367 -0
  81. package/coverage/lcov-report/components/ScatterPlot/index.html +221 -0
  82. package/coverage/lcov-report/components/ScatterPlot/index.ts.html +94 -0
  83. package/coverage/lcov-report/components/ScatterPlot/styles.ts.html +190 -0
  84. package/coverage/lcov-report/components/ScatterPlot/types.ts.html +394 -0
  85. package/coverage/lcov-report/components/ScatterPlot/utils.ts.html +388 -0
  86. package/coverage/lcov-report/core/Arc/Arc.tsx.html +304 -0
  87. package/coverage/lcov-report/core/Arc/index.html +146 -0
  88. package/coverage/lcov-report/core/Arc/index.ts.html +94 -0
  89. package/coverage/lcov-report/core/Arc/styles.ts.html +202 -0
  90. package/coverage/lcov-report/core/Arcs/Arcs.tsx.html +421 -0
  91. package/coverage/lcov-report/core/Arcs/index.html +146 -0
  92. package/coverage/lcov-report/core/Arcs/index.ts.html +94 -0
  93. package/coverage/lcov-report/core/Arcs/styles.ts.html +106 -0
  94. package/coverage/lcov-report/core/Axis/Axis.tsx.html +754 -0
  95. package/coverage/lcov-report/core/Axis/computeTicks.ts.html +481 -0
  96. package/coverage/lcov-report/core/Axis/index.html +176 -0
  97. package/coverage/lcov-report/core/Axis/index.ts.html +94 -0
  98. package/coverage/lcov-report/core/Axis/styles.ts.html +145 -0
  99. package/coverage/lcov-report/core/Axis/types.ts.html +253 -0
  100. package/coverage/lcov-report/core/Bar/Bar.tsx.html +421 -0
  101. package/coverage/lcov-report/core/Bar/index.html +161 -0
  102. package/coverage/lcov-report/core/Bar/index.ts.html +94 -0
  103. package/coverage/lcov-report/core/Bar/styles.ts.html +190 -0
  104. package/coverage/lcov-report/core/Bar/types.ts.html +178 -0
  105. package/coverage/lcov-report/core/BottomAxis/BottomAxis.tsx.html +277 -0
  106. package/coverage/lcov-report/core/BottomAxis/index.html +146 -0
  107. package/coverage/lcov-report/core/BottomAxis/index.ts.html +94 -0
  108. package/coverage/lcov-report/core/BottomAxis/styles.ts.html +139 -0
  109. package/coverage/lcov-report/core/ChartConfig/ChartConfig.ts.html +97 -0
  110. package/coverage/lcov-report/core/ChartConfig/index.html +131 -0
  111. package/coverage/lcov-report/core/ChartConfig/index.ts.html +88 -0
  112. package/coverage/lcov-report/core/ChartContainer/ChartContainer.tsx.html +421 -0
  113. package/coverage/lcov-report/core/ChartContainer/index.html +146 -0
  114. package/coverage/lcov-report/core/ChartContainer/index.ts.html +94 -0
  115. package/coverage/lcov-report/core/ChartContainer/intl/index.html +116 -0
  116. package/coverage/lcov-report/core/ChartContainer/intl/index.ts.html +106 -0
  117. package/coverage/lcov-report/core/ChartContainer/styles.ts.html +205 -0
  118. package/coverage/lcov-report/core/DataPoint/DataPoint.tsx.html +442 -0
  119. package/coverage/lcov-report/core/DataPoint/index.html +146 -0
  120. package/coverage/lcov-report/core/DataPoint/index.ts.html +94 -0
  121. package/coverage/lcov-report/core/DataPoint/styles.ts.html +109 -0
  122. package/coverage/lcov-report/core/Dot/Dot.tsx.html +232 -0
  123. package/coverage/lcov-report/core/Dot/index.html +146 -0
  124. package/coverage/lcov-report/core/Dot/index.ts.html +94 -0
  125. package/coverage/lcov-report/core/Dot/styles.ts.html +184 -0
  126. package/coverage/lcov-report/core/Legend/Legend.tsx.html +277 -0
  127. package/coverage/lcov-report/core/Legend/index.html +146 -0
  128. package/coverage/lcov-report/core/Legend/index.ts.html +94 -0
  129. package/coverage/lcov-report/core/Legend/styles.ts.html +172 -0
  130. package/coverage/lcov-report/core/Point/Point.tsx.html +484 -0
  131. package/coverage/lcov-report/core/Point/index.html +146 -0
  132. package/coverage/lcov-report/core/Point/index.ts.html +94 -0
  133. package/coverage/lcov-report/core/Point/styles.ts.html +169 -0
  134. package/coverage/lcov-report/favicon.png +0 -0
  135. package/coverage/lcov-report/gallery/HorizontalBarChart/HorizontalBarChart.tsx.html +706 -0
  136. package/coverage/lcov-report/gallery/HorizontalBarChart/index.html +161 -0
  137. package/coverage/lcov-report/gallery/HorizontalBarChart/index.ts.html +94 -0
  138. package/coverage/lcov-report/gallery/HorizontalBarChart/styles.ts.html +316 -0
  139. package/coverage/lcov-report/gallery/HorizontalBarChart/types.ts.html +310 -0
  140. package/coverage/lcov-report/gallery/PieChart/PieChart.tsx.html +1252 -0
  141. package/coverage/lcov-report/gallery/PieChart/index.html +161 -0
  142. package/coverage/lcov-report/gallery/PieChart/index.ts.html +94 -0
  143. package/coverage/lcov-report/gallery/PieChart/styles.ts.html +517 -0
  144. package/coverage/lcov-report/gallery/PieChart/types.ts.html +388 -0
  145. package/coverage/lcov-report/gallery/ScatterPlot/index.html +146 -0
  146. package/coverage/lcov-report/gallery/ScatterPlot/index.ts.html +94 -0
  147. package/coverage/lcov-report/gallery/ScatterPlot/styles.ts.html +343 -0
  148. package/coverage/lcov-report/gallery/ScatterPlot/types.ts.html +433 -0
  149. package/coverage/lcov-report/hooks/index.html +176 -0
  150. package/coverage/lcov-report/hooks/index.ts.html +97 -0
  151. package/coverage/lcov-report/hooks/useBrush.tsx.html +430 -0
  152. package/coverage/lcov-report/hooks/useColor.tsx.html +163 -0
  153. package/coverage/lcov-report/hooks/useFormatCategoricalData.tsx.html +289 -0
  154. package/coverage/lcov-report/hooks/useIsEmpty.tsx.html +118 -0
  155. package/coverage/lcov-report/hooks/useZoom.tsx.html +235 -0
  156. package/coverage/lcov-report/index.html +311 -0
  157. package/coverage/lcov-report/prettify.css +1 -0
  158. package/coverage/lcov-report/prettify.js +2 -0
  159. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  160. package/coverage/lcov-report/sorter.js +196 -0
  161. package/coverage/lcov.info +2345 -0
  162. package/coverage/storybook/coverage-storybook.json +79382 -0
  163. package/dist/package.json +98 -0
  164. package/index.ts +1 -0
  165. package/jest.config.js +3 -0
  166. package/package.json +2 -3
  167. package/rollup.config.js +13 -0
  168. package/src/components/Arc/Arc.test.tsx +80 -0
  169. package/src/components/Arc/Arc.tsx +73 -0
  170. package/src/components/Arc/index.ts +3 -0
  171. package/src/components/Arc/styles.ts +41 -0
  172. package/src/components/Arc/types.ts +18 -0
  173. package/src/components/Arcs/Arcs.stories.tsx +177 -0
  174. package/src/components/Arcs/Arcs.tsx +108 -0
  175. package/src/components/Arcs/index.ts +3 -0
  176. package/src/components/Arcs/styles.ts +7 -0
  177. package/src/components/Arcs/types.ts +26 -0
  178. package/src/components/Axis/Axis.stories.tsx +297 -0
  179. package/src/components/Axis/Axis.tsx +223 -0
  180. package/src/components/Axis/computeTicks.ts +132 -0
  181. package/src/components/Axis/index.ts +3 -0
  182. package/src/components/Axis/styles.ts +21 -0
  183. package/src/components/Axis/types.ts +56 -0
  184. package/src/components/Bar/Bar.stories.tsx +152 -0
  185. package/src/components/Bar/Bar.test.tsx +156 -0
  186. package/src/components/Bar/Bar.tsx +112 -0
  187. package/src/components/Bar/index.ts +3 -0
  188. package/src/components/Bar/styles.ts +54 -0
  189. package/src/components/Bar/types.ts +31 -0
  190. package/src/components/BarChart/BarChart.stories.tsx +74 -0
  191. package/src/components/BarChart/BarChart.test.tsx +178 -0
  192. package/src/components/BarChart/BarChart.tsx +89 -0
  193. package/src/components/BarChart/EmptyBarChart.tsx +58 -0
  194. package/src/components/BarChart/LoadingBarChart.tsx +20 -0
  195. package/src/components/BarChart/RenderedBarChart.tsx +115 -0
  196. package/src/components/BarChart/__snapshots__/BarChart.test.tsx.snap +7028 -0
  197. package/src/components/BarChart/index.ts +3 -0
  198. package/src/components/BarChart/styles.ts +35 -0
  199. package/src/components/BarChart/types.ts +58 -0
  200. package/src/components/BarChart/utils.ts +20 -0
  201. package/src/components/ChartContainer/ChartContainer.stories.tsx +81 -0
  202. package/src/components/ChartContainer/ChartContainer.test.tsx +71 -0
  203. package/src/components/ChartContainer/ChartContainer.tsx +92 -0
  204. package/src/components/ChartContainer/index.ts +3 -0
  205. package/src/components/ChartContainer/intl/en-US.json +3 -0
  206. package/src/components/ChartContainer/intl/fr-FR.json +3 -0
  207. package/src/components/ChartContainer/intl/index.ts +7 -0
  208. package/src/components/ChartContainer/styles.ts +41 -0
  209. package/src/components/ChartContainer/types.ts +26 -0
  210. package/src/components/DataPoint/DataPoint.tsx +102 -0
  211. package/src/components/DataPoint/index.ts +3 -0
  212. package/src/components/DataPoint/styles.ts +8 -0
  213. package/src/components/DataPoint/types.ts +33 -0
  214. package/src/components/Dot/Dot.stories.tsx +157 -0
  215. package/src/components/Dot/Dot.test.tsx +136 -0
  216. package/src/components/Dot/Dot.tsx +49 -0
  217. package/src/components/Dot/index.ts +3 -0
  218. package/src/components/Dot/styles.ts +33 -0
  219. package/src/components/Dot/types.ts +16 -0
  220. package/src/components/Legend/Legend.stories.tsx +108 -0
  221. package/src/components/Legend/Legend.tsx +61 -0
  222. package/src/components/Legend/index.ts +3 -0
  223. package/src/components/Legend/styles.ts +15 -0
  224. package/src/components/Legend/types.ts +27 -0
  225. package/src/components/LegendItem/LegendItem.test.tsx +69 -0
  226. package/src/components/LegendItem/LegendItem.tsx +80 -0
  227. package/src/components/LegendItem/index.ts +3 -0
  228. package/src/components/LegendItem/styles.ts +40 -0
  229. package/src/components/LegendItem/types.ts +30 -0
  230. package/src/components/PieChart/EmptyPieChart.tsx +86 -0
  231. package/src/components/PieChart/LoadingPieChart.tsx +20 -0
  232. package/src/components/PieChart/PieChart.stories.tsx +85 -0
  233. package/src/components/PieChart/PieChart.test.tsx +183 -0
  234. package/src/components/PieChart/PieChart.tsx +100 -0
  235. package/src/components/PieChart/RenderedPieChart.tsx +174 -0
  236. package/src/components/PieChart/__snapshots__/PieChart.test.tsx.snap +21020 -0
  237. package/src/components/PieChart/index.ts +3 -0
  238. package/src/components/PieChart/styles.ts +95 -0
  239. package/src/components/PieChart/types.ts +94 -0
  240. package/src/components/PieChart/utils.ts +38 -0
  241. package/src/components/ScatterPlot/EmptyScatterPlot.tsx +70 -0
  242. package/src/components/ScatterPlot/LoadingScatterPlot.tsx +20 -0
  243. package/src/components/ScatterPlot/RenderedScatterPlot.tsx +321 -0
  244. package/src/components/ScatterPlot/ScatterPlot.stories.tsx +101 -0
  245. package/src/components/ScatterPlot/ScatterPlot.test.tsx +61 -0
  246. package/src/components/ScatterPlot/ScatterPlot.tsx +94 -0
  247. package/src/components/ScatterPlot/__snapshots__/ScatterPlot.test.tsx.snap +91712 -0
  248. package/src/components/ScatterPlot/index.ts +3 -0
  249. package/src/components/ScatterPlot/styles.ts +35 -0
  250. package/src/components/ScatterPlot/types.ts +103 -0
  251. package/src/components/ScatterPlot/utils.ts +101 -0
  252. package/src/config.ts +10 -0
  253. package/src/hooks/index.ts +4 -0
  254. package/src/hooks/useBrush.tsx +115 -0
  255. package/src/hooks/useColor.tsx +26 -0
  256. package/src/hooks/useFormatCategoricalData.tsx +68 -0
  257. package/src/hooks/useZoom.tsx +50 -0
  258. package/src/index.ts +15 -0
  259. package/src/scheme.ts +213 -0
  260. package/src/types/data.ts +52 -0
  261. package/src/types/index.ts +5 -0
  262. package/src/types/legend.ts +19 -0
  263. package/src/types/scale.ts +79 -0
  264. package/src/types/size.ts +17 -0
  265. package/src/types/theme.ts +27 -0
  266. package/tsconfig.json +3 -0
  267. /package/{CONTRIBUTING.md → dist/CONTRIBUTING.md} +0 -0
  268. /package/{index.d.ts → dist/index.d.ts} +0 -0
  269. /package/{index.js → dist/index.js} +0 -0
  270. /package/{index.js.map → dist/index.js.map} +0 -0
@@ -0,0 +1,297 @@
1
+ import React, { RefObject, useRef } from 'react';
2
+ // @ts-ignore
3
+ import type { StoryObj } from '@storybook/react';
4
+ import { scaleLinear as d3scaleLinear, scalePoint as d3scalePoint } from 'd3';
5
+
6
+ import { Axis, AxisPosition, AxisProps, AxisVariant } from '.';
7
+ import { Flexbox } from '@redsift/design-system';
8
+ import { useZoom } from '../../hooks';
9
+ import { AnyScale } from '../../types';
10
+
11
+ const meta = {
12
+ title: 'Charts/Core/Axis',
13
+ component: Axis,
14
+ };
15
+
16
+ export default meta;
17
+ type Story = StoryObj<AxisProps>;
18
+
19
+ const scaleLinearX = d3scaleLinear().domain([0, 80]).range([0, 280]);
20
+ const scaleLinearY = d3scaleLinear().domain([0, 35]).range([160, 0]);
21
+
22
+ export const Linear: Story = {
23
+ render: () => (
24
+ <Flexbox gap="16px">
25
+ {[0, -45].map((tickRotation) => (
26
+ <svg
27
+ height={260}
28
+ style={{ border: '1px dashed black' }}
29
+ width={380}
30
+ key={`${tickRotation}`}
31
+ >
32
+ <g transform="translate(50,50)">
33
+ <Axis
34
+ scale={scaleLinearX as AnyScale}
35
+ position={AxisPosition.top}
36
+ x={0}
37
+ y={0}
38
+ length={280}
39
+ tickRotation={tickRotation}
40
+ />
41
+ <Axis
42
+ scale={scaleLinearY as AnyScale}
43
+ position={AxisPosition.right}
44
+ x={280}
45
+ y={0}
46
+ length={160}
47
+ tickRotation={tickRotation}
48
+ />
49
+ <Axis
50
+ scale={scaleLinearX as AnyScale}
51
+ position={AxisPosition.bottom}
52
+ x={0}
53
+ y={160}
54
+ length={280}
55
+ tickRotation={tickRotation}
56
+ />
57
+ <Axis
58
+ scale={scaleLinearY as AnyScale}
59
+ position={AxisPosition.left}
60
+ x={0}
61
+ y={0}
62
+ length={160}
63
+ tickRotation={tickRotation}
64
+ />
65
+ </g>
66
+ </svg>
67
+ ))}
68
+ </Flexbox>
69
+ ),
70
+ };
71
+
72
+ export const WithLegend: Story = {
73
+ render: () => (
74
+ <Flexbox gap="16px">
75
+ <svg height={260} style={{ border: '1px dashed black' }} width={380}>
76
+ <g transform="translate(50,50)">
77
+ <Axis
78
+ scale={scaleLinearX as AnyScale}
79
+ position={AxisPosition.top}
80
+ x={0}
81
+ y={32}
82
+ length={280}
83
+ legend="start"
84
+ legendPosition="start"
85
+ />
86
+ <Axis
87
+ scale={scaleLinearX as AnyScale}
88
+ position={AxisPosition.top}
89
+ x={0}
90
+ y={96}
91
+ length={280}
92
+ legend="middle"
93
+ legendPosition="middle"
94
+ />
95
+ <Axis
96
+ scale={scaleLinearX as AnyScale}
97
+ position={AxisPosition.top}
98
+ x={0}
99
+ y={160}
100
+ length={280}
101
+ legend="end"
102
+ legendPosition="end"
103
+ />
104
+ </g>
105
+ </svg>
106
+ <svg height={260} style={{ border: '1px dashed black' }} width={380}>
107
+ <g transform="translate(50,50)">
108
+ <Axis
109
+ scale={scaleLinearY as AnyScale}
110
+ position={AxisPosition.left}
111
+ x={32}
112
+ y={0}
113
+ length={160}
114
+ legend="start"
115
+ legendPosition="start"
116
+ />
117
+ <Axis
118
+ scale={scaleLinearY as AnyScale}
119
+ position={AxisPosition.left}
120
+ x={156}
121
+ y={0}
122
+ length={160}
123
+ legend="middle"
124
+ legendPosition="middle"
125
+ />
126
+ <Axis
127
+ scale={scaleLinearY as AnyScale}
128
+ position={AxisPosition.left}
129
+ x={280}
130
+ y={0}
131
+ length={160}
132
+ legend="end"
133
+ legendPosition="end"
134
+ />
135
+ </g>
136
+ </svg>
137
+ </Flexbox>
138
+ ),
139
+ };
140
+
141
+ export const AllVariants: Story = {
142
+ render: () => (
143
+ <Flexbox gap="16px">
144
+ {Object.keys(AxisVariant).map((variant) => (
145
+ <svg
146
+ height={260}
147
+ style={{ border: '1px dashed black' }}
148
+ width={380}
149
+ key={`${variant}`}
150
+ >
151
+ <g transform="translate(50,50)">
152
+ <Axis
153
+ scale={scaleLinearX as AnyScale}
154
+ position={AxisPosition.top}
155
+ x={0}
156
+ y={0}
157
+ length={280}
158
+ variant={variant as AxisVariant}
159
+ />
160
+ <Axis
161
+ scale={scaleLinearY as AnyScale}
162
+ position={AxisPosition.right}
163
+ x={280}
164
+ y={0}
165
+ length={160}
166
+ variant={variant as AxisVariant}
167
+ />
168
+ <Axis
169
+ scale={scaleLinearX as AnyScale}
170
+ position={AxisPosition.bottom}
171
+ x={0}
172
+ y={160}
173
+ length={280}
174
+ variant={variant as AxisVariant}
175
+ />
176
+ <Axis
177
+ scale={scaleLinearY as AnyScale}
178
+ position={AxisPosition.left}
179
+ x={0}
180
+ y={0}
181
+ length={160}
182
+ variant={variant as AxisVariant}
183
+ />
184
+ </g>
185
+ </svg>
186
+ ))}
187
+ </Flexbox>
188
+ ),
189
+ };
190
+
191
+ export const Zoomable: Story = {
192
+ render: () => {
193
+ const svgRef = useRef<SVGSVGElement>();
194
+ const { scaleX, scaleY } = useZoom({
195
+ svgRef,
196
+ scaleX: scaleLinearX,
197
+ scaleY: scaleLinearY,
198
+ });
199
+
200
+ return (
201
+ <Flexbox gap="16px">
202
+ <svg
203
+ ref={svgRef as RefObject<SVGSVGElement>}
204
+ height={260}
205
+ style={{ border: '1px dashed black' }}
206
+ width={380}
207
+ >
208
+ <g transform="translate(50,50)">
209
+ <Axis
210
+ scale={scaleX as AnyScale}
211
+ position={AxisPosition.top}
212
+ x={0}
213
+ y={0}
214
+ length={280}
215
+ />
216
+ <Axis
217
+ scale={scaleY as AnyScale}
218
+ position={AxisPosition.right}
219
+ x={280}
220
+ y={0}
221
+ length={160}
222
+ />
223
+ <Axis
224
+ scale={scaleX as AnyScale}
225
+ position={AxisPosition.bottom}
226
+ x={0}
227
+ y={160}
228
+ length={280}
229
+ />
230
+ <Axis
231
+ scale={scaleY as AnyScale}
232
+ position={AxisPosition.left}
233
+ x={0}
234
+ y={0}
235
+ length={160}
236
+ />
237
+ </g>
238
+ </svg>
239
+ </Flexbox>
240
+ );
241
+ },
242
+ };
243
+
244
+ const scalePointX = d3scalePoint()
245
+ .domain(['A', 'list', 'of', 'words', 'as', 'domain'])
246
+ .range([0, 280]);
247
+ const scalePointY = d3scalePoint().domain(['A', 'B', 'C']).range([160, 0]);
248
+
249
+ export const Point: Story = {
250
+ render: () => (
251
+ <Flexbox gap="16px">
252
+ {[0, -45].map((tickRotation) => (
253
+ <svg
254
+ height={260}
255
+ style={{ border: '1px dashed black' }}
256
+ width={380}
257
+ key={`${tickRotation}`}
258
+ >
259
+ <g transform="translate(50,50)">
260
+ <Axis
261
+ scale={scalePointX as AnyScale}
262
+ position={AxisPosition.top}
263
+ x={0}
264
+ y={0}
265
+ length={280}
266
+ tickRotation={tickRotation}
267
+ />
268
+ <Axis
269
+ scale={scalePointY as AnyScale}
270
+ position={AxisPosition.right}
271
+ x={280}
272
+ y={0}
273
+ length={160}
274
+ tickRotation={tickRotation}
275
+ />
276
+ <Axis
277
+ scale={scalePointX as AnyScale}
278
+ position={AxisPosition.bottom}
279
+ x={0}
280
+ y={160}
281
+ length={280}
282
+ tickRotation={tickRotation}
283
+ />
284
+ <Axis
285
+ scale={scalePointY as AnyScale}
286
+ position={AxisPosition.left}
287
+ x={0}
288
+ y={0}
289
+ length={160}
290
+ tickRotation={tickRotation}
291
+ />
292
+ </g>
293
+ </svg>
294
+ ))}
295
+ </Flexbox>
296
+ ),
297
+ };
@@ -0,0 +1,223 @@
1
+ import React, { forwardRef, RefObject, useRef } from 'react';
2
+ import classNames from 'classnames';
3
+
4
+ import { Comp } from '@redsift/design-system';
5
+
6
+ import { AxisProps, AxisPosition, AxisVariant } from './types';
7
+ import { StyledAxis } from './styles';
8
+ import { animated, useSpring, useTransition } from '@react-spring/web';
9
+ import { computeTicks } from './computeTicks';
10
+ import { config } from '../../config';
11
+
12
+ const COMPONENT_NAME = 'Axis';
13
+ const CLASSNAME = 'redsift-axis';
14
+ const DEFAULT_PROPS: Partial<AxisProps> = {
15
+ position: AxisPosition.bottom,
16
+ legendOffset: -32,
17
+ legendPosition: 'end',
18
+ tickPadding: 5,
19
+ tickRotation: 0,
20
+ tickSize: 5,
21
+ variant: AxisVariant.default,
22
+ x: 0,
23
+ y: 0,
24
+ };
25
+
26
+ const getAxisType = (position: AxisPosition) =>
27
+ [AxisPosition.top, AxisPosition.bottom].includes(position) ? 'x' : 'y';
28
+
29
+ export const Axis: Comp<AxisProps, SVGGElement> = forwardRef((props, ref) => {
30
+ const {
31
+ className,
32
+ length,
33
+ legend,
34
+ legendOffset,
35
+ legendPosition,
36
+ position,
37
+ scale,
38
+ tickPadding,
39
+ tickRotation,
40
+ tickSize,
41
+ tickValues,
42
+ variant,
43
+ x,
44
+ y,
45
+ ...forwardedProps
46
+ } = props;
47
+ const axis = getAxisType(position!);
48
+
49
+ const axisRef = (ref || useRef<SVGGElement>()) as RefObject<SVGGElement>;
50
+
51
+ const animatedProps = useSpring({
52
+ ...config,
53
+ to: async (next: (props?: object) => Promise<void>) => {
54
+ await next({
55
+ lineX2: axis === 'x' ? length : 0,
56
+ lineY2: axis === 'x' ? 0 : length,
57
+ });
58
+ },
59
+ from: { lineX2: 0, lineY2: 0 },
60
+ reset: false,
61
+ });
62
+
63
+ let legendNode = null;
64
+ if (legend !== undefined) {
65
+ let legendX = 0;
66
+ let legendY = 0;
67
+ let legendRotation = 0;
68
+ let textAnchor;
69
+
70
+ if (axis === 'y') {
71
+ legendRotation = -90;
72
+ legendX = legendOffset!;
73
+ if (legendPosition === 'start') {
74
+ textAnchor = 'start';
75
+ legendY = length!;
76
+ } else if (legendPosition === 'middle') {
77
+ textAnchor = 'middle';
78
+ legendY = length! / 2;
79
+ } else if (legendPosition === 'end') {
80
+ textAnchor = 'end';
81
+ }
82
+ } else {
83
+ legendY = legendOffset!;
84
+ if (legendPosition === 'start') {
85
+ textAnchor = 'start';
86
+ } else if (legendPosition === 'middle') {
87
+ textAnchor = 'middle';
88
+ legendX = length! / 2;
89
+ } else if (legendPosition === 'end') {
90
+ textAnchor = 'end';
91
+ legendX = length!;
92
+ }
93
+ }
94
+
95
+ legendNode = (
96
+ <>
97
+ <text
98
+ transform={`translate(${legendX}, ${legendY}) rotate(${legendRotation})`}
99
+ textAnchor={textAnchor}
100
+ style={{
101
+ dominantBaseline: 'central',
102
+ }}
103
+ >
104
+ {legend}
105
+ </text>
106
+ </>
107
+ );
108
+ }
109
+
110
+ const { ticks, textAlign, textBaseline } = computeTicks({
111
+ axis,
112
+ scale,
113
+ ticksPosition: [AxisPosition.top, AxisPosition.left].includes(position!)
114
+ ? 'before'
115
+ : 'after',
116
+ tickValues,
117
+ tickSize: tickSize!,
118
+ tickPadding: tickPadding!,
119
+ tickRotation: tickRotation!,
120
+ });
121
+
122
+ const transition = useTransition<
123
+ typeof ticks[0],
124
+ { opacity: number; transform: string; textTransform: string }
125
+ >(ticks, {
126
+ ...config,
127
+ keys: (tick) => tick.key,
128
+ initial: (tick) => ({
129
+ opacity: 1,
130
+ transform: `translate(${tick.x},${tick.y})`,
131
+ textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
132
+ }),
133
+ from: (tick) => ({
134
+ opacity: 0,
135
+ transform: `translate(${tick.x},${tick.y})`,
136
+ textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
137
+ }),
138
+ enter: (tick) => ({
139
+ opacity: 1,
140
+ transform: `translate(${tick.x},${tick.y})`,
141
+ textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
142
+ }),
143
+ update: (tick) => ({
144
+ opacity: 1,
145
+ transform: `translate(${tick.x},${tick.y})`,
146
+ textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
147
+ }),
148
+ leave: {
149
+ opacity: 0,
150
+ },
151
+ });
152
+
153
+ return (
154
+ <StyledAxis
155
+ className={classNames(Axis.className, className)}
156
+ {...forwardedProps}
157
+ transform={`translate(${x},${y})`}
158
+ ref={axisRef}
159
+ >
160
+ {variant === AxisVariant.default ||
161
+ variant === AxisVariant.tick ||
162
+ variant === AxisVariant.lineTick ||
163
+ variant === AxisVariant.tickValue
164
+ ? transition((transitionProps, tick, _state, tickIndex) => {
165
+ return (
166
+ <animated.g
167
+ className={`${Axis.className}__tick`}
168
+ key={tickIndex}
169
+ transform={transitionProps.transform}
170
+ style={{ opacity: transitionProps.opacity }}
171
+ >
172
+ <line
173
+ className={`${Axis.className}-tick__line`}
174
+ x1={0}
175
+ x2={tick.lineX}
176
+ y1={0}
177
+ y2={tick.lineY}
178
+ />
179
+ {variant === AxisVariant.default ||
180
+ variant === AxisVariant.tickValue ? (
181
+ <animated.text
182
+ dominantBaseline={textBaseline}
183
+ textAnchor={textAlign}
184
+ transform={transitionProps.textTransform}
185
+ >
186
+ {`${tick.value}`}
187
+ </animated.text>
188
+ ) : null}
189
+ </animated.g>
190
+ );
191
+ })
192
+ : null}
193
+
194
+ {variant === AxisVariant.default ||
195
+ variant === AxisVariant.line ||
196
+ variant === AxisVariant.lineTick ? (
197
+ <animated.line
198
+ className={`${Axis.className}__line`}
199
+ x1={0}
200
+ x2={
201
+ config.immediate
202
+ ? axis === 'x'
203
+ ? length
204
+ : 0
205
+ : animatedProps.lineX2
206
+ }
207
+ y1={0}
208
+ y2={
209
+ config.immediate
210
+ ? axis === 'x'
211
+ ? 0
212
+ : length
213
+ : animatedProps.lineY2
214
+ }
215
+ />
216
+ ) : null}
217
+ {legendNode}
218
+ </StyledAxis>
219
+ );
220
+ });
221
+ Axis.className = CLASSNAME;
222
+ Axis.defaultProps = DEFAULT_PROPS;
223
+ Axis.displayName = COMPONENT_NAME;
@@ -0,0 +1,132 @@
1
+ import {
2
+ AnyScale,
3
+ Coordinates,
4
+ ScaleValue,
5
+ ScaleWithBandwidth,
6
+ TicksSpec,
7
+ } from '../../types';
8
+
9
+ const getScaleTicks = (scale: AnyScale, spec?: TicksSpec) => {
10
+ // specific values
11
+ if (Array.isArray(spec)) {
12
+ return spec;
13
+ }
14
+
15
+ // continuous scales
16
+ if ('ticks' in scale) {
17
+ // default behaviour
18
+ if (spec === undefined) {
19
+ return scale.ticks();
20
+ }
21
+
22
+ // specific tick count
23
+ if (
24
+ typeof spec === 'number' &&
25
+ isFinite(spec) &&
26
+ Math.floor(spec) === spec
27
+ ) {
28
+ return scale.ticks(spec);
29
+ }
30
+ }
31
+
32
+ // non linear scale default
33
+ return scale.domain();
34
+ };
35
+
36
+ const centerScale = (scale: ScaleWithBandwidth) => {
37
+ const bandwidth = scale.bandwidth();
38
+
39
+ if (bandwidth === 0) return scale;
40
+
41
+ let offset = bandwidth / 2;
42
+ if (scale.round()) {
43
+ offset = Math.round(offset);
44
+ }
45
+
46
+ return <T extends ScaleValue>(d: T) => (scale(d) ?? 0) + offset;
47
+ };
48
+
49
+ export const computeTicks = ({
50
+ axis,
51
+ scale,
52
+ ticksPosition,
53
+ tickValues,
54
+ tickSize,
55
+ tickPadding,
56
+ tickRotation,
57
+ }: {
58
+ axis: 'x' | 'y';
59
+ scale: AnyScale;
60
+ ticksPosition?: 'after' | 'before';
61
+ tickValues?: TicksSpec;
62
+ tickSize: number;
63
+ tickPadding: number;
64
+ tickRotation: number;
65
+ }) => {
66
+ const values = getScaleTicks(scale, tickValues);
67
+
68
+ const position = 'bandwidth' in scale ? centerScale(scale) : scale;
69
+ const line = { lineX: 0, lineY: 0 };
70
+ const text = { textX: 0, textY: 0 };
71
+
72
+ const isRTL = typeof document === 'object' ? document.dir === 'rtl' : false;
73
+ let translate: (value: ScaleValue) => Coordinates;
74
+ let textAlign = 'middle';
75
+ let textBaseline = 'central';
76
+
77
+ if (axis === 'x') {
78
+ translate = (d) => ({ x: position(d) ?? 0, y: 0 });
79
+
80
+ line.lineY = tickSize * (ticksPosition === 'after' ? 1 : -1);
81
+ text.textY =
82
+ (tickSize + tickPadding) * (ticksPosition === 'after' ? 1 : -1);
83
+
84
+ if (ticksPosition === 'after') {
85
+ textBaseline = 'text-before-edge';
86
+ } else {
87
+ textBaseline = 'alphabetic';
88
+ }
89
+
90
+ if (tickRotation === 0) {
91
+ textAlign = 'middle';
92
+ } else if (
93
+ (ticksPosition === 'after' && tickRotation < 0) ||
94
+ (ticksPosition === 'before' && tickRotation > 0)
95
+ ) {
96
+ textAlign = isRTL ? 'start' : 'end';
97
+ textBaseline = 'middle';
98
+ } else if (
99
+ (ticksPosition === 'after' && tickRotation > 0) ||
100
+ (ticksPosition === 'before' && tickRotation < 0)
101
+ ) {
102
+ textAlign = isRTL ? 'end' : 'start';
103
+ textBaseline = 'middle';
104
+ }
105
+ } else {
106
+ translate = (d) => ({ x: 0, y: position(d) ?? 0 });
107
+
108
+ line.lineX = tickSize * (ticksPosition === 'after' ? 1 : -1);
109
+ text.textX =
110
+ (tickSize + tickPadding) * (ticksPosition === 'after' ? 1 : -1);
111
+
112
+ if (ticksPosition === 'after') {
113
+ textAlign = 'start';
114
+ } else {
115
+ textAlign = 'end';
116
+ }
117
+ }
118
+
119
+ const ticks = values.map((value: ScaleValue) => ({
120
+ key: value instanceof Date ? `${value.valueOf()}` : `${value}`,
121
+ value,
122
+ ...translate(value),
123
+ ...line,
124
+ ...text,
125
+ }));
126
+
127
+ return {
128
+ ticks,
129
+ textAlign,
130
+ textBaseline,
131
+ };
132
+ };
@@ -0,0 +1,3 @@
1
+ export * from './Axis';
2
+ export * from './types';
3
+ export * from './styles';
@@ -0,0 +1,21 @@
1
+ import styled from 'styled-components';
2
+ import { StyledAxisProps } from './types';
3
+ import { animated } from '@react-spring/web';
4
+
5
+ /**
6
+ * Component style.
7
+ */
8
+ export const StyledAxis = styled(animated.g)<StyledAxisProps>`
9
+ .redsift-axis__line,
10
+ .redsift-axis-tick__line {
11
+ fill: none;
12
+ stroke: var(--redsift-color-neutral-black);
13
+ shape-rendering: crispEdges;
14
+ }
15
+
16
+ text {
17
+ font-family: var(--redsift-typography-font-family-poppins);
18
+ font-size: 10px;
19
+ user-select: none;
20
+ }
21
+ `;