@auth0/quantum-charts 0.0.3 → 0.1.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 (37) hide show
  1. package/README.md +9 -0
  2. package/bar-chart/index.js +46 -21
  3. package/chart-summary/data-table-chart.d.ts +2 -2
  4. package/chart-summary/data-table-chart.js +46 -4
  5. package/chart-summary/index.d.ts +1 -1
  6. package/common/chart.d.ts +6 -0
  7. package/common/chart.js +30 -0
  8. package/common/custom-legend.d.ts +2 -0
  9. package/common/custom-legend.js +69 -0
  10. package/common/custom-tooltip.d.ts +4 -0
  11. package/common/custom-tooltip.js +54 -0
  12. package/donut-chart/decoupled-legend.d.ts +1 -0
  13. package/donut-chart/decoupled-legend.js +24 -22
  14. package/donut-chart/index.d.ts +2 -0
  15. package/donut-chart/index.js +25 -9
  16. package/esm/bar-chart/index.js +47 -22
  17. package/esm/chart-summary/data-table-chart.js +47 -5
  18. package/esm/common/chart.js +28 -1
  19. package/esm/common/custom-legend.js +42 -0
  20. package/esm/common/custom-tooltip.js +26 -0
  21. package/esm/donut-chart/decoupled-legend.js +26 -21
  22. package/esm/donut-chart/index.js +27 -11
  23. package/esm/line-chart/index.js +56 -18
  24. package/esm/styles.js +11 -11
  25. package/esm/theme.js +37 -21
  26. package/line-chart/index.js +55 -17
  27. package/package.json +16 -13
  28. package/styles.d.ts +3 -4
  29. package/styles.js +11 -14
  30. package/theme.d.ts +10 -2
  31. package/theme.js +39 -24
  32. package/esm/line-chart/custom-tooltip.js +0 -20
  33. package/line-chart/custom-tooltip.d.ts +0 -6
  34. package/line-chart/custom-tooltip.js +0 -48
  35. /package/{custom-color-status-dot.d.ts → common/custom-color-status-dot.d.ts} +0 -0
  36. /package/{custom-color-status-dot.js → common/custom-color-status-dot.js} +0 -0
  37. /package/esm/{custom-color-status-dot.js → common/custom-color-status-dot.js} +0 -0
@@ -17,14 +17,53 @@ var __read = (this && this.__read) || function (o, n) {
17
17
  import _ from 'lodash';
18
18
  import * as React from 'react';
19
19
  import { format } from 'date-fns';
20
- import { Box, Button, DataTable, Dialog, Tab, TabList, TabPanel, Tabs } from '@auth0/quantum-product';
20
+ import { Box, Button, DataTable, Dialog, DownloadIcon, Tab, TabList, TabPanel, Tabs } from '@auth0/quantum-product';
21
21
  export function DataTableChart(props) {
22
22
  var isOpen = props.isOpen, title = props.title, toggleIsOpen = props.toggleIsOpen, data = props.data;
23
23
  var isDonut = data[0] && data[0].name !== undefined;
24
24
  var groups = _.groupBy(data, 'group');
25
25
  var _a = __read(React.useState(Object.keys(groups)[0]), 2), selectedTab = _a[0], setSelectedTab = _a[1];
26
+ var hasKey = data[0] && data[0].key !== undefined;
27
+ var downloadCSV = function (filename) {
28
+ if (filename === void 0) { filename = 'chart data'; }
29
+ var mappedData = data.map(function (row) {
30
+ if (row.date) {
31
+ row.date = format(new Date(row.date), 'LLL d p');
32
+ }
33
+ return Object.values(row).map(function (column) { return "\"".concat(column === '–' ? '–' : column, "\""); });
34
+ });
35
+ mappedData.unshift(Object.keys(data[0]));
36
+ var content = '', csvData = '';
37
+ mappedData.forEach(function (d, i) {
38
+ csvData = d.join(',');
39
+ content += i < data.length ? csvData + '\n' : csvData;
40
+ });
41
+ var anchor = document.createElement('a');
42
+ var mimeType = 'text/csv;encoding:utf-8';
43
+ if (navigator['msSaveBlob']) {
44
+ // Internet Explorer 10
45
+ navigator['msSaveBlob'](new Blob([content], {
46
+ type: mimeType,
47
+ }), filename);
48
+ }
49
+ else if (URL && 'download' in anchor) {
50
+ // HTML5
51
+ var href = URL.createObjectURL(new Blob([content], {
52
+ type: mimeType,
53
+ }));
54
+ anchor.href = href;
55
+ anchor.setAttribute('download', filename);
56
+ document.body.appendChild(anchor);
57
+ anchor.click();
58
+ document.body.removeChild(anchor);
59
+ URL.revokeObjectURL(href);
60
+ }
61
+ else {
62
+ location.href = "data:application/octet-stream,".concat(encodeURIComponent(content));
63
+ }
64
+ };
26
65
  return (React.createElement(Dialog, { open: isOpen, fullWidth: true, title: title, onClose: toggleIsOpen, actions: React.createElement(React.Fragment, null,
27
- React.createElement(Button, { color: "primary", variant: "contained" }, "Download CSV")) },
66
+ React.createElement(Button, { color: "primary", variant: "contained", startIcon: React.createElement(DownloadIcon, null), onClick: function () { return downloadCSV(title); } }, "Download")) },
28
67
  React.createElement(Box, { p: 2 },
29
68
  React.createElement(Tabs, { baseId: 'example', onChange: setSelectedTab, value: selectedTab },
30
69
  React.createElement(TabList, { classes: { indicator: 'chromatic-ignore' } }, !isDonut &&
@@ -45,10 +84,13 @@ export function DataTableChart(props) {
45
84
  var item = _a.item;
46
85
  return item.value || 'N/A';
47
86
  } },
48
- { title: 'date', render: function (_a) {
87
+ {
88
+ title: hasKey ? 'key' : 'date',
89
+ render: function (_a) {
49
90
  var item = _a.item;
50
- return format(new Date(item.date), 'LLL d p');
51
- } },
91
+ return (hasKey ? item.key : format(new Date(item.date), 'LLL d p'));
92
+ },
93
+ },
52
94
  ] })));
53
95
  })))))));
54
96
  }
@@ -1 +1,28 @@
1
- export {};
1
+ import { format } from 'date-fns';
2
+ export var tickFormatter = function (value, scaleType) {
3
+ switch (scaleType) {
4
+ case 'number':
5
+ if (value > 1000000000) {
6
+ return (value / 1000000000).toString() + 'B';
7
+ }
8
+ else if (value > 1000000) {
9
+ return (value / 1000000).toString() + 'M';
10
+ }
11
+ else if (value > 1000) {
12
+ return (value / 1000).toString() + 'K';
13
+ }
14
+ else {
15
+ return value.toString();
16
+ }
17
+ case 'label':
18
+ if (value.length <= 8)
19
+ return value;
20
+ return "".concat(value.substring(0, 8), "...");
21
+ case 'date':
22
+ return format(new Date(value), 'LLL d');
23
+ case 'datetime':
24
+ return format(new Date(value), 'LLL d p');
25
+ default:
26
+ break;
27
+ }
28
+ };
@@ -0,0 +1,42 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { StackLayout, Text, styled } from '@auth0/quantum-product';
13
+ import * as React from 'react';
14
+ var Root = styled(StackLayout)(function (_a) {
15
+ var theme = _a.theme;
16
+ return ({
17
+ justifyContent: 'center',
18
+ marginTop: theme.spacing(3),
19
+ });
20
+ });
21
+ var LegendIcon = styled('div')(function (_a) {
22
+ var theme = _a.theme, ownerState = _a.ownerState;
23
+ return (__assign({}, (ownerState.isHide
24
+ ? {
25
+ borderRadius: theme.spacing(0.5),
26
+ border: "2px solid ".concat(ownerState.color),
27
+ width: '14px',
28
+ height: '14px',
29
+ }
30
+ : {
31
+ background: ownerState.color,
32
+ width: '14px',
33
+ height: '14px',
34
+ borderRadius: '4px',
35
+ })));
36
+ });
37
+ export var CustomLegend = function (props) {
38
+ var payload = props.payload, selectData = props.selectData, handleLegendMouseEnter = props.handleLegendMouseEnter, handleLegendMouseLeave = props.handleLegendMouseLeave, dataVisibility = props.dataVisibility;
39
+ return (React.createElement(Root, { gutter: 1 }, payload.map(function (entry, index) { return (React.createElement(StackLayout, { sx: { padding: '4px 8px', cursor: 'pointer' }, key: index, gutter: 1, onClick: function () { return selectData(entry); }, onMouseEnter: function () { return handleLegendMouseEnter(entry); }, onMouseLeave: function () { return handleLegendMouseLeave(entry); } },
40
+ React.createElement(LegendIcon, { ownerState: { isHide: dataVisibility[entry.dataKey], color: entry.color } }),
41
+ React.createElement(Text, { variant: "body2" }, entry.value))); })));
42
+ };
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ import { Box, RowLayout, StackLayout, Text } from '@auth0/quantum-product';
3
+ import StatusDot from './custom-color-status-dot';
4
+ import { format } from 'date-fns';
5
+ import { CustomTooltip as CustomTooltipStyled } from '../styles';
6
+ var CustomTooltip = function (props) {
7
+ var _a, _b, _c;
8
+ var active = props.active, payload = props.payload, scaleType = props.scaleType, labelProp = props.label;
9
+ if (active && payload && payload.length) {
10
+ var label = ((_a = payload[0].payload) === null || _a === void 0 ? void 0 : _a.date)
11
+ ? scaleType === 'datetime'
12
+ ? "".concat(format(new Date((_b = payload[0].payload) === null || _b === void 0 ? void 0 : _b.date), 'LLL d HH:mm'))
13
+ : "".concat(format(new Date((_c = payload[0].payload) === null || _c === void 0 ? void 0 : _c.date), 'LLL d'))
14
+ : labelProp;
15
+ return (React.createElement(CustomTooltipStyled, null,
16
+ React.createElement(Text, { color: "text.secondary" }, label),
17
+ React.createElement(Box, null,
18
+ React.createElement(RowLayout, { gutter: 1 }, payload.map(function (x, index) {
19
+ return (React.createElement(StackLayout, { key: index, gutter: 0.5 },
20
+ React.createElement(StatusDot, { key: index, dotColor: x.color || 'grey', label: "".concat(x.name, ":") + ' ' }),
21
+ React.createElement(Text, { color: "text.secondary" }, x.payload[x.name || ''])));
22
+ })))));
23
+ }
24
+ return null;
25
+ };
26
+ export default CustomTooltip;
@@ -1,18 +1,33 @@
1
- var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
2
- if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
- return cooked;
4
- };
5
1
  import * as React from 'react';
6
- import styled from 'styled-components';
7
- import { StackLayout, StackLayoutItem, useTheme } from '@auth0/quantum-product';
8
- import { getBaseColorScale } from '../theme';
2
+ import { StackLayout, StackLayoutItem, styled, useTheme } from '@auth0/quantum-product';
3
+ import { getColorScale } from '../theme';
4
+ var Root = styled('div')({
5
+ display: 'flex',
6
+ flexDirection: 'column',
7
+ gap: '8px',
8
+ height: '150px',
9
+ flexWrap: 'wrap',
10
+ });
11
+ var LegendDot = styled('div')({
12
+ height: '14px',
13
+ width: '14px',
14
+ borderRadius: '4px',
15
+ });
16
+ var LegendText = styled('span')({
17
+ whiteSpace: 'nowrap',
18
+ overflow: 'hidden',
19
+ textOverflow: 'ellipsis',
20
+ cursor: 'default',
21
+ });
9
22
  function DecoupledLegend(props) {
10
- var data = props.data, activeIndex = props.activeIndex, setActiveIndex = props.setActiveIndex;
23
+ var data = props.data, activeIndex = props.activeIndex, setActiveIndex = props.setActiveIndex, _a = props.color, color = _a === void 0 ? 'categorical' : _a;
11
24
  var theme = useTheme();
12
- var BASE_COLORS = getBaseColorScale(theme);
13
- return (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: '8px', height: '150px', flexWrap: 'wrap' } }, data.map(function (datum, index) {
25
+ var BASE_COLORS = getColorScale(theme)[color]['base'];
26
+ var MUTED_COLORS = getColorScale(theme)[color]['muted'];
27
+ return (React.createElement(Root, null, data.map(function (datum, index) {
14
28
  var isActive = activeIndex !== undefined && activeIndex === index;
15
29
  var color = BASE_COLORS[index % BASE_COLORS.length];
30
+ var mutedColor = MUTED_COLORS[index % MUTED_COLORS.length];
16
31
  return (React.createElement(React.Fragment, { key: index },
17
32
  React.createElement(StackLayout, { gutter: 1, onMouseEnter: function () {
18
33
  setActiveIndex(index);
@@ -24,21 +39,11 @@ function DecoupledLegend(props) {
24
39
  React.createElement(StackLayoutItem, { sx: {
25
40
  alignSelf: 'center',
26
41
  } },
27
- React.createElement(LegendDotWrapper, { style: {
28
- border: '2px solid ' + (isActive ? color : 'white'),
29
- } },
30
- React.createElement(LegendDot, { style: { backgroundColor: color } }))),
42
+ React.createElement(LegendDot, { style: { backgroundColor: activeIndex === undefined ? color : isActive ? color : mutedColor } })),
31
43
  React.createElement(StackLayoutItem, { sx: {
32
44
  alignSelf: 'center',
33
45
  } },
34
46
  React.createElement(LegendText, { color: isActive ? 'primary' : 'secondary' }, datum.name)))));
35
47
  })));
36
48
  }
37
- var LegendDot = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n height: 12px;\n width: 12px;\n border: 2px solid white;\n border-radius: 2px;\n"], ["\n height: 12px;\n width: 12px;\n border: 2px solid white;\n border-radius: 2px;\n"])));
38
- var LegendDotWrapper = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n border-radius: 4px;\n"], ["\n border-radius: 4px;\n"])));
39
- var LegendText = styled.span(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n color: ", ";\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: default;\n"], ["\n color: ", ";\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: default;\n"])), function (_a) {
40
- var theme = _a.theme, color = _a.color;
41
- return theme.palette.text[color !== null && color !== void 0 ? color : 'secondary'];
42
- });
43
49
  export default DecoupledLegend;
44
- var templateObject_1, templateObject_2, templateObject_3;
@@ -1,3 +1,14 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
1
12
  var __read = (this && this.__read) || function (o, n) {
2
13
  var m = typeof Symbol === "function" && o[Symbol.iterator];
3
14
  if (!m) return o;
@@ -16,22 +27,27 @@ var __read = (this && this.__read) || function (o, n) {
16
27
  };
17
28
  import * as React from 'react';
18
29
  import { Cell, Pie, PieChart as RechartsPieChart, ResponsiveContainer } from 'recharts';
19
- import { StackLayout, StackLayoutItem, useTheme } from '@auth0/quantum-product';
20
- import { getBaseColorScale } from '../theme';
30
+ import { StackLayout, StackLayoutItem, styled, useTheme } from '@auth0/quantum-product';
31
+ import { getColorScale } from '../theme';
21
32
  import Center from './center';
22
33
  import DecoupledLegend from './decoupled-legend';
23
34
  import { ChartCard } from '../chart-card';
35
+ var ResponsiveChartCard = styled(StackLayout)(function (_a) {
36
+ var _b;
37
+ var theme = _a.theme, ownerState = _a.ownerState;
38
+ return (__assign((_b = {}, _b[theme.breakpoints.down('sm')] = {
39
+ flexDirection: 'column',
40
+ }, _b.flexWrap = 'nowrap', _b.marginTop = theme.spacing(3), _b), (ownerState.layout === 'vertical' && {
41
+ flexDirection: 'column',
42
+ })));
43
+ });
24
44
  export function DonutChart(props) {
25
- var data = props.data, displayType = props.displayType, title = props.title, value = props.value, label = props.label, helperText = props.helperText;
26
- var _a = __read(React.useState(undefined), 2), activeIndex = _a[0], setActiveIndex = _a[1];
45
+ var data = props.data, displayType = props.displayType, title = props.title, value = props.value, label = props.label, helperText = props.helperText, _a = props.layout, layout = _a === void 0 ? 'horizontal' : _a, _b = props.color, color = _b === void 0 ? 'categorical' : _b;
46
+ var _c = __read(React.useState(undefined), 2), activeIndex = _c[0], setActiveIndex = _c[1];
27
47
  var theme = useTheme();
28
- var BASE_COLORS = getBaseColorScale(theme);
48
+ var BASE_COLORS = getColorScale(theme)[color]['base'];
29
49
  return (React.createElement(ChartCard, { title: title, value: value, dataTable: data, label: label, helperText: helperText },
30
- React.createElement(StackLayout, { sx: {
31
- height: '150px',
32
- flexWrap: 'nowrap',
33
- mt: '24px',
34
- } },
50
+ React.createElement(ResponsiveChartCard, { ownerState: { layout: layout } },
35
51
  React.createElement(StackLayoutItem, { sx: {
36
52
  height: '150px',
37
53
  width: '150px',
@@ -48,5 +64,5 @@ export function DonutChart(props) {
48
64
  return (React.createElement(Cell, { key: "cell-".concat(index), fill: BASE_COLORS[index % BASE_COLORS.length], opacity: activeIndex === undefined ? 1 : activeIndex === index ? 1 : 0.5 }));
49
65
  }))))),
50
66
  React.createElement(StackLayoutItem, null,
51
- React.createElement(DecoupledLegend, { activeIndex: activeIndex, setActiveIndex: setActiveIndex, data: data })))));
67
+ React.createElement(DecoupledLegend, { activeIndex: activeIndex, setActiveIndex: setActiveIndex, data: data, color: color })))));
52
68
  }
@@ -1,17 +1,62 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __read = (this && this.__read) || function (o, n) {
13
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
14
+ if (!m) return o;
15
+ var i = m.call(o), r, ar = [], e;
16
+ try {
17
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
18
+ }
19
+ catch (error) { e = { error: error }; }
20
+ finally {
21
+ try {
22
+ if (r && !r.done && (m = i["return"])) m.call(i);
23
+ }
24
+ finally { if (e) throw e.error; }
25
+ }
26
+ return ar;
27
+ };
1
28
  import _ from 'lodash';
2
29
  import * as React from 'react';
3
30
  import { CartesianGrid, Legend, Line, LineChart as RechartsLineChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
4
- import { format } from 'date-fns';
5
31
  import { useTheme, Text } from '@auth0/quantum-product';
6
- import { getBaseColorScale } from '../theme';
32
+ import { getColorScale } from '../theme';
7
33
  import CustomActiveDot from './custom-active-dot';
8
- import CustomTooltip from './custom-tooltip';
34
+ import CustomTooltip from '../common/custom-tooltip';
9
35
  import { ChartCard } from '../chart-card';
36
+ import { tickFormatter } from '../common/chart';
37
+ import { CustomLegend } from '../common/custom-legend';
10
38
  export function LineChart(props) {
11
- var _a = props, data = _a.data, leftAxis = _a.leftAxis, bottomAxis = _a.bottomAxis, _b = _a.height, height = _b === void 0 ? 300 : _b, title = _a.title, value = _a.value, label = _a.label, helperText = _a.helperText, _c = _a.legend, legend = _c === void 0 ? true : _c, syncId = _a.syncId;
39
+ var _a = props, data = _a.data, leftAxis = _a.leftAxis, bottomAxis = _a.bottomAxis, _b = _a.height, height = _b === void 0 ? 300 : _b, title = _a.title, value = _a.value, label = _a.label, helperText = _a.helperText, _c = _a.legend, legend = _c === void 0 ? true : _c, syncId = _a.syncId, _d = _a.color, color = _d === void 0 ? 'categorical' : _d;
12
40
  var theme = useTheme();
13
41
  // Function to know how many lines we need based of how much different group values are.
14
42
  var groups = _.uniqBy(data, 'group').map(function (item) { return item.group; });
43
+ var initialState = __assign({ hover: null }, groups.reduce(function (acc, group) {
44
+ var _a;
45
+ return (__assign(__assign({}, acc), (_a = {}, _a[group] = false, _a)));
46
+ }, {}));
47
+ var _e = __read(React.useState(initialState), 2), lineVisibility = _e[0], setLineVisibility = _e[1];
48
+ var handleLegendMouseEnter = function (e) {
49
+ if (!lineVisibility[e.dataKey]) {
50
+ setLineVisibility(__assign(__assign({}, lineVisibility), { hover: e.dataKey }));
51
+ }
52
+ };
53
+ var handleLegendMouseLeave = function () {
54
+ setLineVisibility(__assign(__assign({}, lineVisibility), { hover: null }));
55
+ };
56
+ var selectLine = function (e) {
57
+ var _a;
58
+ setLineVisibility(__assign(__assign({}, lineVisibility), (_a = {}, _a[e.dataKey] = !lineVisibility[e.dataKey], _a.hover = null, _a)));
59
+ };
15
60
  var bottomAxisDataKey = bottomAxis.mapsTo || 'date';
16
61
  var leftAxisDataKey = leftAxis.mapsTo || 'value';
17
62
  var entries = {};
@@ -32,15 +77,6 @@ export function LineChart(props) {
32
77
  _b[entry.group] = entry[leftAxisDataKey],
33
78
  _b;
34
79
  });
35
- var formatBottomTick = function (value) {
36
- if (bottomAxis.scaleType === 'date') {
37
- return format(new Date(value), 'LLL d');
38
- }
39
- if (bottomAxis.scaleType === 'datetime') {
40
- return format(new Date(value), 'LLL d p');
41
- }
42
- return value;
43
- };
44
80
  return (React.createElement(ChartCard, { title: title, value: value, dataTable: data, label: label, helperText: helperText },
45
81
  React.createElement(ResponsiveContainer, { width: '100%', height: height }, data.length ? (React.createElement(RechartsLineChart, { data: Object.values(entries), height: height, width: 500, syncId: syncId, margin: {
46
82
  top: 24,
@@ -48,13 +84,15 @@ export function LineChart(props) {
48
84
  left: -24,
49
85
  bottom: 0,
50
86
  } },
51
- React.createElement(XAxis, { tickFormatter: formatBottomTick, dataKey: bottomAxisDataKey, height: 30, interval: "preserveStartEnd" }),
52
87
  React.createElement(CartesianGrid, { vertical: false, stroke: theme.tokens.color_border_default }),
53
- React.createElement(YAxis, { domain: ['auto', 'auto'] }),
54
- React.createElement(Tooltip, { content: React.createElement(CustomTooltip, { active: undefined, payload: undefined }) }),
55
- legend && React.createElement(Legend, { align: "center", iconType: "square", iconSize: 14, wrapperStyle: { paddingTop: 16 } }),
88
+ React.createElement(XAxis, { tickFormatter: function (value) { return tickFormatter(value, bottomAxis.scaleType); }, dataKey: bottomAxisDataKey, height: 30, interval: "preserveStartEnd", minTickGap: theme.spacingPX(14), tickMargin: theme.spacingPX(3), axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold } }),
89
+ React.createElement(YAxis, { tickFormatter: function (value) { return tickFormatter(value, leftAxis.scaleType); }, domain: ['auto', 'auto'], width: 78, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold } }),
90
+ React.createElement(Tooltip, { wrapperStyle: { outline: 'none' }, content: React.createElement(CustomTooltip, { active: undefined, payload: undefined, scaleType: bottomAxis.scaleType }) }),
91
+ legend && (React.createElement(Legend, { align: "center", iconSize: 14, wrapperStyle: { paddingTop: 16 }, content: React.createElement(CustomLegend, { selectData: selectLine, handleLegendMouseEnter: handleLegendMouseEnter, handleLegendMouseLeave: handleLegendMouseLeave, dataVisibility: lineVisibility }) })),
56
92
  groups.map(function (group, index) {
57
- return (React.createElement(Line, { key: group, dataKey: group, name: group, strokeWidth: 3, stroke: getBaseColorScale(theme)[index], dot: false, activeDot: CustomActiveDot() }));
93
+ return (React.createElement(Line, { key: group, dataKey: group, name: group, strokeWidth: 3, hide: lineVisibility[group] === true, stroke: lineVisibility.hover === group || !lineVisibility.hover
94
+ ? getColorScale(theme)[color]['base'][index]
95
+ : getColorScale(theme)[color]['muted'][index], dot: false, activeDot: CustomActiveDot() }));
58
96
  }))) : (React.createElement("div", { style: {
59
97
  display: 'grid',
60
98
  placeItems: 'center',
package/esm/styles.js CHANGED
@@ -2,9 +2,8 @@ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cook
2
2
  if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
3
  return cooked;
4
4
  };
5
- import styled from 'styled-components';
6
- import { Box } from '@auth0/quantum-product';
7
- export var ChartContainer = styled.div(function (_a) {
5
+ import { Box, styled } from '@auth0/quantum-product';
6
+ export var ChartContainer = styled('div')(function (_a) {
8
7
  var theme = _a.theme, height = _a.height, marginTop = _a.marginTop;
9
8
  var props = {
10
9
  marginTop: theme.spacing(3),
@@ -18,20 +17,21 @@ export var ChartContainer = styled.div(function (_a) {
18
17
  }
19
18
  return props;
20
19
  });
21
- export var CustomTooltip = styled.div(function (_a) {
20
+ export var CustomTooltip = styled('div')(function (_a) {
22
21
  var theme = _a.theme;
23
22
  return ({
24
- backgroundColor: theme.tokens.color_bg_layer_boldest,
23
+ display: 'grid',
24
+ gap: theme.spacing(1),
25
+ backgroundColor: theme.tokens.color_bg_layer_elevated,
26
+ border: "1px solid ".concat(theme.tokens.color_border_bold),
25
27
  borderRadius: theme.shape.borderRadius,
26
- padding: theme.spacing(1, 3),
27
- color: theme.tokens.color_fg_inverse,
28
+ padding: theme.spacing(1, 2),
29
+ color: theme.tokens.color_fg_bold,
28
30
  fontSize: theme.typography.caption.fontSize,
29
31
  fontWeight: theme.typography.caption.fontWeight,
30
32
  lineHeight: theme.typography.caption.lineHeight,
31
33
  letterSpacing: theme.typography.caption.letterSpacing,
32
34
  });
33
35
  });
34
- // `textSecondary` doesn't have enough contrast for the black background of the tooltip
35
- export var CustomTooltipLabel = styled.span(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: lightgrey;\n"], ["\n color: lightgrey;\n"])));
36
- export var DefaultCursorBox = styled(Box)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n cursor: default;\n"], ["\n cursor: default;\n"])));
37
- var templateObject_1, templateObject_2;
36
+ export var DefaultCursorBox = styled(Box)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n cursor: default;\n"], ["\n cursor: default;\n"])));
37
+ var templateObject_1;
package/esm/theme.js CHANGED
@@ -1,22 +1,38 @@
1
- export var getBaseColorScale = function (_a) {
2
- var palette = _a.palette;
3
- return [
4
- palette.purple[500],
5
- palette.magenta[500],
6
- palette.green[500],
7
- palette.yellow[500],
8
- palette.red[500],
9
- palette.neutral[500],
10
- ];
11
- };
12
- export var getBaseColorScaleMuted = function (_a) {
13
- var palette = _a.palette;
14
- return [
15
- palette.purple[300],
16
- palette.yellow[300],
17
- palette.green[300],
18
- palette.red[300],
19
- palette.neutral[300],
20
- palette.magenta[300],
21
- ];
1
+ import { alpha } from '@auth0/quantum-product';
2
+ export var getColorScale = function (_a) {
3
+ var tokens = _a.tokens;
4
+ return {
5
+ categorical: {
6
+ base: [
7
+ tokens.color_chart_categorical_1,
8
+ tokens.color_chart_categorical_2,
9
+ tokens.color_chart_categorical_3,
10
+ tokens.color_chart_categorical_4,
11
+ tokens.color_chart_categorical_5,
12
+ tokens.color_chart_categorical_6,
13
+ ],
14
+ muted: [
15
+ alpha(tokens.color_chart_categorical_1, 0.35),
16
+ alpha(tokens.color_chart_categorical_2, 0.35),
17
+ alpha(tokens.color_chart_categorical_3, 0.35),
18
+ alpha(tokens.color_chart_categorical_4, 0.35),
19
+ alpha(tokens.color_chart_categorical_5, 0.35),
20
+ alpha(tokens.color_chart_categorical_6, 0.35),
21
+ ],
22
+ },
23
+ sequential: {
24
+ base: [
25
+ tokens.color_chart_sequential_1,
26
+ tokens.color_chart_sequential_2,
27
+ tokens.color_chart_sequential_3,
28
+ tokens.color_chart_sequential_4,
29
+ ],
30
+ muted: [
31
+ alpha(tokens.color_chart_sequential_1, 0.35),
32
+ alpha(tokens.color_chart_sequential_2, 0.35),
33
+ alpha(tokens.color_chart_sequential_3, 0.35),
34
+ alpha(tokens.color_chart_sequential_4, 0.35),
35
+ ],
36
+ },
37
+ };
22
38
  };
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
14
  if (k2 === undefined) k2 = k;
4
15
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -22,6 +33,22 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
33
  __setModuleDefault(result, mod);
23
34
  return result;
24
35
  };
36
+ var __read = (this && this.__read) || function (o, n) {
37
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
38
+ if (!m) return o;
39
+ var i = m.call(o), r, ar = [], e;
40
+ try {
41
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
42
+ }
43
+ catch (error) { e = { error: error }; }
44
+ finally {
45
+ try {
46
+ if (r && !r.done && (m = i["return"])) m.call(i);
47
+ }
48
+ finally { if (e) throw e.error; }
49
+ }
50
+ return ar;
51
+ };
25
52
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
53
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
54
  };
@@ -30,17 +57,35 @@ exports.LineChart = void 0;
30
57
  var lodash_1 = __importDefault(require("lodash"));
31
58
  var React = __importStar(require("react"));
32
59
  var recharts_1 = require("recharts");
33
- var date_fns_1 = require("date-fns");
34
60
  var quantum_product_1 = require("@auth0/quantum-product");
35
61
  var theme_1 = require("../theme");
36
62
  var custom_active_dot_1 = __importDefault(require("./custom-active-dot"));
37
- var custom_tooltip_1 = __importDefault(require("./custom-tooltip"));
63
+ var custom_tooltip_1 = __importDefault(require("../common/custom-tooltip"));
38
64
  var chart_card_1 = require("../chart-card");
65
+ var chart_1 = require("../common/chart");
66
+ var custom_legend_1 = require("../common/custom-legend");
39
67
  function LineChart(props) {
40
- var _a = props, data = _a.data, leftAxis = _a.leftAxis, bottomAxis = _a.bottomAxis, _b = _a.height, height = _b === void 0 ? 300 : _b, title = _a.title, value = _a.value, label = _a.label, helperText = _a.helperText, _c = _a.legend, legend = _c === void 0 ? true : _c, syncId = _a.syncId;
68
+ var _a = props, data = _a.data, leftAxis = _a.leftAxis, bottomAxis = _a.bottomAxis, _b = _a.height, height = _b === void 0 ? 300 : _b, title = _a.title, value = _a.value, label = _a.label, helperText = _a.helperText, _c = _a.legend, legend = _c === void 0 ? true : _c, syncId = _a.syncId, _d = _a.color, color = _d === void 0 ? 'categorical' : _d;
41
69
  var theme = (0, quantum_product_1.useTheme)();
42
70
  // Function to know how many lines we need based of how much different group values are.
43
71
  var groups = lodash_1.default.uniqBy(data, 'group').map(function (item) { return item.group; });
72
+ var initialState = __assign({ hover: null }, groups.reduce(function (acc, group) {
73
+ var _a;
74
+ return (__assign(__assign({}, acc), (_a = {}, _a[group] = false, _a)));
75
+ }, {}));
76
+ var _e = __read(React.useState(initialState), 2), lineVisibility = _e[0], setLineVisibility = _e[1];
77
+ var handleLegendMouseEnter = function (e) {
78
+ if (!lineVisibility[e.dataKey]) {
79
+ setLineVisibility(__assign(__assign({}, lineVisibility), { hover: e.dataKey }));
80
+ }
81
+ };
82
+ var handleLegendMouseLeave = function () {
83
+ setLineVisibility(__assign(__assign({}, lineVisibility), { hover: null }));
84
+ };
85
+ var selectLine = function (e) {
86
+ var _a;
87
+ setLineVisibility(__assign(__assign({}, lineVisibility), (_a = {}, _a[e.dataKey] = !lineVisibility[e.dataKey], _a.hover = null, _a)));
88
+ };
44
89
  var bottomAxisDataKey = bottomAxis.mapsTo || 'date';
45
90
  var leftAxisDataKey = leftAxis.mapsTo || 'value';
46
91
  var entries = {};
@@ -61,15 +106,6 @@ function LineChart(props) {
61
106
  _b[entry.group] = entry[leftAxisDataKey],
62
107
  _b;
63
108
  });
64
- var formatBottomTick = function (value) {
65
- if (bottomAxis.scaleType === 'date') {
66
- return (0, date_fns_1.format)(new Date(value), 'LLL d');
67
- }
68
- if (bottomAxis.scaleType === 'datetime') {
69
- return (0, date_fns_1.format)(new Date(value), 'LLL d p');
70
- }
71
- return value;
72
- };
73
109
  return (React.createElement(chart_card_1.ChartCard, { title: title, value: value, dataTable: data, label: label, helperText: helperText },
74
110
  React.createElement(recharts_1.ResponsiveContainer, { width: '100%', height: height }, data.length ? (React.createElement(recharts_1.LineChart, { data: Object.values(entries), height: height, width: 500, syncId: syncId, margin: {
75
111
  top: 24,
@@ -77,13 +113,15 @@ function LineChart(props) {
77
113
  left: -24,
78
114
  bottom: 0,
79
115
  } },
80
- React.createElement(recharts_1.XAxis, { tickFormatter: formatBottomTick, dataKey: bottomAxisDataKey, height: 30, interval: "preserveStartEnd" }),
81
116
  React.createElement(recharts_1.CartesianGrid, { vertical: false, stroke: theme.tokens.color_border_default }),
82
- React.createElement(recharts_1.YAxis, { domain: ['auto', 'auto'] }),
83
- React.createElement(recharts_1.Tooltip, { content: React.createElement(custom_tooltip_1.default, { active: undefined, payload: undefined }) }),
84
- legend && React.createElement(recharts_1.Legend, { align: "center", iconType: "square", iconSize: 14, wrapperStyle: { paddingTop: 16 } }),
117
+ React.createElement(recharts_1.XAxis, { tickFormatter: function (value) { return (0, chart_1.tickFormatter)(value, bottomAxis.scaleType); }, dataKey: bottomAxisDataKey, height: 30, interval: "preserveStartEnd", minTickGap: theme.spacingPX(14), tickMargin: theme.spacingPX(3), axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold } }),
118
+ React.createElement(recharts_1.YAxis, { tickFormatter: function (value) { return (0, chart_1.tickFormatter)(value, leftAxis.scaleType); }, domain: ['auto', 'auto'], width: 78, axisLine: { stroke: theme.tokens.color_border_bold }, tickLine: { stroke: theme.tokens.color_border_bold } }),
119
+ React.createElement(recharts_1.Tooltip, { wrapperStyle: { outline: 'none' }, content: React.createElement(custom_tooltip_1.default, { active: undefined, payload: undefined, scaleType: bottomAxis.scaleType }) }),
120
+ legend && (React.createElement(recharts_1.Legend, { align: "center", iconSize: 14, wrapperStyle: { paddingTop: 16 }, content: React.createElement(custom_legend_1.CustomLegend, { selectData: selectLine, handleLegendMouseEnter: handleLegendMouseEnter, handleLegendMouseLeave: handleLegendMouseLeave, dataVisibility: lineVisibility }) })),
85
121
  groups.map(function (group, index) {
86
- return (React.createElement(recharts_1.Line, { key: group, dataKey: group, name: group, strokeWidth: 3, stroke: (0, theme_1.getBaseColorScale)(theme)[index], dot: false, activeDot: (0, custom_active_dot_1.default)() }));
122
+ return (React.createElement(recharts_1.Line, { key: group, dataKey: group, name: group, strokeWidth: 3, hide: lineVisibility[group] === true, stroke: lineVisibility.hover === group || !lineVisibility.hover
123
+ ? (0, theme_1.getColorScale)(theme)[color]['base'][index]
124
+ : (0, theme_1.getColorScale)(theme)[color]['muted'][index], dot: false, activeDot: (0, custom_active_dot_1.default)() }));
87
125
  }))) : (React.createElement("div", { style: {
88
126
  display: 'grid',
89
127
  placeItems: 'center',