@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,3 @@
1
+ export * from './PieChart';
2
+ export * from './types';
3
+ export * from './styles';
@@ -0,0 +1,95 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { StyledPieChartProps } from './types';
3
+ import { ChartContainer } from '../ChartContainer';
4
+
5
+ /**
6
+ * Component style.
7
+ */
8
+ export const StyledPieChart = styled(ChartContainer)<StyledPieChartProps>`
9
+ .redsift-piechart__chart-wrapper {
10
+ position: relative;
11
+ }
12
+ `;
13
+
14
+ export const StyledPieChartCenterText = styled.div<{
15
+ $maxWidth: number;
16
+ $textSize: number;
17
+ $smallTextSize: number;
18
+ }>`
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ height: 100%;
23
+ width: 100%;
24
+ display: flex;
25
+ flex-direction: column;
26
+ justify-content: center;
27
+ align-items: center;
28
+ pointer-events: none;
29
+
30
+ > * {
31
+ max-width: ${({ $maxWidth }) => $maxWidth}px;
32
+ }
33
+
34
+ > b {
35
+ font-family: var(--redsift-typography-font-family-poppins);
36
+ color: var(--redsift-color-neutral-black);
37
+ font-weight: var(--redsift-typography-font-weight-medium);
38
+ font-size: ${({ $textSize }) => $textSize}px;
39
+ line-height: ${({ $textSize }) => $textSize}px;
40
+
41
+ &:nth-child(2) {
42
+ font-weight: normal;
43
+ margin-top: 8px;
44
+ font-family: var(--redsift-typography-font-family-poppins);
45
+ font-size: ${({ $smallTextSize }) => $smallTextSize}px;
46
+ line-height: ${({ $smallTextSize }) => $smallTextSize}px;
47
+ }
48
+ }
49
+ > span {
50
+ color: var(--redsift-color-neutral-black);
51
+ font-size: ${({ $textSize }) => $textSize}px;
52
+ line-height: ${({ $textSize }) => $textSize}px;
53
+ &:nth-child(3) {
54
+ margin-top: 4px;
55
+ font-size: ${({ $smallTextSize }) => $smallTextSize}px;
56
+ line-height: ${({ $smallTextSize }) => $smallTextSize}px;
57
+ }
58
+ }
59
+ > b + span {
60
+ font-size: var(--redsift-typography-body-font-size);
61
+ font-family: var(--redsift-typography-font-family-poppins);
62
+ line-height: var(--redsift-typography-badge-line-height);
63
+ color: rgba(0, 0, 0, 0.6);
64
+ text-align: center;
65
+ }
66
+ `;
67
+
68
+ export const StyledPieChartEmptyText = styled.div<{
69
+ $maxWidth: number;
70
+ $textSize: number;
71
+ $isDonut: boolean;
72
+ }>`
73
+ position: absolute;
74
+ top: 0;
75
+ left: 0;
76
+ height: 100%;
77
+ width: 100%;
78
+ display: flex;
79
+ flex-direction: column;
80
+ justify-content: center;
81
+ align-items: center;
82
+ pointer-events: none;
83
+
84
+ > * {
85
+ max-width: ${({ $maxWidth }) => $maxWidth}px;
86
+ }
87
+
88
+ > span {
89
+ font-family: var(--redsift-typography-font-family-poppins);
90
+ color: ${({ $isDonut }) =>
91
+ $isDonut ? css`var(--redsift-color-neutral-midgrey)` : css`var(--redsift-color-neutral-black)`};
92
+ font-size: ${({ $textSize }) => $textSize}px;
93
+ line-height: ${({ $textSize }) => $textSize}px;
94
+ }
95
+ `;
@@ -0,0 +1,94 @@
1
+ import { ComponentProps, ReactElement, ReactNode } from 'react';
2
+ import { PieArcDatum as d3PieArcDatum } from 'd3-shape';
3
+ import {
4
+ ChartDimensions,
5
+ ChartSize,
6
+ ChartTheme,
7
+ ArcDatum,
8
+ TooltipVariant,
9
+ CategoryData,
10
+ CategoryDatum,
11
+ } from '../../types';
12
+ import { ValueOf } from '@redsift/design-system';
13
+ import { ArcProps } from '../Arc';
14
+ import { ChartContainerProps } from '../ChartContainer';
15
+ import { LegendProps } from '../Legend';
16
+
17
+ /**
18
+ * Component variant.
19
+ */
20
+ export const PieChartVariant = {
21
+ plain: 'plain',
22
+ spaced: 'spaced',
23
+ donut: 'donut',
24
+ spacedDonut: 'spacedDonut',
25
+ } as const;
26
+ export type PieChartVariant = ValueOf<typeof PieChartVariant>;
27
+
28
+ /**
29
+ * Component's labels variant.
30
+ */
31
+ export const PieChartLabelVariant = {
32
+ none: 'none',
33
+ internal: 'internal',
34
+ externalLabel: 'externalLabel',
35
+ externalLabelValue: 'externalLabelValue',
36
+ externalLabelPercent: 'externalLabelPercent',
37
+ } as const;
38
+ export type PieChartLabelVariant = ValueOf<typeof PieChartLabelVariant>;
39
+
40
+ interface LocaleText {
41
+ emptyChartText: string;
42
+ }
43
+
44
+ export type PieChartDimensions = ChartDimensions & {
45
+ smallFontSize: number;
46
+ fontSize: number;
47
+ innerRadius: number;
48
+ };
49
+
50
+ /**
51
+ * Component props.
52
+ */
53
+ export interface PieChartProps extends ChartContainerProps {
54
+ /** Number of categories to use, the rest being put into a new category called "Others". */
55
+ caping?: number;
56
+ /** Dataset to use to generate the chart, should be a list of objects containing a key and a value. */
57
+ data?: CategoryData;
58
+ /** Component to use if the chart is empty (replacing the default one). */
59
+ emptyComponent?: ReactNode;
60
+ /** Method to determine whether a slice is selected or not. */
61
+ isSliceSelected?: (datum: ArcDatum) => boolean | undefined;
62
+ /** Method to override the data labels. */
63
+ labelDecorator?: (datum: ArcDatum) => string;
64
+ /** Define whether the labels should be displayed inside or outside the charts and if they should contain raw or percentage values. */
65
+ labelVariant?: PieChartLabelVariant;
66
+ /** Props to forward to the Legend block. Can be used to make the legend selectable. */
67
+ legendProps?: Omit<LegendProps, 'data' | 'ref' | 'variant' | 'width'>;
68
+ /** Labels and texts. */
69
+ localeText?: LocaleText;
70
+ /** Method to be called on a click on a slice. */
71
+ onSliceClick?: (datum: ArcDatum) => void;
72
+ /** Whether a category should be displayed for categories that has been removed by the caping option. Optionaly, this prop can be used to change the label of this category. */
73
+ others?: boolean | string;
74
+ /** PieChart size. */
75
+ size?: ChartSize | PieChartDimensions;
76
+ /** Native HTML props to forward to each slice. */
77
+ sliceProps?: Omit<ComponentProps<'g'>, 'onClick' | 'ref' | 'width'>;
78
+ /** Slice role. Used to indicate that slices are to be considered buttons or links. If an onClick is provided, the slices will have the role `button` unless specifically set to `link` with this prop. */
79
+ sliceRole?: ArcProps['role'];
80
+ /** Secondary text to be displayed in the middle of the chart, between the main text and subtext. Recommended to be used with donut variants only. */
81
+ middleText?: string | ReactElement | ((data: d3PieArcDatum<CategoryDatum>[], total: number) => string | ReactElement);
82
+ /** Secondary text to be displayed in the middle of the chart, above the main text. Recommended to be used with `donut` variants only. */
83
+ subtext?: string | ReactElement | ((data: d3PieArcDatum<CategoryDatum>[], total: number) => string | ReactElement);
84
+ /** Main text to be displayed in the middle of the chart. Recommended to be used with `donut` variants only. */
85
+ text?: string | ReactElement | ((data: d3PieArcDatum<CategoryDatum>[], total: number) => string | ReactElement);
86
+ /** Color palette to use. You can choose among the list of available color palette or also choose to use the success/warning/danger theme for which you have to specify which key corresponds to which status. */
87
+ theme?: ChartTheme;
88
+ /** PieChart variant. */
89
+ variant?: PieChartVariant;
90
+ /** Tooltip variant. */
91
+ tooltipVariant?: TooltipVariant;
92
+ }
93
+
94
+ export type StyledPieChartProps = PieChartProps & {};
@@ -0,0 +1,38 @@
1
+ import { ChartSize } from '../../types';
2
+ import { PieChartDimensions } from './types';
3
+
4
+ export const sizeToDimension = (
5
+ size: ChartSize | PieChartDimensions
6
+ ): PieChartDimensions => {
7
+ if (typeof size !== 'string') {
8
+ return size;
9
+ }
10
+
11
+ switch (size) {
12
+ case ChartSize.small:
13
+ return {
14
+ width: 200,
15
+ height: 200,
16
+ smallFontSize: 13,
17
+ fontSize: 30,
18
+ innerRadius: 55,
19
+ };
20
+ case ChartSize.large:
21
+ return {
22
+ width: 300,
23
+ height: 300,
24
+ smallFontSize: 18,
25
+ fontSize: 38,
26
+ innerRadius: 80,
27
+ };
28
+ case ChartSize.medium:
29
+ default:
30
+ return {
31
+ width: 240,
32
+ height: 240,
33
+ smallFontSize: 14,
34
+ fontSize: 34,
35
+ innerRadius: 65,
36
+ };
37
+ }
38
+ };
@@ -0,0 +1,70 @@
1
+ import React, { forwardRef, RefObject, useEffect, useRef } from 'react';
2
+ import { scaleLinear as d3scaleLinear } from 'd3';
3
+
4
+ import { AnyScale, JSONArray } from '../../types';
5
+ import { ScatterPlotProps } from './types';
6
+ import { StyledScatterPlot, StyledScatterPlotEmptyText } from './styles';
7
+ import { Axis } from '../Axis';
8
+ import { sizeToDimension } from './utils';
9
+
10
+ export const EmptyScatterPlot = forwardRef<HTMLDivElement, ScatterPlotProps>(
11
+ (props, ref) => {
12
+ const {
13
+ className,
14
+ data: propsData,
15
+ emptyComponent,
16
+ localeText,
17
+ size,
18
+ ...forwardedProps
19
+ } = props;
20
+
21
+ const cache = useRef<JSONArray>();
22
+
23
+ const data = propsData;
24
+
25
+ useEffect(() => {
26
+ cache.current = data;
27
+ });
28
+
29
+ const chartDimensions = sizeToDimension(size!);
30
+ const width = chartDimensions.width;
31
+ const height = chartDimensions.height;
32
+ const margins = { top: 16, left: 48, right: 16, bottom: 48 };
33
+ const chartWidth = width - margins.left - margins.right;
34
+
35
+ return (
36
+ <StyledScatterPlot
37
+ {...forwardedProps}
38
+ className={className}
39
+ ref={ref as RefObject<HTMLDivElement>}
40
+ >
41
+ {emptyComponent ?? (
42
+ <>
43
+ <StyledScatterPlotEmptyText
44
+ $maxWidth={width}
45
+ $textSize={chartDimensions.fontSize / 2}
46
+ >
47
+ <span>{localeText?.emptyChartText}</span>
48
+ </StyledScatterPlotEmptyText>
49
+ <svg width={width} height={height}>
50
+ <g transform={`translate(${margins.left},${margins.top})`}>
51
+ <Axis
52
+ position="bottom"
53
+ length={width - 32}
54
+ scale={
55
+ d3scaleLinear()
56
+ .domain([])
57
+ .range([0, chartWidth]) as AnyScale
58
+ }
59
+ x={0}
60
+ y={height}
61
+ tickValues={4}
62
+ />
63
+ </g>
64
+ </svg>
65
+ </>
66
+ )}
67
+ </StyledScatterPlot>
68
+ );
69
+ }
70
+ );
@@ -0,0 +1,20 @@
1
+ import React, { forwardRef, RefObject } from 'react';
2
+
3
+ import { ScatterPlotProps } from './types';
4
+ import { StyledScatterPlot } from './styles';
5
+
6
+ export const LoadingScatterPlot = forwardRef<HTMLDivElement, ScatterPlotProps>(
7
+ (props, ref) => {
8
+ const { className, ...forwardedProps } = props;
9
+
10
+ return (
11
+ <StyledScatterPlot
12
+ {...forwardedProps}
13
+ className={className}
14
+ ref={ref as RefObject<HTMLDivElement>}
15
+ >
16
+ Loading...
17
+ </StyledScatterPlot>
18
+ );
19
+ }
20
+ );
@@ -0,0 +1,321 @@
1
+ import React, { forwardRef, RefObject, useEffect, useRef, useState } from 'react';
2
+ import {
3
+ BrushBehavior as d3BrushBehavior,
4
+ descending as d3descending,
5
+ extent as d3extent,
6
+ max as d3max,
7
+ min as d3min,
8
+ scaleLinear as d3scaleLinear,
9
+ scaleSqrt as d3scaleSqrt,
10
+ select as d3select,
11
+ } from 'd3';
12
+
13
+ import { AnyScale, JSONArray, LabelVariant } from '../../types';
14
+ import { ScatterPlotLabelVariant, ScatterPlotProps, ScatterPlotVariant } from './types';
15
+ import { StyledScatterPlot } from './styles';
16
+ import { useZoom, useColor, useBrush } from '../../hooks';
17
+ import { Axis, AxisVariant } from '../Axis';
18
+ import { Legend } from '../Legend';
19
+ import { Dot } from '../Dot';
20
+ import { BASE_NUMBER_OF_TICKS, countBy, group, sizeToDimension } from './utils';
21
+ import { Button, Flexbox, Text } from '@redsift/design-system';
22
+ import { StyledChartContainerCaption } from '../ChartContainer';
23
+ import { mdiChevronDown, mdiChevronRight, mdiMouse } from '@redsift/icons';
24
+ import { Popover } from '@redsift/popovers';
25
+
26
+ interface RenderedScatterPlotProps extends Required<Pick<ScatterPlotProps, 'data'>>, Omit<ScatterPlotProps, 'data'> {}
27
+
28
+ export const RenderedScatterPlot = forwardRef<HTMLDivElement, RenderedScatterPlotProps>((props, ref) => {
29
+ const {
30
+ isBrushable,
31
+ caption,
32
+ className,
33
+ data: propsData,
34
+ dotRole,
35
+ hideControlKeyPanel,
36
+ id,
37
+ isDotSelected,
38
+ labelDecorator,
39
+ labelVariant,
40
+ legendProps,
41
+ onBrush,
42
+ onBrushEnd,
43
+ onDotClick,
44
+ size,
45
+ theme,
46
+ tooltipVariant,
47
+ variant,
48
+ xAxisVariant,
49
+ xAxisPlacement,
50
+ yAxisVariant,
51
+ yAxisPlacement,
52
+ ...forwardedProps
53
+ } = props;
54
+
55
+ const cache = useRef<JSONArray>();
56
+
57
+ const data = propsData.filter(
58
+ (datum) =>
59
+ datum.value &&
60
+ typeof datum.key[0] === 'number' &&
61
+ !Number.isNaN(datum.key[0]) &&
62
+ typeof datum.key[1] === 'number' &&
63
+ !Number.isNaN(datum.key[1])
64
+ );
65
+
66
+ useEffect(() => {
67
+ cache.current = data;
68
+ });
69
+
70
+ const chartDimensions = sizeToDimension(size!);
71
+ const width = chartDimensions.width;
72
+ const height = chartDimensions.height;
73
+ const margins = {
74
+ top: xAxisVariant === AxisVariant.default || xAxisVariant === AxisVariant.tickValue ? 24 : 8,
75
+ left: yAxisVariant === AxisVariant.default || yAxisVariant === AxisVariant.tickValue ? 48 : 8,
76
+ right: yAxisVariant === AxisVariant.default || yAxisVariant === AxisVariant.tickValue ? 48 : 8,
77
+ bottom: xAxisVariant === AxisVariant.default || xAxisVariant === AxisVariant.tickValue ? 24 : 8,
78
+ };
79
+ const chartHeight = height - margins.top - margins.bottom;
80
+ const chartWidth = width - margins.left - margins.right;
81
+ const minSize = d3min([chartWidth, chartHeight]) as number;
82
+
83
+ const extendedScaleX = (() => {
84
+ const domain = d3extent(data, (d) => d.key[0]) as [number, number];
85
+ const gap = domain[1] - domain[0];
86
+ domain[0] -= gap * 0.1;
87
+ domain[1] += gap * 0.1;
88
+ return d3scaleLinear().domain(domain).range([0, chartWidth]).nice();
89
+ })();
90
+ const extendedScaleY = (() => {
91
+ const domain = d3extent(data, (d) => d.key[1]) as [number, number];
92
+ const gap = domain[1] - domain[0];
93
+ domain[0] -= gap * 0.1;
94
+ domain[1] += gap * 0.1;
95
+ return d3scaleLinear().domain(domain).range([chartHeight, 0]).nice();
96
+ })();
97
+
98
+ const hasCategory = data[0] && data[0].key.length >= 3 && data[0].key[2] !== null && data[0].key[2] !== undefined;
99
+ const countsByCategory = hasCategory ? countBy(data) : undefined;
100
+ const colorScale = useColor({
101
+ data: countsByCategory || data,
102
+ theme: theme!,
103
+ category: 'key',
104
+ });
105
+
106
+ const svgRef = useRef<SVGSVGElement>();
107
+ const brushRef = useRef<d3BrushBehavior<unknown>>();
108
+ const svgBrushRef = useRef<SVGGElement>();
109
+ const { scaleX, scaleY, transform } = useZoom({
110
+ svgRef,
111
+ scaleX: extendedScaleX,
112
+ scaleY: extendedScaleY,
113
+ size,
114
+ onZoom: () => {
115
+ if (brushRef.current && svgBrushRef.current) {
116
+ brushRef.current.clear(d3select(svgBrushRef.current));
117
+
118
+ onBrushEnd?.(null);
119
+ }
120
+ },
121
+ });
122
+ useBrush({
123
+ brushRef,
124
+ svgRef: svgBrushRef,
125
+ extent: [
126
+ [0, 0],
127
+ [chartWidth, chartHeight],
128
+ ],
129
+ scaleX,
130
+ scaleY,
131
+ isBrushable,
132
+ isGridded: variant === ScatterPlotVariant.gridded,
133
+ onBrush,
134
+ onBrushEnd,
135
+ });
136
+
137
+ const circles =
138
+ variant === ScatterPlotVariant.gridded
139
+ ? group(data, scaleX, scaleY).sort((a, b) => d3descending(a.points.length, b.points.length))
140
+ : data.map((d) => ({
141
+ category: d.key[2],
142
+ x: d.key[0],
143
+ y: d.key[1],
144
+ data: {
145
+ key: d.key,
146
+ value: 1,
147
+ },
148
+ points: [d],
149
+ }));
150
+ const globalSize =
151
+ variant === ScatterPlotVariant.gridded
152
+ ? d3scaleSqrt()
153
+ .domain([1, Math.max(d3max(circles, (d) => d.points.length)!, 1)])
154
+ .range([3, minSize / BASE_NUMBER_OF_TICKS / 2])
155
+ : undefined;
156
+ const legendWidth = useRef<string>();
157
+ if (countsByCategory && !legendWidth.current) {
158
+ legendWidth.current = `${
159
+ Math.max(...countsByCategory.map((d) => d.key.length + String(d.value).length)) * 8 + 32
160
+ }px`;
161
+ }
162
+
163
+ const [isKeyPanelOpen, setIsKeyPanelOpen] = useState(false);
164
+
165
+ return (
166
+ <StyledScatterPlot {...forwardedProps} id={id} className={className} ref={ref as RefObject<HTMLDivElement>}>
167
+ <Flexbox flexDirection="column" alignItems="center" gap="8">
168
+ {!hideControlKeyPanel ? (
169
+ <Flexbox width={width} position="absolute">
170
+ <Flexbox
171
+ flexDirection="column"
172
+ alignItems="flex-end"
173
+ position="absolute"
174
+ top={`${margins.top + 16}px`}
175
+ right={`${margins.right + 16}px`}
176
+ >
177
+ <Popover placement="bottom-end" isOpen={isKeyPanelOpen} onOpen={setIsKeyPanelOpen}>
178
+ <Popover.Trigger>
179
+ <Button
180
+ variant="secondary"
181
+ leftIcon={mdiMouse}
182
+ rightIcon={isKeyPanelOpen ? mdiChevronDown : mdiChevronRight}
183
+ color="question"
184
+ style={{
185
+ border: '1px solid var(--redsift-color-neutral-midgrey)',
186
+ gap: '4px',
187
+ }}
188
+ />
189
+ </Popover.Trigger>
190
+ <Popover.Content flexDirection="column" alignItems="flex-start">
191
+ <Text margin="8px 16px 0" fontSize="13px">
192
+ Zoom - Mouse wheel
193
+ </Text>
194
+ <Text margin="0 16px" fontSize="13px">
195
+ Pan - Left click and drag
196
+ </Text>
197
+ <Text margin="0 16px 8px" fontSize="13px">
198
+ Select - Hold shift, left click and drag
199
+ </Text>
200
+ </Popover.Content>
201
+ </Popover>
202
+ </Flexbox>
203
+ </Flexbox>
204
+ ) : null}
205
+ <svg ref={svgRef as RefObject<SVGSVGElement>} width={width} height={height}>
206
+ <g ref={svgBrushRef as RefObject<SVGGElement>} transform={`translate(${margins.left},${margins.top})`} />
207
+ <g transform={`translate(${margins.left},${margins.top})`}>
208
+ <g>
209
+ {circles.map((circle, index) => {
210
+ const scaleXDomain = scaleX.domain();
211
+ const scaleYDomain = scaleY.domain();
212
+
213
+ if (
214
+ circle.x! < scaleXDomain[0] ||
215
+ circle.x! > scaleXDomain[1] ||
216
+ circle.y! < scaleYDomain[0] ||
217
+ circle.y! > scaleYDomain[1]
218
+ ) {
219
+ return null;
220
+ }
221
+
222
+ const to = {
223
+ ...circle,
224
+ data: {
225
+ ...circle.data,
226
+ percent: circle.category
227
+ ? circle.data.value / countsByCategory?.find(({ key }) => key === circle.category)?.value!
228
+ : undefined,
229
+ },
230
+ r:
231
+ variant === ScatterPlotVariant.gridded
232
+ ? globalSize!(circle.points.length) / (transform.k < 1 ? transform.k : 1)
233
+ : 4,
234
+ };
235
+
236
+ return (
237
+ <Dot
238
+ color={colorScale?.(circle.category!)}
239
+ data={to}
240
+ isSelected={Boolean(isDotSelected?.(to))}
241
+ key={`circle _${index}`}
242
+ labelDecorator={labelDecorator}
243
+ onClick={onDotClick}
244
+ role={dotRole}
245
+ scaleX={scaleX}
246
+ scaleY={scaleY}
247
+ tooltipVariant={tooltipVariant}
248
+ />
249
+ );
250
+ })}
251
+ </g>
252
+ </g>
253
+ <g transform={`translate(${margins.left},${margins.top})`}>
254
+ {['bottom', 'both'].includes(xAxisPlacement!) ? (
255
+ <Axis
256
+ position="bottom"
257
+ length={chartWidth}
258
+ scale={scaleX as AnyScale}
259
+ x={0}
260
+ y={chartHeight}
261
+ tickValues={8}
262
+ variant={xAxisVariant}
263
+ />
264
+ ) : null}
265
+ {['top', 'both'].includes(xAxisPlacement!) ? (
266
+ <Axis
267
+ position="top"
268
+ length={chartWidth}
269
+ scale={scaleX as AnyScale}
270
+ x={0}
271
+ y={0}
272
+ tickValues={8}
273
+ variant={xAxisVariant}
274
+ />
275
+ ) : null}
276
+ {['left', 'both'].includes(yAxisPlacement!) ? (
277
+ <Axis
278
+ position="left"
279
+ length={chartHeight}
280
+ scale={scaleY as AnyScale}
281
+ x={0}
282
+ y={0}
283
+ tickValues={8}
284
+ variant={yAxisVariant}
285
+ />
286
+ ) : null}
287
+ {['right', 'both'].includes(yAxisPlacement!) ? (
288
+ <Axis
289
+ position="right"
290
+ length={chartHeight}
291
+ scale={scaleY as AnyScale}
292
+ x={chartWidth}
293
+ y={0}
294
+ tickValues={8}
295
+ variant={yAxisVariant}
296
+ />
297
+ ) : null}
298
+ </g>
299
+ </svg>
300
+ <StyledChartContainerCaption width={chartWidth - 48}>{caption}</StyledChartContainerCaption>
301
+ </Flexbox>
302
+ {hasCategory && labelVariant !== ScatterPlotLabelVariant.none ? (
303
+ <Legend
304
+ data={countsByCategory!.map((d) => ({
305
+ ...d,
306
+ color: colorScale?.(d.key)!,
307
+ }))}
308
+ variant={
309
+ labelVariant === ScatterPlotLabelVariant.externalLabelValue
310
+ ? LabelVariant.value
311
+ : labelVariant === ScatterPlotLabelVariant.externalLabelPercent
312
+ ? LabelVariant.percent
313
+ : LabelVariant.label
314
+ }
315
+ width={legendWidth.current}
316
+ {...legendProps}
317
+ />
318
+ ) : null}
319
+ </StyledScatterPlot>
320
+ );
321
+ });