@react-magma/charts 7.0.0-next.1 → 7.0.0-next.2

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 (42) hide show
  1. package/dist/charts.css +6 -0
  2. package/dist/charts.css.map +1 -0
  3. package/dist/charts.js +1 -1
  4. package/dist/charts.js.map +1 -1
  5. package/dist/charts.modern.js +303 -12
  6. package/dist/charts.modern.js.map +1 -1
  7. package/dist/charts.modern.module.js +1 -1
  8. package/dist/charts.modern.module.js.map +1 -1
  9. package/dist/charts.umd.js +1 -1
  10. package/dist/charts.umd.js.map +1 -1
  11. package/dist/components/CarbonChart/CarbonChart.d.ts +32 -0
  12. package/dist/components/CarbonChart/CarbonChart.test.d.ts +1 -0
  13. package/dist/components/CarbonChart/CarbonChartArea.stories.d.ts +8 -0
  14. package/dist/components/CarbonChart/CarbonChartAreaStacked.stories.d.ts +6 -0
  15. package/dist/components/CarbonChart/CarbonChartBar.stories.d.ts +12 -0
  16. package/dist/components/CarbonChart/CarbonChartBarFloating.stories.d.ts +6 -0
  17. package/dist/components/CarbonChart/CarbonChartBarGrouped.stories.d.ts +12 -0
  18. package/dist/components/CarbonChart/CarbonChartBarStacked.stories.d.ts +13 -0
  19. package/dist/components/CarbonChart/CarbonChartDonut.stories.d.ts +8 -0
  20. package/dist/components/CarbonChart/CarbonChartLine.stories.d.ts +9 -0
  21. package/dist/components/CarbonChart/CarbonChartLollipop.stories.d.ts +5 -0
  22. package/dist/components/CarbonChart/CarbonChartPie.stories.d.ts +8 -0
  23. package/dist/components/CarbonChart/index.d.ts +1 -0
  24. package/dist/index.d.ts +1 -0
  25. package/package.json +7 -1
  26. package/src/components/CarbonChart/CarbonChart.test.js +74 -0
  27. package/src/components/CarbonChart/CarbonChart.tsx +524 -0
  28. package/src/components/CarbonChart/CarbonChartArea.stories.tsx +357 -0
  29. package/src/components/CarbonChart/CarbonChartAreaStacked.stories.tsx +313 -0
  30. package/src/components/CarbonChart/CarbonChartBar.stories.tsx +388 -0
  31. package/src/components/CarbonChart/CarbonChartBarFloating.stories.tsx +156 -0
  32. package/src/components/CarbonChart/CarbonChartBarGrouped.stories.tsx +798 -0
  33. package/src/components/CarbonChart/CarbonChartBarStacked.stories.tsx +833 -0
  34. package/src/components/CarbonChart/CarbonChartDonut.stories.tsx +204 -0
  35. package/src/components/CarbonChart/CarbonChartLine.stories.tsx +674 -0
  36. package/src/components/CarbonChart/CarbonChartLollipop.stories.tsx +113 -0
  37. package/src/components/CarbonChart/CarbonChartPie.stories.tsx +187 -0
  38. package/src/components/CarbonChart/index.ts +1 -0
  39. package/src/components/LineChart/Chart.tsx +15 -14
  40. package/src/components/LineChart/GraphTooltip.tsx +6 -3
  41. package/src/components/LineChart/LineChart.tsx +7 -5
  42. package/src/index.ts +1 -0
@@ -0,0 +1,524 @@
1
+ import * as React from 'react';
2
+ import { ThemeInterface, ThemeContext, useIsInverse } from 'react-magma-dom';
3
+ import { transparentize } from 'polished';
4
+ import styled, { CreateStyled } from '@emotion/styled';
5
+ import {
6
+ AreaChart,
7
+ StackedAreaChart,
8
+ DonutChart,
9
+ GroupedBarChart,
10
+ LineChart,
11
+ LollipopChart,
12
+ PieChart,
13
+ SimpleBarChart,
14
+ StackedBarChart,
15
+ } from '@carbon/charts-react';
16
+ import '@carbon/charts/styles.css';
17
+
18
+ const typedStyled = styled as CreateStyled<ThemeInterface>;
19
+
20
+ export enum CarbonChartType {
21
+ area = 'area',
22
+ areaStacked = 'areaStacked',
23
+ bar = 'bar',
24
+ barGrouped = 'barGrouped',
25
+ barStacked = 'barStacked',
26
+ donut = 'donut',
27
+ line = 'line',
28
+ pie = 'pie',
29
+ lollipop = 'lollipop',
30
+ }
31
+
32
+ export interface CarbonChartProps extends React.HTMLAttributes<HTMLDivElement> {
33
+ dataSet: Array<Object>;
34
+ isInverse?: boolean;
35
+ /**
36
+ * For a complete list of options, see Carbon Charts documentation
37
+ */
38
+ options: Object;
39
+ testId?: string;
40
+ /**
41
+ * @internal
42
+ */
43
+ theme?: ThemeInterface;
44
+ /**
45
+ * Type of Chart: area, bar, donut, line, etc.
46
+ */
47
+ type: CarbonChartType;
48
+ }
49
+
50
+ const CarbonChartWrapper = typedStyled.div<{
51
+ isInverse?: boolean;
52
+ theme: ThemeInterface;
53
+ }>`
54
+ .cds--data-table thead tr th {
55
+ background: ${props =>
56
+ props.isInverse ? props.theme.colors.primary700 : ''} !important;
57
+ }
58
+ .cds--data-table td,
59
+ .cds--data-table tbody th {
60
+ color: ${props => props.theme.colors.neutral700};
61
+ }
62
+ .cds--data-table tbody tr,
63
+ .cds--data-table tbody tr td,
64
+ .cds--data-table tbody tr th {
65
+ color: ${props => (props.isInverse ? props.theme.colors.neutral100 : '')};
66
+ }
67
+ .cds--data-table tr {
68
+ block-size: 2.5rem;
69
+ }
70
+
71
+ .cds--cc--tooltip .content-box .datapoint-tooltip p {
72
+ font-size: ${props => props.theme.typeScale.size02.fontSize};
73
+ padding: ${props => props.theme.spaceScale.spacing02};
74
+ color: ${props =>
75
+ props.isInverse
76
+ ? props.theme.colors.neutral100
77
+ : props.theme.colors.neutral700};
78
+ max-width:142px;
79
+ white-space: normal;
80
+ }
81
+
82
+ .cds--modal-container {
83
+ clip-path: inset(0% 0% 0% 0% round ${props => props.theme.borderRadius});
84
+ background: ${props =>
85
+ props.isInverse ? props.theme.colors.primary700 : ''};
86
+ .cds--data-table th {
87
+ background: ${props =>
88
+ props.isInverse ? props.theme.colors.primary600 : ''};
89
+ }
90
+ .cds--data-table td {
91
+ border-top: 1px solid
92
+ ${props =>
93
+ props.isInverse
94
+ ? transparentize(0.8, props.theme.colors.neutral100)
95
+ : 'inherit'};
96
+ border-bottom: 1px solid
97
+ ${props =>
98
+ props.isInverse
99
+ ? transparentize(0.8, props.theme.colors.neutral100)
100
+ : 'inherit'};
101
+ background: ${props => (props.isInverse ? '#202565' : '')};
102
+ }
103
+ .cds--data-table tr:hover td {
104
+ background: ${props =>
105
+ props.isInverse ? props.theme.colors.primary600 : ''};
106
+ }
107
+ }
108
+
109
+ p,
110
+ div,
111
+ text,
112
+ .cds--cc--axes g.axis .axis-title,
113
+ .cds--cc--title p.title,
114
+ .cds--cc--axes g.axis g.tick text {
115
+ font-family: ${props => props.theme.bodyFont} !important;
116
+ color: ${props =>
117
+ props.isInverse
118
+ ? props.theme.colors.neutral100
119
+ : props.theme.colors.neutral700};
120
+ }
121
+
122
+ .cds--cc--axes {
123
+ overflow: visible;
124
+ }
125
+
126
+ div.cds--cc--legend {
127
+ div.legend-item {
128
+ div.checkbox {
129
+ background: ${props =>
130
+ props.isInverse
131
+ ? props.theme.colors.neutral900
132
+ : props.theme.colors.neutral100};
133
+ border: none;
134
+ width: ${props => props.theme.spaceScale.spacing05};
135
+ height: ${props => props.theme.spaceScale.spacing05};
136
+ svg {
137
+ left: 2px;
138
+ position: relative;
139
+ }
140
+ }
141
+ p {
142
+ font-size: ${props => props.theme.typeScale.size03.fontSize};
143
+ margin: 0 ${props => props.theme.spaceScale.spacing03} 0 0;
144
+ }
145
+ }
146
+ }
147
+ div.cds--cc--legend.has-deactivated-items {
148
+ div.legend-item {
149
+ div.checkbox {
150
+ border: 1px solid
151
+ ${props =>
152
+ props.isInverse
153
+ ? props.theme.colors.neutral100
154
+ : props.theme.colors.neutral900};
155
+ }
156
+ div.checkbox.active {
157
+ border: 1px solid transparent;
158
+ }
159
+ }
160
+ }
161
+ .chart-holder {
162
+ .cds--cc--axes g.axis g.tick text {
163
+ fill: ${props => (props.isInverse ? props.theme.colors.neutral100 : '')};
164
+ }
165
+ .cds--cc--axes g.axis path.domain {
166
+ stroke: ${props =>
167
+ props.isInverse ? props.theme.colors.neutral100 : ''};
168
+ }
169
+ .cds--cc--grid g.x.grid g.tick line,
170
+ .cds--cc--grid g.y.grid g.tick line {
171
+ stroke: ${props =>
172
+ props.isInverse
173
+ ? transparentize(0.5, props.theme.colors.neutral100)
174
+ : ''};
175
+ }
176
+ .cds--cc--grid rect.chart-grid-backdrop.stroked{
177
+ stroke: ${props => (props.isInverse ? props.theme.colors.neutral100 : '')}
178
+ }
179
+ .cds--cc--skeleton .shimmer-effect-lines {
180
+ filter: ${props => (props.isInverse ? 'invert(1)' : '')};
181
+ }
182
+ /* .chart-holder.cds--chart-holder.filled,
183
+ .cds--cc--skeleton rect.chart-skeleton-backdrop,
184
+ .cds--cc--grid rect.chart-grid-backdrop {
185
+ } */
186
+
187
+ .cds--cc--grid rect.chart-grid-backdrop{
188
+ fill:transparent;
189
+ }
190
+ .cds--cc--scatter circle.dot.hovered {
191
+ padding: 10px;
192
+ }
193
+ .cds--cc--scatter-stacked circle.dot.hovered,
194
+ .cds--cc--scatter-stacked circle.dot.unfilled,
195
+ .cds--cc--scatter circle.dot.unfilled{
196
+ stroke-width: 6px;
197
+ transition: 0.1s all linear;
198
+
199
+ }
200
+ .cds--cc--scatter circle.dot.hovered {
201
+ stroke-width: 0.5em;
202
+ transition: 0.1s all linear;
203
+ filter:
204
+ drop-shadow( 1px 0px 0px ${props =>
205
+ props.isInverse
206
+ ? props.theme.colors.primary600
207
+ : props.theme.colors.neutral100})
208
+ drop-shadow(-1px 0px 0px ${props =>
209
+ props.isInverse
210
+ ? props.theme.colors.primary600
211
+ : props.theme.colors.neutral100})
212
+ drop-shadow( 0px 1px 0px ${props =>
213
+ props.isInverse
214
+ ? props.theme.colors.primary600
215
+ : props.theme.colors.neutral100})
216
+ drop-shadow( 0px -1px 0px ${props =>
217
+ props.isInverse
218
+ ? props.theme.colors.primary600
219
+ : props.theme.colors.neutral100});
220
+ }
221
+ }
222
+ .cds--cc--lollipop circle.dot.filled,
223
+ .cds--cc--lollipop circle.dot.hovered {
224
+ stroke-width: 15px;
225
+ }
226
+ .cds--cc--scatter-stacked circle.dot.hovered,
227
+ .cds--cc--scatter-stacked circle.dot.unfilled,
228
+ .cds--cc--scatter circle.dot.unfilled,
229
+ .cds--cc--lollipop circle.dot.filled,
230
+ .cds--cc--lollipop circle.dot.hovered{
231
+ transition: 0.1s all linear;
232
+ filter:
233
+ drop-shadow( 1px 0px 0px ${props =>
234
+ props.isInverse
235
+ ? props.theme.colors.primary600
236
+ : props.theme.colors.neutral100})
237
+ drop-shadow(-1px 0px 0px ${props =>
238
+ props.isInverse
239
+ ? props.theme.colors.primary600
240
+ : props.theme.colors.neutral100})
241
+ drop-shadow( 0px 1px 0px ${props =>
242
+ props.isInverse
243
+ ? props.theme.colors.primary600
244
+ : props.theme.colors.neutral100})
245
+ drop-shadow( 0px -1px 0px ${props =>
246
+ props.isInverse
247
+ ? props.theme.colors.primary600
248
+ : props.theme.colors.neutral100});
249
+ }
250
+ .cds--cc--lollipop .cds--cc--scatter circle.dot.hovered{
251
+ transition: 0.1s all linear;
252
+ stroke-width: 1.1em;
253
+ }
254
+
255
+ .cds--overflow-menu-options__btn:focus {
256
+ outline-color: ${props =>
257
+ props.isInverse ? props.theme.colors.focusInverse : ''};
258
+ }
259
+
260
+ .cds--btn {
261
+ min-height: auto;
262
+ display: flex;
263
+ flex: 0 auto;
264
+ align-items: center;
265
+ text-align: center;
266
+ padding: 20px;
267
+ margin: 0;
268
+ line-height: ${props => props.theme.typeScale.size03.lineHeight};
269
+ margin: 0;
270
+ min-width: ${props => props.theme.spaceScale.spacing13};
271
+ overflow: hidden;
272
+ padding: ;
273
+ position: relative;
274
+ right: ${props => props.theme.spaceScale.spacing04};
275
+ text-align: center;
276
+ height: 40px;
277
+ font-family: ${props => props.theme.bodyFont};
278
+ font-size: ${props => props.theme.typeScale.size03.fontSize};
279
+ border-radius: ${props => props.theme.borderRadius};
280
+ font-weight: 500;
281
+ }
282
+
283
+ .cds--btn--primary {
284
+ background: ${props =>
285
+ props.isInverse
286
+ ? props.theme.colors.tertiary500
287
+ : props.theme.colors.primary};
288
+ color: ${props =>
289
+ props.isInverse ? props.theme.colors.neutral900 : ''};
290
+ }
291
+
292
+ *:focus {
293
+ outline: 2px solid
294
+ ${props =>
295
+ props.isInverse
296
+ ? props.theme.colors.focusInverse
297
+ : props.theme.colors.focus} !important;
298
+ }
299
+ outline-offset: 0;
300
+ }
301
+ .cds--overflow-menu-options__btn:focus,
302
+ .cds--overflow-menu:focus,
303
+ .cds--overflow-menu__trigger:focus,
304
+ .toolbar-control:focus {
305
+ outline: 2px solid
306
+ ${props =>
307
+ props.isInverse
308
+ ? props.theme.colors.focusInverse
309
+ : props.theme.colors.focus} !important;
310
+ }
311
+ div.cds--cc--legend.clickable
312
+ div.legend-item:not(.additional):focus
313
+ div.checkbox,
314
+ div.cds--cc--legend.clickable
315
+ div.legend-item:not(.additional):hover
316
+ div.checkbox {
317
+ border: ${props =>
318
+ props.isInverse ? `1px solid ${props.theme.colors.focusInverse}` : ''};
319
+ }
320
+ div.cds--cc--legend.clickable
321
+ div.legend-item:not(.additional):hover
322
+ div.checkbox {
323
+ box-shadow: 0 0 0 2px
324
+ ${props =>
325
+ props.isInverse
326
+ ? props.theme.colors.focusInverse
327
+ : props.theme.colors.focus} !important;
328
+ }
329
+
330
+ .cds--btn--primary {
331
+ &:focus {
332
+ outline: 2px solid
333
+ ${props =>
334
+ props.isInverse
335
+ ? props.theme.colors.focusInverse
336
+ : props.theme.colors.focus};
337
+ }
338
+ outline-offset: 2px;
339
+ border: none;
340
+ box-shadow: none;
341
+ }
342
+ .cds--modal-header {
343
+ background: ${props =>
344
+ props.isInverse
345
+ ? props.theme.colors.primary600
346
+ : props.theme.colors.neutral100};
347
+ margin-bottom: 0;
348
+ border-bottom: 1px solid
349
+ ${props =>
350
+ props.isInverse
351
+ ? transparentize(0.8, props.theme.colors.neutral100)
352
+ : props.theme.colors.neutral300};
353
+ }
354
+ .cds--modal-header__heading {
355
+ font-weight: 600;
356
+ }
357
+
358
+ .cds--modal-close {
359
+ position: absolute;
360
+ top: 0;
361
+ right: 0;
362
+ &:focus {
363
+ outline: 2px solid
364
+ ${props =>
365
+ props.isInverse
366
+ ? props.theme.colors.focusInverse
367
+ : props.theme.colors.focus};
368
+ }
369
+ outline-offset: 0;
370
+ border: none;
371
+ }
372
+ }
373
+
374
+ .cds--modal-footer.cds--modal-footer {
375
+ display: flex;
376
+ align-items: center;
377
+ border-top: 1px solid
378
+ ${props =>
379
+ props.isInverse
380
+ ? transparentize(0.8, props.theme.colors.neutral100)
381
+ : props.theme.colors.neutral300};
382
+ background: ${props =>
383
+ props.isInverse
384
+ ? props.theme.colors.primary600
385
+ : props.theme.colors.neutral100} !important;
386
+ }
387
+ .layout-child.header {
388
+ height: auto !important;
389
+ p {
390
+ text-overflow: inherit;
391
+ overflow: auto;
392
+ white-space: normal;
393
+ }
394
+ }
395
+
396
+ svg:not(:root) {
397
+ overflow: visible;
398
+ }
399
+
400
+ .cds--cc--chart-wrapper text {
401
+ font-size: ${props => props.theme.typeScale.size02.fontSize};
402
+ }
403
+
404
+ g.center text,
405
+ .pie-label{
406
+ fill: ${props => (props.isInverse ? props.theme.colors.neutral100 : '')} ;
407
+ }
408
+
409
+ // Zoom responsive tweaks
410
+
411
+ @media screen and (max-width: 760px) {
412
+ .cds--modal-container {
413
+ overflow-y: auto;
414
+ }
415
+ .cds--chart-holder .cds--modal .cds--modal-container .cds--modal-content {
416
+ overflow: visible;
417
+ }
418
+ .cds--chart-holder
419
+ .cds--modal
420
+ .cds--modal-container
421
+ .cds--modal-content
422
+ table
423
+ th {
424
+ position: relative;
425
+ }
426
+ }
427
+ `;
428
+
429
+ /* Carbon themes
430
+ https://github.com/carbon-design-system/carbon-charts/blob/master/packages/core/src/interfaces/enums.ts#L12)
431
+ */
432
+ enum ChartTheme {
433
+ WHITE = 'white', // default
434
+ G100 = 'g100', // isInverse
435
+ G90 = 'g90',
436
+ G10 = 'g10',
437
+ }
438
+
439
+ interface ColorsObject {
440
+ [key: string]: string;
441
+ }
442
+
443
+ export const CarbonChart = React.forwardRef<HTMLDivElement, CarbonChartProps>(
444
+ (props, ref) => {
445
+ const {
446
+ children,
447
+ testId,
448
+ isInverse: isInverseProp,
449
+ type,
450
+ dataSet,
451
+ options,
452
+ ...rest
453
+ } = props;
454
+ const theme = React.useContext(ThemeContext);
455
+ const isInverse = useIsInverse(isInverseProp);
456
+ const allCharts = {
457
+ area: AreaChart,
458
+ areaStacked: StackedAreaChart,
459
+ bar: SimpleBarChart,
460
+ barGrouped: GroupedBarChart,
461
+ barStacked: StackedBarChart,
462
+ donut: DonutChart,
463
+ line: LineChart,
464
+ lollipop: LollipopChart,
465
+ pie: PieChart,
466
+ };
467
+
468
+ function buildColors() {
469
+ let scaleColorsObj: ColorsObject = {};
470
+
471
+ const allGroups = dataSet.map(item => {
472
+ return 'group' in item ? item['group'] : null;
473
+ });
474
+ const uniqueGroups = allGroups.filter(
475
+ (g, index) => allGroups.indexOf(g) === index
476
+ );
477
+
478
+ uniqueGroups.forEach((group, i) => {
479
+ if (uniqueGroups.length <= theme.chartColors.length) {
480
+ return (scaleColorsObj[group || ('null' as any)] = isInverse
481
+ ? theme.chartColorsInverse[i]
482
+ : theme.chartColors[i]);
483
+ }
484
+ return {};
485
+ });
486
+
487
+ return scaleColorsObj;
488
+ }
489
+
490
+ const newOptions = {
491
+ ...options,
492
+ theme: isInverse ? ChartTheme.G100 : ChartTheme.WHITE,
493
+ color: {
494
+ scale: buildColors(),
495
+ },
496
+ tooltip: {
497
+ truncation: {
498
+ type: 'none',
499
+ },
500
+ },
501
+ };
502
+
503
+ const ChartType = allCharts[type] as any;
504
+
505
+ // Adding aria-label to main SVG container
506
+ React.useEffect(() => {
507
+ document.querySelectorAll('.graph-frame ').forEach(div => {
508
+ div.setAttribute('aria-label', 'Interactive chart');
509
+ });
510
+ });
511
+
512
+ return (
513
+ <CarbonChartWrapper
514
+ data-testid={testId}
515
+ ref={ref}
516
+ isInverse={isInverse}
517
+ theme={theme}
518
+ {...rest}
519
+ >
520
+ <ChartType data={dataSet} options={newOptions} />
521
+ </CarbonChartWrapper>
522
+ );
523
+ }
524
+ );