@hero-design/rn 8.99.4 → 8.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -3
- package/CHANGELOG.md +17 -0
- package/es/index.js +5621 -690
- package/jest.config.js +1 -1
- package/lib/index.js +5545 -613
- package/package.json +4 -2
- package/src/components/Avatar/AvatarStack/utils.ts +6 -4
- package/src/components/Badge/Status.tsx +1 -1
- package/src/components/Badge/__tests__/Status.spec.tsx +20 -0
- package/src/components/Badge/__tests__/__snapshots__/Status.spec.tsx.snap +2 -0
- package/src/components/Chart/ChartSelect/StyledChartSelect.tsx +9 -0
- package/src/components/Chart/ChartSelect/__tests__/StyledChartSelect.spec.tsx +15 -0
- package/src/components/Chart/ChartSelect/__tests__/__snapshots__/StyledChartSelect.spec.tsx.snap +20 -0
- package/src/components/Chart/ChartSelect/__tests__/index.spec.tsx +111 -0
- package/src/components/Chart/ChartSelect/index.tsx +137 -0
- package/src/components/Chart/ColumnChart/ColumnChartContent.tsx +84 -0
- package/src/components/Chart/ColumnChart/Segment.tsx +66 -0
- package/src/components/Chart/ColumnChart/StackedSegment.tsx +99 -0
- package/src/components/Chart/ColumnChart/StyledColumnChart.tsx +9 -0
- package/src/components/Chart/ColumnChart/__tests__/ColumnChartContent.spec.tsx +68 -0
- package/src/components/Chart/ColumnChart/__tests__/Segment.spec.tsx +99 -0
- package/src/components/Chart/ColumnChart/__tests__/StackedSegment.spec.tsx +115 -0
- package/src/components/Chart/ColumnChart/__tests__/__snapshots__/StackedSegment.spec.tsx.snap +120 -0
- package/src/components/Chart/ColumnChart/__tests__/__snapshots__/index.spec.tsx.snap +1405 -0
- package/src/components/Chart/ColumnChart/__tests__/index.spec.tsx +134 -0
- package/src/components/Chart/ColumnChart/index.tsx +216 -0
- package/src/components/Chart/Line/Line.tsx +81 -0
- package/src/components/Chart/Line/__tests__/Line.spec.tsx +148 -0
- package/src/components/Chart/Line/__tests__/__snapshots__/Line.spec.tsx.snap +56 -0
- package/src/components/Chart/Line/__tests__/__snapshots__/index.spec.tsx.snap +1461 -0
- package/src/components/Chart/Line/__tests__/index.spec.tsx +112 -0
- package/src/components/Chart/Line/index.tsx +143 -0
- package/src/components/Chart/StyledChart.tsx +16 -0
- package/src/components/Chart/index.tsx +13 -0
- package/src/components/Chart/shared/AxisLabel.tsx +25 -0
- package/src/components/Chart/shared/ChartFrame.tsx +131 -0
- package/src/components/Chart/shared/ChartHeader.tsx +19 -0
- package/src/components/Chart/shared/EmptyState.tsx +83 -0
- package/src/components/Chart/shared/XAxis.tsx +69 -0
- package/src/components/Chart/shared/XAxisGrid.tsx +42 -0
- package/src/components/Chart/shared/YAxis.tsx +104 -0
- package/src/components/Chart/shared/YAxisGrid.tsx +58 -0
- package/src/components/Chart/shared/__tests__/ChartFrame.spec.tsx +125 -0
- package/src/components/Chart/shared/__tests__/ChartHeader.spec.tsx +22 -0
- package/src/components/Chart/shared/__tests__/EmptyState.spec.tsx +29 -0
- package/src/components/Chart/shared/__tests__/XAXisGrid.spec.tsx +30 -0
- package/src/components/Chart/shared/__tests__/XAxis.spec.tsx +42 -0
- package/src/components/Chart/shared/__tests__/YAxis.spec.tsx +72 -0
- package/src/components/Chart/shared/__tests__/YAxisGrid.spec.tsx +35 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/ChartFrame.spec.tsx.snap +3058 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/ChartHeader.spec.tsx.snap +160 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/EmptyState.spec.tsx.snap +155 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/XAXisGrid.spec.tsx.snap +197 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/XAxis.spec.tsx.snap +369 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/YAxis.spec.tsx.snap +1013 -0
- package/src/components/Chart/shared/__tests__/__snapshots__/YAxisGrid.spec.tsx.snap +228 -0
- package/src/components/Chart/shared/__tests__/niceNumbers.spec.tsx +127 -0
- package/src/components/Chart/shared/constants.ts +2 -0
- package/src/components/Chart/shared/hooks/useColorScale.ts +25 -0
- package/src/components/Chart/shared/hooks/useGenerateTicks.ts +27 -0
- package/src/components/Chart/shared/hooks/useScaleBandX.ts +17 -0
- package/src/components/Chart/shared/hooks/useScaleLinearY.ts +30 -0
- package/src/components/Chart/shared/niceNumbers.ts +68 -0
- package/src/components/Chart/types.ts +100 -0
- package/src/components/Select/MultiSelect/OptionList.tsx +1 -1
- package/src/components/Select/MultiSelect/index.tsx +2 -6
- package/src/components/Select/MultiSelect/utils.ts +1 -1
- package/src/components/Select/SingleSelect/OptionList.tsx +1 -1
- package/src/components/Select/SingleSelect/index.tsx +2 -7
- package/src/components/Select/__tests__/helpers.spec.tsx +0 -36
- package/src/components/Select/helpers.tsx +0 -75
- package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/Option.spec.tsx.snap +3 -0
- package/src/components/Switch/SelectorSwitch/__tests__/__snapshots__/index.spec.tsx.snap +1 -0
- package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabs.spec.tsx.snap +3 -0
- package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabsHeader.spec.tsx.snap +2 -0
- package/src/components/Tabs/__tests__/__snapshots__/TabWithBadge.spec.tsx.snap +1 -0
- package/src/components/Tabs/__tests__/__snapshots__/index.spec.tsx.snap +3 -0
- package/src/index.ts +2 -0
- package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +28 -0
- package/src/theme/components/chart.ts +28 -0
- package/src/theme/components/columnChart.ts +15 -0
- package/src/theme/getTheme.ts +6 -0
- package/src/types.ts +4 -0
- package/src/utils/__tests__/helpers.spec.ts +36 -1
- package/src/utils/helpers.ts +76 -1
- package/stats/8.100.0/rn-stats.html +4842 -0
- package/stats/8.99.4/rn-stats.html +1 -1
- package/types/components/Badge/Status.d.ts +0 -1
- package/types/components/Chart/ChartSelect/StyledChartSelect.d.ts +8 -0
- package/types/components/Chart/ChartSelect/index.d.ts +63 -0
- package/types/components/Chart/ColumnChart/ColumnChartContent.d.ts +25 -0
- package/types/components/Chart/ColumnChart/Segment.d.ts +14 -0
- package/types/components/Chart/ColumnChart/StackedSegment.d.ts +28 -0
- package/types/components/Chart/ColumnChart/StyledColumnChart.d.ts +8 -0
- package/types/components/Chart/ColumnChart/index.d.ts +80 -0
- package/types/components/Chart/Line/Line.d.ts +21 -0
- package/types/components/Chart/Line/index.d.ts +35 -0
- package/types/components/Chart/StyledChart.d.ts +9 -0
- package/types/components/Chart/index.d.ts +9 -0
- package/types/components/Chart/shared/AxisLabel.d.ts +7 -0
- package/types/components/Chart/shared/ChartFrame.d.ts +30 -0
- package/types/components/Chart/shared/ChartHeader.d.ts +8 -0
- package/types/components/Chart/shared/EmptyState.d.ts +8 -0
- package/types/components/Chart/shared/XAxis.d.ts +8 -0
- package/types/components/Chart/shared/XAxisGrid.d.ts +8 -0
- package/types/components/Chart/shared/YAxis.d.ts +10 -0
- package/types/components/Chart/shared/YAxisGrid.d.ts +10 -0
- package/types/components/Chart/shared/constants.d.ts +2 -0
- package/types/components/Chart/shared/hooks/useColorScale.d.ts +7 -0
- package/types/components/Chart/shared/hooks/useGenerateTicks.d.ts +6 -0
- package/types/components/Chart/shared/hooks/useScaleBandX.d.ts +8 -0
- package/types/components/Chart/shared/hooks/useScaleLinearY.d.ts +9 -0
- package/types/components/Chart/shared/niceNumbers.d.ts +12 -0
- package/types/components/Chart/types.d.ts +84 -0
- package/types/components/Select/helpers.d.ts +0 -5
- package/types/index.d.ts +2 -1
- package/types/theme/components/chart.d.ts +22 -0
- package/types/theme/components/columnChart.d.ts +10 -0
- package/types/theme/getTheme.d.ts +4 -0
- package/types/types.d.ts +3 -1
- package/types/utils/helpers.d.ts +5 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`YAxisGrid should render correctly 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
style={
|
|
6
|
+
{
|
|
7
|
+
"flex": 1,
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
>
|
|
11
|
+
<RNSVGGroup
|
|
12
|
+
fill={
|
|
13
|
+
{
|
|
14
|
+
"payload": 4278190080,
|
|
15
|
+
"type": 0,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
testID="y-axis-grid"
|
|
19
|
+
>
|
|
20
|
+
<RNSVGLine
|
|
21
|
+
fill={
|
|
22
|
+
{
|
|
23
|
+
"payload": 4278190080,
|
|
24
|
+
"type": 0,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
propList={
|
|
28
|
+
[
|
|
29
|
+
"stroke",
|
|
30
|
+
"strokeDasharray",
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
stroke={
|
|
34
|
+
{
|
|
35
|
+
"payload": 4293454314,
|
|
36
|
+
"type": 0,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
strokeDasharray={
|
|
40
|
+
[
|
|
41
|
+
4,
|
|
42
|
+
4,
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
testID="y-axis-grid-0"
|
|
46
|
+
x1={0}
|
|
47
|
+
x2={100}
|
|
48
|
+
y1={100}
|
|
49
|
+
y2={100}
|
|
50
|
+
/>
|
|
51
|
+
<RNSVGLine
|
|
52
|
+
fill={
|
|
53
|
+
{
|
|
54
|
+
"payload": 4278190080,
|
|
55
|
+
"type": 0,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
propList={
|
|
59
|
+
[
|
|
60
|
+
"stroke",
|
|
61
|
+
"strokeDasharray",
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
stroke={
|
|
65
|
+
{
|
|
66
|
+
"payload": 4293454314,
|
|
67
|
+
"type": 0,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
strokeDasharray={
|
|
71
|
+
[
|
|
72
|
+
4,
|
|
73
|
+
4,
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
testID="y-axis-grid-2000"
|
|
77
|
+
x1={0}
|
|
78
|
+
x2={100}
|
|
79
|
+
y1={80}
|
|
80
|
+
y2={80}
|
|
81
|
+
/>
|
|
82
|
+
<RNSVGLine
|
|
83
|
+
fill={
|
|
84
|
+
{
|
|
85
|
+
"payload": 4278190080,
|
|
86
|
+
"type": 0,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
propList={
|
|
90
|
+
[
|
|
91
|
+
"stroke",
|
|
92
|
+
"strokeDasharray",
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
stroke={
|
|
96
|
+
{
|
|
97
|
+
"payload": 4293454314,
|
|
98
|
+
"type": 0,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
strokeDasharray={
|
|
102
|
+
[
|
|
103
|
+
4,
|
|
104
|
+
4,
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
testID="y-axis-grid-4000"
|
|
108
|
+
x1={0}
|
|
109
|
+
x2={100}
|
|
110
|
+
y1={60}
|
|
111
|
+
y2={60}
|
|
112
|
+
/>
|
|
113
|
+
<RNSVGLine
|
|
114
|
+
fill={
|
|
115
|
+
{
|
|
116
|
+
"payload": 4278190080,
|
|
117
|
+
"type": 0,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
propList={
|
|
121
|
+
[
|
|
122
|
+
"stroke",
|
|
123
|
+
"strokeDasharray",
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
stroke={
|
|
127
|
+
{
|
|
128
|
+
"payload": 4293454314,
|
|
129
|
+
"type": 0,
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
strokeDasharray={
|
|
133
|
+
[
|
|
134
|
+
4,
|
|
135
|
+
4,
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
testID="y-axis-grid-6000"
|
|
139
|
+
x1={0}
|
|
140
|
+
x2={100}
|
|
141
|
+
y1={40}
|
|
142
|
+
y2={40}
|
|
143
|
+
/>
|
|
144
|
+
<RNSVGLine
|
|
145
|
+
fill={
|
|
146
|
+
{
|
|
147
|
+
"payload": 4278190080,
|
|
148
|
+
"type": 0,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
propList={
|
|
152
|
+
[
|
|
153
|
+
"stroke",
|
|
154
|
+
"strokeDasharray",
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
stroke={
|
|
158
|
+
{
|
|
159
|
+
"payload": 4293454314,
|
|
160
|
+
"type": 0,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
strokeDasharray={
|
|
164
|
+
[
|
|
165
|
+
4,
|
|
166
|
+
4,
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
testID="y-axis-grid-8000"
|
|
170
|
+
x1={0}
|
|
171
|
+
x2={100}
|
|
172
|
+
y1={19.999999999999996}
|
|
173
|
+
y2={19.999999999999996}
|
|
174
|
+
/>
|
|
175
|
+
<RNSVGLine
|
|
176
|
+
fill={
|
|
177
|
+
{
|
|
178
|
+
"payload": 4278190080,
|
|
179
|
+
"type": 0,
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
propList={
|
|
183
|
+
[
|
|
184
|
+
"stroke",
|
|
185
|
+
"strokeDasharray",
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
stroke={
|
|
189
|
+
{
|
|
190
|
+
"payload": 4293454314,
|
|
191
|
+
"type": 0,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
strokeDasharray={
|
|
195
|
+
[
|
|
196
|
+
4,
|
|
197
|
+
4,
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
testID="y-axis-grid-10000"
|
|
201
|
+
x1={0}
|
|
202
|
+
x2={100}
|
|
203
|
+
y1={0}
|
|
204
|
+
y2={0}
|
|
205
|
+
/>
|
|
206
|
+
</RNSVGGroup>
|
|
207
|
+
<View
|
|
208
|
+
pointerEvents="box-none"
|
|
209
|
+
position="bottom"
|
|
210
|
+
style={
|
|
211
|
+
[
|
|
212
|
+
{
|
|
213
|
+
"bottom": 0,
|
|
214
|
+
"elevation": 9999,
|
|
215
|
+
"flexDirection": "column-reverse",
|
|
216
|
+
"left": 0,
|
|
217
|
+
"paddingHorizontal": 24,
|
|
218
|
+
"paddingVertical": 16,
|
|
219
|
+
"position": "absolute",
|
|
220
|
+
"right": 0,
|
|
221
|
+
"top": 0,
|
|
222
|
+
},
|
|
223
|
+
undefined,
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
/>
|
|
227
|
+
</View>
|
|
228
|
+
`;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createNiceScale,
|
|
3
|
+
maxValueFromDataSet,
|
|
4
|
+
minValueFromDataSet,
|
|
5
|
+
} from '../niceNumbers';
|
|
6
|
+
|
|
7
|
+
describe('createNiceScale', () => {
|
|
8
|
+
it('calculates niceMin, niceMax, and tickSpacing correctly', () => {
|
|
9
|
+
const result = createNiceScale(0, 100, 10);
|
|
10
|
+
expect(result.niceMin).toBe(0);
|
|
11
|
+
expect(result.niceMax).toBe(100);
|
|
12
|
+
expect(result.tickSpacing).toBe(10);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('handles different input values', () => {
|
|
16
|
+
const result = createNiceScale(-50, 50, 5);
|
|
17
|
+
expect(result.niceMin).toBe(-60);
|
|
18
|
+
expect(result.niceMax).toBe(60);
|
|
19
|
+
expect(result.tickSpacing).toBe(20);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('handles small input range', () => {
|
|
23
|
+
const result = createNiceScale(1, 2, 2);
|
|
24
|
+
expect(result.niceMin).toBe(1);
|
|
25
|
+
expect(result.niceMax).toBe(2);
|
|
26
|
+
expect(result.tickSpacing).toBe(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Test cases for different fraction ranges with rounding
|
|
30
|
+
it('handles range with fraction < 1.5', () => {
|
|
31
|
+
const result = createNiceScale(0, 12, 5);
|
|
32
|
+
expect(result.niceMin).toBe(0);
|
|
33
|
+
expect(result.niceMax).toBe(15);
|
|
34
|
+
expect(result.tickSpacing).toBe(5);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('handles range with fraction < 3', () => {
|
|
38
|
+
const result = createNiceScale(0, 25, 5);
|
|
39
|
+
expect(result.niceMin).toBe(0);
|
|
40
|
+
expect(result.niceMax).toBe(30);
|
|
41
|
+
expect(result.tickSpacing).toBe(10);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('handles range with fraction < 7', () => {
|
|
45
|
+
const result = createNiceScale(0, 60, 5);
|
|
46
|
+
expect(result.niceMin).toBe(0);
|
|
47
|
+
expect(result.niceMax).toBe(60);
|
|
48
|
+
expect(result.tickSpacing).toBe(20);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('handles range with fraction >= 7', () => {
|
|
52
|
+
const result = createNiceScale(0, 80, 5);
|
|
53
|
+
expect(result.niceMin).toBe(0);
|
|
54
|
+
expect(result.niceMax).toBe(80);
|
|
55
|
+
expect(result.tickSpacing).toBe(20);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Test cases for different fraction ranges without rounding
|
|
59
|
+
it('handles range with fraction <= 1 without rounding', () => {
|
|
60
|
+
const result = createNiceScale(0, 8, 5);
|
|
61
|
+
expect(result.niceMin).toBe(0);
|
|
62
|
+
expect(result.niceMax).toBe(8);
|
|
63
|
+
expect(result.tickSpacing).toBe(2);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('handles range with fraction <= 2 without rounding', () => {
|
|
67
|
+
const result = createNiceScale(0, 15, 5);
|
|
68
|
+
expect(result.niceMin).toBe(0);
|
|
69
|
+
expect(result.niceMax).toBe(15);
|
|
70
|
+
expect(result.tickSpacing).toBe(5);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('handles range with fraction <= 5 without rounding', () => {
|
|
74
|
+
const result = createNiceScale(0, 40, 5);
|
|
75
|
+
expect(result.niceMin).toBe(0);
|
|
76
|
+
expect(result.niceMax).toBe(40);
|
|
77
|
+
expect(result.tickSpacing).toBe(10);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('handles range with fraction > 5 without rounding', () => {
|
|
81
|
+
const result = createNiceScale(0, 60, 5);
|
|
82
|
+
expect(result.niceMin).toBe(0);
|
|
83
|
+
expect(result.niceMax).toBe(60);
|
|
84
|
+
expect(result.tickSpacing).toBe(20);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Test cases for different orders of magnitude
|
|
88
|
+
it('handles very small numbers', () => {
|
|
89
|
+
const result = createNiceScale(0.001, 0.005, 5);
|
|
90
|
+
expect(result.niceMin).toBe(0.001);
|
|
91
|
+
expect(result.niceMax).toBe(0.005);
|
|
92
|
+
expect(result.tickSpacing).toBe(0.001);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('handles very large numbers', () => {
|
|
96
|
+
const result = createNiceScale(1000000, 1500000, 5);
|
|
97
|
+
expect(result.niceMin).toBe(1000000);
|
|
98
|
+
expect(result.niceMax).toBe(1500000);
|
|
99
|
+
expect(result.tickSpacing).toBe(100000);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('maxValueFromDataSet', () => {
|
|
104
|
+
it('returns the maximum value from a dataset', () => {
|
|
105
|
+
const data = [
|
|
106
|
+
{ label: 'Series 1', data: [100, undefined, 80, 1000, 476, -890] },
|
|
107
|
+
{ label: 'Series 2', data: [] },
|
|
108
|
+
{ label: 'Series 3', data: [100, 235, undefined, -1000, 476, 890] },
|
|
109
|
+
{ label: 'Series 4', data: [-1, -10, -100, undefined] },
|
|
110
|
+
];
|
|
111
|
+
const result = maxValueFromDataSet(data);
|
|
112
|
+
expect(result).toBe(1000);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('minValueFromDataSet', () => {
|
|
117
|
+
it('returns the minimum value from a dataset', () => {
|
|
118
|
+
const data = [
|
|
119
|
+
{ label: 'Series 1', data: [100, undefined, 80, 1000, 476, 890] },
|
|
120
|
+
{ label: 'Series 2', data: [] },
|
|
121
|
+
{ label: 'Series 3', data: [-100, 235, undefined, 1000, 476, -890] },
|
|
122
|
+
{ label: 'Series 4', data: [undefined, -1, undefined] },
|
|
123
|
+
];
|
|
124
|
+
const result = minValueFromDataSet(data);
|
|
125
|
+
expect(result).toBe(-890);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import * as d3 from 'd3';
|
|
3
|
+
import { mobileVisualisationPalette } from '@hero-design/colors';
|
|
4
|
+
|
|
5
|
+
// Only use colors that are not maasstrichtBlue
|
|
6
|
+
const DEFAULT_COLORS = Object.entries(mobileVisualisationPalette)
|
|
7
|
+
.filter(([key]) => !key.startsWith('maasstrichtBlue'))
|
|
8
|
+
.map(([, value]) => value);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* useColorScale - Returns a d3 ordinal scale for mapping labels to colors.
|
|
12
|
+
* @param labels Array of labels (series names or keys)
|
|
13
|
+
* @param customColors Optional custom color palette
|
|
14
|
+
* @returns Ordinal scale function: (label: string) => color
|
|
15
|
+
*/
|
|
16
|
+
export default function useColorScale(
|
|
17
|
+
labels: string[],
|
|
18
|
+
customColors?: string[]
|
|
19
|
+
): (label: string) => string | undefined {
|
|
20
|
+
return useMemo(() => {
|
|
21
|
+
const palette =
|
|
22
|
+
customColors && customColors.length > 0 ? customColors : DEFAULT_COLORS;
|
|
23
|
+
return d3.scaleOrdinal<string, string>().domain(labels).range(palette);
|
|
24
|
+
}, [labels, customColors]);
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import * as d3 from 'd3';
|
|
3
|
+
|
|
4
|
+
const useGenerateTicks = ({
|
|
5
|
+
maxValue,
|
|
6
|
+
minValue,
|
|
7
|
+
step,
|
|
8
|
+
}: {
|
|
9
|
+
maxValue?: number;
|
|
10
|
+
minValue?: number;
|
|
11
|
+
step?: number;
|
|
12
|
+
}) => {
|
|
13
|
+
const maxValueOrZero = maxValue || 0;
|
|
14
|
+
const minValueOrZero = minValue || 0;
|
|
15
|
+
|
|
16
|
+
const ticks = useMemo(() => {
|
|
17
|
+
const generatedTicks = d3.range(minValueOrZero, maxValueOrZero, step);
|
|
18
|
+
if (generatedTicks[generatedTicks.length - 1] !== maxValueOrZero) {
|
|
19
|
+
generatedTicks.push(maxValueOrZero);
|
|
20
|
+
}
|
|
21
|
+
return generatedTicks;
|
|
22
|
+
}, [maxValueOrZero, minValueOrZero, step]);
|
|
23
|
+
|
|
24
|
+
return ticks;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default useGenerateTicks;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import * as d3 from 'd3';
|
|
3
|
+
|
|
4
|
+
export type UseScaleBandXProps = {
|
|
5
|
+
labels: string[];
|
|
6
|
+
xStart: number;
|
|
7
|
+
xEnd: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const useScaleBandX = ({ labels, xStart, xEnd }: UseScaleBandXProps) => {
|
|
11
|
+
return useMemo(
|
|
12
|
+
() => d3.scaleBand().domain(labels).range([xStart, xEnd]).padding(0.2),
|
|
13
|
+
[labels, xStart, xEnd]
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default useScaleBandX;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import * as d3 from 'd3';
|
|
3
|
+
|
|
4
|
+
export type UseScaleLinearYProps = {
|
|
5
|
+
maxValue: number;
|
|
6
|
+
minValue: number;
|
|
7
|
+
yStart: number;
|
|
8
|
+
yEnd: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const useScaleLinearY = ({
|
|
12
|
+
maxValue,
|
|
13
|
+
minValue,
|
|
14
|
+
yStart,
|
|
15
|
+
yEnd,
|
|
16
|
+
}: UseScaleLinearYProps) => {
|
|
17
|
+
const maxValueOrZero = maxValue || 0;
|
|
18
|
+
const minValueOrZero = minValue || 0;
|
|
19
|
+
|
|
20
|
+
return useMemo(
|
|
21
|
+
() =>
|
|
22
|
+
d3
|
|
23
|
+
.scaleLinear()
|
|
24
|
+
.domain([minValueOrZero, maxValueOrZero])
|
|
25
|
+
.range([yEnd, yStart]),
|
|
26
|
+
[maxValueOrZero, minValueOrZero, yStart, yEnd]
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default useScaleLinearY;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DataValue } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Finds a "nice" number approximately equal to x.
|
|
5
|
+
* https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
|
|
6
|
+
*
|
|
7
|
+
* Reference: Paul Heckbert, "Nice Numbers for Graph Labels",
|
|
8
|
+
* Graphics Gems, pp 61-63.
|
|
9
|
+
* */
|
|
10
|
+
const niceNum = (localRange: number, round: boolean): number => {
|
|
11
|
+
const exponent = Math.floor(Math.log(localRange) / Math.log(10));
|
|
12
|
+
const fraction = localRange / 10 ** exponent;
|
|
13
|
+
|
|
14
|
+
let niceFraction: number;
|
|
15
|
+
|
|
16
|
+
if (round) {
|
|
17
|
+
if (fraction < 1.5) {
|
|
18
|
+
niceFraction = 1;
|
|
19
|
+
} else if (fraction < 3) {
|
|
20
|
+
niceFraction = 2;
|
|
21
|
+
} else if (fraction < 7) {
|
|
22
|
+
niceFraction = 5;
|
|
23
|
+
} else {
|
|
24
|
+
niceFraction = 10;
|
|
25
|
+
}
|
|
26
|
+
} else if (fraction <= 1) {
|
|
27
|
+
niceFraction = 1;
|
|
28
|
+
} else if (fraction <= 2) {
|
|
29
|
+
niceFraction = 2;
|
|
30
|
+
} else if (fraction <= 5) {
|
|
31
|
+
niceFraction = 5;
|
|
32
|
+
} else {
|
|
33
|
+
niceFraction = 10;
|
|
34
|
+
}
|
|
35
|
+
return niceFraction * 10 ** exponent;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const createNiceScale = (
|
|
39
|
+
min: number,
|
|
40
|
+
max: number,
|
|
41
|
+
maxTicks = 10
|
|
42
|
+
): { niceMin: number; niceMax: number; tickSpacing: number } => {
|
|
43
|
+
const range = niceNum(max - min, false);
|
|
44
|
+
const tickSpacing = niceNum(range / (maxTicks - 1), true);
|
|
45
|
+
const niceMin = Math.floor(min / tickSpacing) * tickSpacing;
|
|
46
|
+
const niceMax = Math.ceil(max / tickSpacing) * tickSpacing;
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
niceMin,
|
|
50
|
+
niceMax,
|
|
51
|
+
tickSpacing,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const isNull = (value: DataValue) => value == null;
|
|
56
|
+
|
|
57
|
+
const filterNullValues = (data: DataValue[]): number[] => {
|
|
58
|
+
return data.filter((d): d is number => !isNull(d));
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const maxValueFromDataSet = (data: { data: DataValue[] }[]): number =>
|
|
62
|
+
Math.max(
|
|
63
|
+
-Infinity,
|
|
64
|
+
...data.map((d) => Math.max(...filterNullValues(d.data)))
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
export const minValueFromDataSet = (data: { data: DataValue[] }[]): number =>
|
|
68
|
+
Math.min(Infinity, ...data.map((d) => Math.min(...filterNullValues(d.data))));
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export type AxisSizeConfig = {
|
|
2
|
+
xAxisTextHeight: number;
|
|
3
|
+
setXAxisTextHeight: (height: number) => void;
|
|
4
|
+
yAxisTextWidth: number;
|
|
5
|
+
setYAxisTextWidth: (width: number) => void;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a data series for the chart.
|
|
10
|
+
* @template Data - The type of the data array for the series.
|
|
11
|
+
*/
|
|
12
|
+
interface Series<Data> {
|
|
13
|
+
/**
|
|
14
|
+
* Label of the series (used for legends, etc.).
|
|
15
|
+
*/
|
|
16
|
+
label: string;
|
|
17
|
+
/**
|
|
18
|
+
* Data values for the series.
|
|
19
|
+
*/
|
|
20
|
+
data: Data;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for axis ticks.
|
|
25
|
+
*/
|
|
26
|
+
interface TickConfig {
|
|
27
|
+
/**
|
|
28
|
+
* The interval between ticks on the axis.
|
|
29
|
+
*/
|
|
30
|
+
interval: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Configuration for the Y axis of the chart.
|
|
35
|
+
*/
|
|
36
|
+
interface YAxisConfig {
|
|
37
|
+
/**
|
|
38
|
+
* Maximum value for the Y axis.
|
|
39
|
+
*/
|
|
40
|
+
maxValue?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Minimum value for the Y axis.
|
|
43
|
+
*/
|
|
44
|
+
minValue?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Labels for the Y axis.
|
|
47
|
+
*/
|
|
48
|
+
labels?: Array<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Step size between ticks on the Y axis.
|
|
51
|
+
*/
|
|
52
|
+
step?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Tick configuration for the Y axis.
|
|
55
|
+
*/
|
|
56
|
+
tick?: TickConfig;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Configuration for the X axis of the chart.
|
|
61
|
+
*/
|
|
62
|
+
interface XAxisConfig {
|
|
63
|
+
/**
|
|
64
|
+
* Labels for the X axis.
|
|
65
|
+
*/
|
|
66
|
+
labels?: Array<string>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Represents a single data value in the chart (can be a number or undefined).
|
|
71
|
+
*/
|
|
72
|
+
type DataValue = number | undefined;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Represents the position of an object in the chart.
|
|
76
|
+
*/
|
|
77
|
+
type AxisCoordinates = {
|
|
78
|
+
xStart: number;
|
|
79
|
+
xEnd: number;
|
|
80
|
+
yStart: number;
|
|
81
|
+
yEnd: number;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Represents the configuration for the header of the chart.
|
|
86
|
+
*/
|
|
87
|
+
type HeaderConfig = {
|
|
88
|
+
title?: string;
|
|
89
|
+
actionsExtra?: React.ReactNode;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export type {
|
|
93
|
+
Series,
|
|
94
|
+
TickConfig,
|
|
95
|
+
XAxisConfig,
|
|
96
|
+
YAxisConfig,
|
|
97
|
+
DataValue,
|
|
98
|
+
AxisCoordinates,
|
|
99
|
+
HeaderConfig,
|
|
100
|
+
};
|
|
@@ -4,8 +4,8 @@ import BaseOptionList, { BaseOptionListProps } from '../BaseOptionList';
|
|
|
4
4
|
import Option from './Option';
|
|
5
5
|
import type { MultiSelectProps } from '.';
|
|
6
6
|
import type { OptionType, SectionType } from '../types';
|
|
7
|
-
import { deepCompareValue } from '../helpers';
|
|
8
7
|
import { isOptionSelected } from './utils';
|
|
8
|
+
import { deepCompareValue } from '../../../utils/helpers';
|
|
9
9
|
|
|
10
10
|
type OptionListProps<V, T extends OptionType<V>> = Pick<
|
|
11
11
|
MultiSelectProps<V, T>,
|
|
@@ -8,16 +8,12 @@ import BottomSheet from '../../BottomSheet';
|
|
|
8
8
|
import Box from '../../Box';
|
|
9
9
|
import TextInput from '../../TextInput';
|
|
10
10
|
import Footer from '../Footer';
|
|
11
|
-
import {
|
|
12
|
-
getScrollParams,
|
|
13
|
-
toFlatOptions,
|
|
14
|
-
toSections,
|
|
15
|
-
useKeyboard,
|
|
16
|
-
} from '../helpers';
|
|
11
|
+
import { getScrollParams, toFlatOptions, toSections } from '../helpers';
|
|
17
12
|
import { StyledSearchBar } from '../StyledSelect';
|
|
18
13
|
import type { OptionType, SectionType, SelectProps } from '../types';
|
|
19
14
|
import OptionList from './OptionList';
|
|
20
15
|
import { isOptionSelected } from './utils';
|
|
16
|
+
import { useKeyboard } from '../../../utils/helpers';
|
|
21
17
|
|
|
22
18
|
export interface MultiSelectProps<V, T extends OptionType<V> = OptionType<V>>
|
|
23
19
|
extends SelectProps<V, T> {
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
} from 'react-native';
|
|
7
7
|
import type { SingleSelectProps } from '.';
|
|
8
8
|
import { BaseOptionListProps } from '../BaseOptionList';
|
|
9
|
-
import { deepCompareValue } from '../helpers';
|
|
10
9
|
import type { OptionType, SectionType } from '../types';
|
|
11
10
|
import Option from './Option';
|
|
12
11
|
import { StyledOptionList } from './StyledSingleSelect';
|
|
12
|
+
import { deepCompareValue } from '../../../utils/helpers';
|
|
13
13
|
|
|
14
14
|
type OptionListProps<V, T extends OptionType<V>> = Pick<
|
|
15
15
|
SingleSelectProps<V, T>,
|
|
@@ -6,16 +6,11 @@ import type {
|
|
|
6
6
|
import { TouchableOpacity, View } from 'react-native';
|
|
7
7
|
import BottomSheet from '../../BottomSheet';
|
|
8
8
|
import TextInput from '../../TextInput';
|
|
9
|
-
import {
|
|
10
|
-
deepCompareValue,
|
|
11
|
-
getScrollParams,
|
|
12
|
-
toFlatOptions,
|
|
13
|
-
toSections,
|
|
14
|
-
useKeyboard,
|
|
15
|
-
} from '../helpers';
|
|
9
|
+
import { getScrollParams, toFlatOptions, toSections } from '../helpers';
|
|
16
10
|
import { StyledSearchBar } from '../StyledSelect';
|
|
17
11
|
import type { OptionType, SectionType, SelectProps } from '../types';
|
|
18
12
|
import OptionList from './OptionList';
|
|
13
|
+
import { deepCompareValue, useKeyboard } from '../../../utils/helpers';
|
|
19
14
|
|
|
20
15
|
export interface SingleSelectProps<V, T extends OptionType<V> = OptionType<V>>
|
|
21
16
|
extends SelectProps<V, T> {
|