@scality/core-ui 0.170.0 → 0.172.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/__mocks__/uuid.js +11 -0
  2. package/dist/components/barchartv2/Barchart.component.d.ts.map +1 -1
  3. package/dist/components/barchartv2/Barchart.component.js +4 -4
  4. package/dist/components/barchartv2/BarchartTooltip.d.ts +11 -0
  5. package/dist/components/barchartv2/BarchartTooltip.d.ts.map +1 -0
  6. package/dist/components/barchartv2/BarchartTooltip.js +27 -0
  7. package/dist/components/chartlegend/ChartLegend.d.ts +3 -1
  8. package/dist/components/chartlegend/ChartLegend.d.ts.map +1 -1
  9. package/dist/components/chartlegend/ChartLegend.js +2 -2
  10. package/dist/components/chartlegend/ChartLegendWrapper.d.ts +3 -1
  11. package/dist/components/chartlegend/ChartLegendWrapper.d.ts.map +1 -1
  12. package/dist/components/chartlegend/ChartLegendWrapper.js +43 -9
  13. package/dist/components/charttooltip/ChartTooltip.d.ts +13 -0
  14. package/dist/components/charttooltip/ChartTooltip.d.ts.map +1 -0
  15. package/dist/components/charttooltip/ChartTooltip.js +49 -0
  16. package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts +4 -0
  17. package/dist/components/globalhealthbar/GlobalHealthBar.component.d.ts.map +1 -1
  18. package/dist/components/globalhealthbar/GlobalHealthBar.component.js +4 -0
  19. package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts +10 -0
  20. package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.d.ts.map +1 -0
  21. package/dist/components/globalhealthbar/GlobalHealthBarRecharts.component.js +78 -0
  22. package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts +18 -0
  23. package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.d.ts.map +1 -0
  24. package/dist/components/globalhealthbar/components/GlobalHealthBarTooltip.js +95 -0
  25. package/dist/components/globalhealthbar/components/HealthBarXAxis.d.ts +7 -0
  26. package/dist/components/globalhealthbar/components/HealthBarXAxis.d.ts.map +1 -0
  27. package/dist/components/globalhealthbar/components/HealthBarXAxis.js +25 -0
  28. package/dist/components/globalhealthbar/healthBarUtils.d.ts +77 -0
  29. package/dist/components/globalhealthbar/healthBarUtils.d.ts.map +1 -0
  30. package/dist/components/globalhealthbar/healthBarUtils.js +196 -0
  31. package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts +2 -0
  32. package/dist/components/globalhealthbar/healthBarUtils.spec.d.ts.map +1 -0
  33. package/dist/components/globalhealthbar/healthBarUtils.spec.js +391 -0
  34. package/dist/components/globalhealthbar/useHealthBarData.d.ts +18 -0
  35. package/dist/components/globalhealthbar/useHealthBarData.d.ts.map +1 -0
  36. package/dist/components/globalhealthbar/useHealthBarData.js +46 -0
  37. package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts +2 -0
  38. package/dist/components/globalhealthbar/useHealthBarData.spec.d.ts.map +1 -0
  39. package/dist/components/globalhealthbar/useHealthBarData.spec.js +207 -0
  40. package/dist/components/icon/Icon.component.d.ts +2 -0
  41. package/dist/components/icon/Icon.component.d.ts.map +1 -1
  42. package/dist/components/icon/Icon.component.js +2 -0
  43. package/dist/components/linetemporalchart/ChartUtil.d.ts.map +1 -1
  44. package/dist/components/linetemporalchart/ChartUtil.js +12 -0
  45. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts +8 -5
  46. package/dist/components/linetimeseriechart/linetimeseriechart.component.d.ts.map +1 -1
  47. package/dist/components/linetimeseriechart/linetimeseriechart.component.js +95 -100
  48. package/dist/components/sparkline/sparkline.component.d.ts +16 -0
  49. package/dist/components/sparkline/sparkline.component.d.ts.map +1 -0
  50. package/dist/components/sparkline/sparkline.component.js +20 -0
  51. package/dist/components/text/Text.component.d.ts +2 -1
  52. package/dist/components/text/Text.component.d.ts.map +1 -1
  53. package/dist/components/text/Text.component.js +6 -1
  54. package/dist/next.d.ts +4 -2
  55. package/dist/next.d.ts.map +1 -1
  56. package/dist/next.js +4 -2
  57. package/package.json +4 -2
  58. package/src/lib/components/barchartv2/Barchart.component.tsx +5 -4
  59. package/src/lib/components/barchartv2/{ChartTooltip.test.tsx → BarchartTooltip.test.tsx} +35 -12
  60. package/src/lib/components/barchartv2/BarchartTooltip.tsx +89 -0
  61. package/src/lib/components/chartlegend/ChartLegend.tsx +4 -2
  62. package/src/lib/components/chartlegend/ChartLegendWrapper.test.tsx +197 -0
  63. package/src/lib/components/chartlegend/ChartLegendWrapper.tsx +65 -9
  64. package/src/lib/components/charttooltip/ChartTooltip.tsx +83 -0
  65. package/src/lib/components/globalhealthbar/GlobalHealthBar.component.tsx +4 -1
  66. package/src/lib/components/globalhealthbar/GlobalHealthBarRecharts.component.tsx +203 -0
  67. package/src/lib/components/globalhealthbar/components/GlobalHealthBarTooltip.tsx +173 -0
  68. package/src/lib/components/globalhealthbar/components/HealthBarXAxis.tsx +94 -0
  69. package/src/lib/components/globalhealthbar/healthBarUtils.spec.ts +701 -0
  70. package/src/lib/components/globalhealthbar/healthBarUtils.ts +311 -0
  71. package/src/lib/components/globalhealthbar/useHealthBarData.spec.tsx +487 -0
  72. package/src/lib/components/globalhealthbar/useHealthBarData.ts +74 -0
  73. package/src/lib/components/icon/Icon.component.tsx +2 -0
  74. package/src/lib/components/linetemporalchart/ChartUtil.ts +26 -0
  75. package/src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx +272 -229
  76. package/src/lib/components/sparkline/sparkline.component.tsx +54 -0
  77. package/src/lib/components/text/Text.component.tsx +15 -2
  78. package/src/lib/next.ts +12 -2
  79. package/stories/BarChart/barchart.stories.tsx +7 -1
  80. package/stories/GlobalHealthBar/globalhealthbarRecharts.stories.tsx +145 -0
  81. package/stories/GlobalHealthBar/globalheathbarrecharts.guideline.mdx +5 -0
  82. package/stories/InlineInput/InlineInput.stories.tsx +7 -1
  83. package/stories/globalhealthbar.stories.tsx +25 -5
  84. package/stories/linetimeseriechart.stories.tsx +217 -1
  85. package/stories/sparkline.stories.tsx +168 -0
  86. package/dist/components/barchartv2/ChartTooltip.d.ts +0 -14
  87. package/dist/components/barchartv2/ChartTooltip.d.ts.map +0 -1
  88. package/dist/components/barchartv2/ChartTooltip.js +0 -41
  89. package/src/lib/components/barchartv2/ChartTooltip.tsx +0 -106
@@ -0,0 +1,311 @@
1
+ import { fontSize } from '../../style/theme';
2
+
3
+ // =============================================================================
4
+ // CONSTANTS
5
+ // =============================================================================
6
+
7
+ export const CHART_CONFIG = {
8
+ RADIUS_SIZE: 4,
9
+ EDGE_THRESHOLD: 8,
10
+ CHART_HEIGHT: 50,
11
+ BAR_SIZE: 8,
12
+ TICK_SIZE: 4,
13
+ TOOLTIP_OFFSET: 24,
14
+ FONT_SIZE: fontSize.smaller,
15
+ TEXT_DY_OFFSET: 12,
16
+ TICK_INTERVAL: 0,
17
+ MARGINS: { left: 28, right: 28, bottom: 4, top: 4 },
18
+ } as const;
19
+
20
+ export const TIME_CONSTANTS = {
21
+ ONE_HOUR: 60 * 60 * 1000,
22
+ ONE_DAY: 24 * 60 * 60 * 1000,
23
+ ONE_WEEK: 7 * 24 * 60 * 60 * 1000,
24
+ MARGIN_HOURS: 6,
25
+ FIFTEEN_MINUTES: 15 * 60 * 1000,
26
+ SIX_HOURS: 6 * 60 * 60 * 1000,
27
+ } as const;
28
+
29
+ export const LABEL_CONFIG = {
30
+ MIN_SPACE_PER_TICK: 80,
31
+ MODULO_CONFIG: {
32
+ [TIME_CONSTANTS.ONE_WEEK]: 2,
33
+ [TIME_CONSTANTS.ONE_DAY]: 3,
34
+ [TIME_CONSTANTS.ONE_HOUR]: 3,
35
+ },
36
+ } as const;
37
+
38
+ // =============================================================================
39
+ // TICK CALCULATIONS
40
+ // =============================================================================
41
+
42
+ const { ONE_HOUR, ONE_DAY, MARGIN_HOURS, FIFTEEN_MINUTES, SIX_HOURS } =
43
+ TIME_CONSTANTS;
44
+
45
+ const generateTickArray = (
46
+ endTimestamp: number,
47
+ count: number,
48
+ interval: number,
49
+ ): number[] => {
50
+ return Array.from({ length: count }, (_, i) => endTimestamp - i * interval);
51
+ };
52
+
53
+ const roundToNearestHalfDay = (timestamp: number): number => {
54
+ const date = new Date(timestamp);
55
+ const hours = date.getHours();
56
+
57
+ if (hours <= 12) {
58
+ return new Date(timestamp).setHours(0, 0, 0, 0);
59
+ } else {
60
+ return new Date(timestamp).setHours(12, 0, 0, 0);
61
+ }
62
+ };
63
+
64
+ export const calculateSevenDayTicks = (endTimestamp: number): number[] => {
65
+ const marginedEnd = endTimestamp - MARGIN_HOURS * ONE_HOUR;
66
+ const roundedEnd = roundToNearestHalfDay(marginedEnd);
67
+ return generateTickArray(roundedEnd, 7, ONE_DAY);
68
+ };
69
+
70
+ export const calculateDayTicks = (endTimestamp: number): number[] => {
71
+ const is6HourTick = endTimestamp % SIX_HOURS === 0;
72
+ const closest6Hours = Math.floor(endTimestamp / SIX_HOURS) * SIX_HOURS;
73
+ const tickCount = is6HourTick ? 5 : 4;
74
+
75
+ return generateTickArray(closest6Hours, tickCount, SIX_HOURS);
76
+ };
77
+
78
+ export const calculateHourTicks = (endTimestamp: number): number[] => {
79
+ const is15MinuteTick = endTimestamp % FIFTEEN_MINUTES === 0;
80
+ const closest15Minutes =
81
+ Math.floor(endTimestamp / FIFTEEN_MINUTES) * FIFTEEN_MINUTES;
82
+ const tickCount = is15MinuteTick ? 5 : 4;
83
+
84
+ return generateTickArray(closest15Minutes, tickCount, FIFTEEN_MINUTES);
85
+ };
86
+
87
+ export const getEdgeMargin = (
88
+ index: number,
89
+ totalTicks: number,
90
+ isDaySpan: boolean,
91
+ ): number => {
92
+ if (isDaySpan && totalTicks === 5) {
93
+ return index === 0 ? -8 : index === totalTicks - 1 ? 8 : 0;
94
+ }
95
+ return 0;
96
+ };
97
+
98
+ export const getTicks = (
99
+ startTimestamp: number,
100
+ endTimestamp: number,
101
+ ): number[] => {
102
+ const span = endTimestamp - startTimestamp;
103
+
104
+ if (span === 7 * ONE_DAY) {
105
+ return calculateSevenDayTicks(endTimestamp);
106
+ } else if (span === 24 * ONE_HOUR) {
107
+ return calculateDayTicks(endTimestamp);
108
+ } else if (span === ONE_HOUR) {
109
+ return calculateHourTicks(endTimestamp);
110
+ }
111
+
112
+ return [];
113
+ };
114
+
115
+ // =============================================================================
116
+ // LABEL VISIBILITY
117
+ // =============================================================================
118
+
119
+ export interface LabelVisibilityConfig {
120
+ hasEnoughSpace: boolean;
121
+ timeSpan: number;
122
+ tickIndex: number;
123
+ totalTicks: number;
124
+ }
125
+
126
+ export const calculateLabelVisibility = (
127
+ chartWidth: number,
128
+ totalTicks: number,
129
+ span: number,
130
+ index: number,
131
+ endTimestamp: number,
132
+ ): boolean => {
133
+ const hasEnoughSpace =
134
+ chartWidth / totalTicks > LABEL_CONFIG.MIN_SPACE_PER_TICK;
135
+
136
+ // If enough space, show all labels
137
+ if (hasEnoughSpace) return true;
138
+
139
+ // Apply specific rules for each time range
140
+ if (span === TIME_CONSTANTS.ONE_WEEK) {
141
+ return index % 2 === 0;
142
+ }
143
+
144
+ if (span === TIME_CONSTANTS.ONE_DAY) {
145
+ const isRoundHour = endTimestamp % (60 * 60 * 1000) === 0;
146
+ const roundHourInterval = index % 2 === 0;
147
+ const defaultInterval = index % 3 === 0;
148
+ const result = isRoundHour ? roundHourInterval : defaultInterval;
149
+
150
+ return result;
151
+ }
152
+
153
+ if (span === TIME_CONSTANTS.ONE_HOUR) {
154
+ const isRound15Minute = endTimestamp % (15 * 60 * 1000) === 0;
155
+ const round15MinuteInterval = index % 2 === 0;
156
+ const defaultInterval = index % 3 === 0;
157
+ const result = isRound15Minute ? round15MinuteInterval : defaultInterval;
158
+
159
+ return result;
160
+ }
161
+
162
+ return false;
163
+ };
164
+
165
+ // =============================================================================
166
+ // RECTANGLE PROPERTIES
167
+ // =============================================================================
168
+
169
+ /**
170
+ * Core calculation for alert positioning within a time range
171
+ */
172
+ export const calculateAlertPosition = (
173
+ alertStartTimestamp: number,
174
+ alertEndTimestamp: number,
175
+ chartStartTimestamp: number,
176
+ chartEndTimestamp: number,
177
+ availableWidth: number,
178
+ baseX: number = 0,
179
+ ) => {
180
+ const start = Math.max(alertStartTimestamp, chartStartTimestamp);
181
+ const end = Math.min(alertEndTimestamp, chartEndTimestamp);
182
+ const totalTimeSpan = chartEndTimestamp - chartStartTimestamp;
183
+ const relativeSize = (end - start) / totalTimeSpan;
184
+
185
+ // Calculate start position relative to baseX
186
+ let startX = baseX;
187
+ if (alertStartTimestamp > chartStartTimestamp) {
188
+ const alertStartRelative =
189
+ (alertStartTimestamp - chartStartTimestamp) / totalTimeSpan;
190
+ startX = baseX + alertStartRelative * availableWidth;
191
+ }
192
+
193
+ const width = relativeSize * availableWidth;
194
+
195
+ return { startX, width, relativeSize };
196
+ };
197
+
198
+ // =============================================================================
199
+ // KEYBOARD NAVIGATION UTILS
200
+ // =============================================================================
201
+
202
+ export type NavigationAction =
203
+ | 'previous'
204
+ | 'next'
205
+ | 'first'
206
+ | 'last'
207
+ | 'escape';
208
+
209
+ export interface NavigationState {
210
+ newIndex: number;
211
+ selectedAlert: any | null;
212
+ shouldActivateKeyboard: boolean;
213
+ }
214
+
215
+ /**
216
+ * Maps keyboard events to navigation actions
217
+ */
218
+ export const getNavigationAction = (key: string): NavigationAction | null => {
219
+ switch (key) {
220
+ case 'ArrowLeft':
221
+ case 'ArrowUp':
222
+ return 'previous';
223
+ case 'ArrowRight':
224
+ case 'ArrowDown':
225
+ return 'next';
226
+ case 'Home':
227
+ return 'first';
228
+ case 'End':
229
+ return 'last';
230
+ case 'Escape':
231
+ return 'escape';
232
+ default:
233
+ return null;
234
+ }
235
+ };
236
+
237
+ /**
238
+ * Calculates new index based on navigation action
239
+ */
240
+ export const calculateNavigationIndex = (
241
+ action: NavigationAction,
242
+ currentIndex: number,
243
+ arrayLength: number,
244
+ ): number => {
245
+ if (arrayLength === 0) return -1;
246
+
247
+ switch (action) {
248
+ case 'previous':
249
+ return currentIndex <= 0 ? arrayLength - 1 : currentIndex - 1;
250
+ case 'next':
251
+ return currentIndex >= arrayLength - 1 ? 0 : currentIndex + 1;
252
+ case 'first':
253
+ return 0;
254
+ case 'last':
255
+ return arrayLength - 1;
256
+ case 'escape':
257
+ return -1;
258
+ default:
259
+ return currentIndex;
260
+ }
261
+ };
262
+
263
+ /**
264
+ * Gets complete navigation state update for a given action
265
+ */
266
+ export const getNavigationStateUpdate = <T>(
267
+ action: NavigationAction,
268
+ currentIndex: number,
269
+ alerts: T[],
270
+ ): NavigationState => {
271
+ const newIndex = calculateNavigationIndex(
272
+ action,
273
+ currentIndex,
274
+ alerts.length,
275
+ );
276
+
277
+ return {
278
+ newIndex,
279
+ selectedAlert: newIndex >= 0 ? alerts[newIndex] : null,
280
+ shouldActivateKeyboard: action !== 'escape',
281
+ };
282
+ };
283
+
284
+ // =============================================================================
285
+ // TOOLTIP UTILS
286
+ // =============================================================================
287
+
288
+ /**
289
+ * Calculates tooltip position for an alert based on its time range
290
+ */
291
+ export const getTooltipPosition = (
292
+ alert: { startsAt: string; endsAt: string },
293
+ startTimestamp: number,
294
+ endTimestamp: number,
295
+ chartUsableWidth: number,
296
+ ) => {
297
+ const alertStart = new Date(alert.startsAt).getTime();
298
+ const alertEnd = new Date(alert.endsAt).getTime();
299
+
300
+ const { startX, width } = calculateAlertPosition(
301
+ alertStart,
302
+ alertEnd,
303
+ startTimestamp,
304
+ endTimestamp,
305
+ chartUsableWidth,
306
+ CHART_CONFIG.MARGINS.left, // Include left margin as baseX
307
+ );
308
+
309
+ // Return center position of the alert
310
+ return startX + width / 2;
311
+ };