react-metric-card
Version:
A metric card component that provides data display with icons, loaders and comparisons, along with custom text segments
496 lines (469 loc) • 12.6 kB
JavaScript
import React from 'react';
import { makeStyles, ThemeProvider } from '@material-ui/styles';
import { colors, createMuiTheme, Card, ButtonBase, CardContent, Grid, Typography, Icon, CircularProgress, Tooltip } from '@material-ui/core';
import PropTypes from 'prop-types';
import TrendingFlatIcon from '@material-ui/icons/TrendingFlat';
import TrendingUpIcon from '@material-ui/icons/TrendingUp';
import TrendingDownIcon from '@material-ui/icons/TrendingDown';
import InsertChartIcon from '@material-ui/icons/InsertChartOutlined';
import ErrorIcon from '@material-ui/icons/Error';
var white = '#FFFFFF';
var black = '#000000';
var green = '#00e676';
var palette = {
black: black,
white: white,
primary: {
contrastText: white,
dark: colors.indigo[900],
main: colors.indigo[500],
light: colors.indigo[100]
},
secondary: {
contrastText: white,
dark: colors.blue[900],
main: colors.blue.A400,
light: colors.blue.A400
},
success: {
contrastText: white,
dark: colors.green[900],
main: colors.green[600],
light: colors.green[400]
},
info: {
contrastText: white,
dark: colors.blue[900],
main: colors.blue[600],
light: colors.blue[400]
},
warning: {
contrastText: white,
dark: colors.orange[900],
main: colors.orange[600],
light: colors.orange[400]
},
error: {
contrastText: white,
dark: colors.red[900],
main: colors.red[600],
light: colors.red[400]
},
text: {
primary: colors.blueGrey[900],
secondary: colors.blueGrey[600],
link: colors.blue[600]
},
background: {
"default": '#F4F6F8',
paper: white
},
icon: {
primary: '#006066',
secondary: green
},
divider: colors.grey[200]
};
var typography = {
h1: {
color: palette.text.primary,
fontWeight: 500,
fontSize: '35px',
letterSpacing: '-0.24px',
lineHeight: '40px'
},
h2: {
color: palette.text.primary,
fontWeight: 500,
fontSize: '29px',
letterSpacing: '-0.24px',
lineHeight: '32px'
},
h3: {
color: palette.text.primary,
fontWeight: 500,
fontSize: '24px',
letterSpacing: '-0.06px',
lineHeight: '28px'
},
h4: {
color: palette.text.primary,
fontWeight: 500,
fontSize: '20px',
letterSpacing: '-0.06px',
lineHeight: '24px'
},
h5: {
color: palette.text.primary,
fontWeight: 500,
fontSize: '16px',
letterSpacing: '-0.05px',
lineHeight: '20px'
},
h6: {
color: palette.text.primary,
fontWeight: 500,
fontSize: '14px',
letterSpacing: '-0.05px',
lineHeight: '20px'
},
subtitle1: {
color: palette.text.primary,
fontSize: '16px',
letterSpacing: '-0.05px',
lineHeight: '25px'
},
subtitle2: {
color: palette.text.secondary,
fontWeight: 400,
fontSize: '14px',
letterSpacing: '-0.05px',
lineHeight: '21px'
},
body1: {
color: palette.text.primary,
fontSize: '14px',
letterSpacing: '-0.05px',
lineHeight: '21px'
},
body2: {
color: palette.text.secondary,
fontSize: '12px',
letterSpacing: '-0.04px',
lineHeight: '18px'
},
button: {
color: palette.text.primary,
fontSize: '14px'
},
caption: {
color: palette.text.secondary,
fontSize: '11px',
letterSpacing: '0.33px',
lineHeight: '13px'
},
overline: {
color: palette.text.secondary,
fontSize: '11px',
fontWeight: 500,
letterSpacing: '0.33px',
lineHeight: '13px',
textTransform: 'uppercase'
}
};
var MuiButton = {
contained: {
boxShadow: '0 1px 1px 0 rgba(0,0,0,0.14), 0 2px 1px -1px rgba(0,0,0,0.12), 0 1px 3px 0 rgba(0,0,0,0.20)',
backgroundColor: '#FFFFFF'
}
};
var MuiIconButton = {
root: {
color: palette.icon,
'&:hover': {
backgroundColor: 'rgba(0, 0, 0, 0.03)'
}
}
};
var MuiPaper = {
elevation1: {
boxShadow: '0 0 0 1px rgba(63,63,68,0.05), 0 1px 3px 0 rgba(63,63,68,0.15)'
}
};
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
var MuiTableCell = {
root: _extends({}, typography.body1, {
borderBottom: "1px solid " + palette.divider
})
};
var MuiTableHead = {
root: {
backgroundColor: colors.grey[50]
}
};
var MuiTypography = {
gutterBottom: {
marginBottom: 8
}
};
var overrides = {
MuiButton: MuiButton,
MuiIconButton: MuiIconButton,
MuiPaper: MuiPaper,
MuiTableCell: MuiTableCell,
MuiTableHead: MuiTableHead,
MuiTypography: MuiTypography
};
var theme = createMuiTheme({
palette: palette,
typography: typography,
overrides: overrides,
zIndex: {
appBar: 100,
drawer: 1200
}
});
function toVal(mix) {
var k, y, str='';
if (typeof mix === 'string' || typeof mix === 'number') {
str += mix;
} else if (typeof mix === 'object') {
if (Array.isArray(mix)) {
for (k=0; k < mix.length; k++) {
if (mix[k]) {
if (y = toVal(mix[k])) {
str && (str += ' ');
str += y;
}
}
}
} else {
for (k in mix) {
if (mix[k]) {
str && (str += ' ');
str += k;
}
}
}
}
return str;
}
function clsx () {
var i=0, tmp, x, str='';
while (i < arguments.length) {
if (tmp = arguments[i++]) {
if (x = toVal(tmp)) {
str && (str += ' ');
str += x;
}
}
}
return str;
}
var useStyles = makeStyles(function (theme) {
return {
content: {
alignItems: 'center',
display: 'flex'
},
cardAction: {
display: 'block',
textAlign: 'initial',
height: '100%',
width: '100%'
},
title: {
fontWeight: 800,
color: '#ff0000',
font: 'Courier New'
},
avatar: {
backgroundColor: theme.palette.error.main,
height: 56,
width: 56
},
difference: {
marginTop: theme.spacing(2),
display: 'flex',
alignItems: 'center'
},
differenceIconSuccess: {
color: theme.palette.success.main
},
differenceIconInfo: {
color: theme.palette.info.main
},
differenceIconError: {
color: theme.palette.error.main
},
differenceValueSuccess: {
color: theme.palette.success.main,
marginRight: theme.spacing(1)
},
differenceValueInfo: {
color: theme.palette.info.main,
marginRight: theme.spacing(1)
},
differenceValueError: {
color: theme.palette.error.main,
marginRight: theme.spacing(1)
},
error: {
color: theme.palette.error.main
}
};
});
var renderMetricTrend = function renderMetricTrend(trend, classes) {
var _trend$slope = trend.slope,
slope = _trend$slope === void 0 ? 0 : _trend$slope,
_trend$description = trend.description,
description = _trend$description === void 0 ? '' : _trend$description;
var trendValueClass = '';
var trendIcon = '';
if (slope > 0) {
trendValueClass = classes.differenceValueSuccess;
trendIcon = /*#__PURE__*/React.createElement(TrendingUpIcon, {
className: classes.differenceIconSuccess
});
} else if (slope < 0) {
trendValueClass = classes.differenceValueError;
trendIcon = /*#__PURE__*/React.createElement(TrendingDownIcon, {
className: classes.differenceIconError
});
} else {
trendValueClass = classes.differenceValueInfo;
trendIcon = /*#__PURE__*/React.createElement(TrendingFlatIcon, {
className: classes.differenceIconInfo
});
}
var text = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Typography, {
className: trendValueClass,
variant: "body2"
}, trend.value || ''), /*#__PURE__*/React.createElement(Typography, {
className: classes.caption,
variant: "caption"
}, description || ''));
return /*#__PURE__*/React.createElement(React.Fragment, null, trendIcon, text);
};
var MetricCard = function MetricCard(props) {
var classes = useStyles();
var fetching = props.fetching,
errorMessage = props.errorMessage,
errorTooltip = props.errorTooltip,
value = props.value,
spinnerColor = props.spinnerColor,
spinnerSize = props.spinnerSize,
spinnerThickness = props.spinnerThickness,
title = props.title,
titleColor = props.titleColor,
titleFontFamily = props.titleFontFamily,
titleFontSize = props.titleFontSize,
valueColor = props.valueColor,
valueFontFamily = props.valueFontFamily,
valueFontSize = props.valueFontSize,
trend = props.trend,
icon = props.icon,
iconBgColor = props.iconBgColor,
iconColor = props.iconColor,
iconBorderRadius = props.iconBorderRadius,
iconHeight = props.iconHeight,
iconWidth = props.iconWidth,
cardBgColor = props.cardBgColor,
cardClick = props.cardClick,
cardClickFunction = props.cardClickFunction;
var customClasses = makeStyles(function (theme) {
return {
root: {
backgroundColor: cardBgColor || theme.palette.primary.white,
height: '100%',
width: '100%'
},
spinner: {
color: spinnerColor
},
title: {
fontWeight: 800,
color: titleColor,
fontFamily: titleFontFamily,
fontSize: titleFontSize
},
value: {
color: valueColor,
font: valueFontFamily,
fontSize: valueFontSize
},
icon: {
backgroundColor: iconBgColor || theme.palette.icon.primary,
height: iconHeight || 56,
width: iconWidth || 56,
borderRadius: iconBorderRadius || '50%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: iconColor || theme.palette.white
}
};
})();
return /*#__PURE__*/React.createElement(Card, {
className: clsx(customClasses.root)
}, /*#__PURE__*/React.createElement(ButtonBase, {
className: classes.cardAction,
onClick: cardClickFunction,
disabled: !cardClick
}, /*#__PURE__*/React.createElement(CardContent, null, /*#__PURE__*/React.createElement(Grid, {
container: true,
justify: "space-between"
}, /*#__PURE__*/React.createElement(Grid, {
item: true
}, /*#__PURE__*/React.createElement(Typography, {
className: customClasses.title,
gutterBottom: true,
variant: "body2"
}, title), /*#__PURE__*/React.createElement(Typography, {
variant: "h3",
className: customClasses.value
}, fetching ? '' : errorMessage ? '' : value)), /*#__PURE__*/React.createElement(Grid, {
item: true
}, /*#__PURE__*/React.createElement(Icon, {
className: customClasses.icon
}, icon || /*#__PURE__*/React.createElement(InsertChartIcon, null)))), /*#__PURE__*/React.createElement("div", {
className: classes.difference
}, fetching ? /*#__PURE__*/React.createElement(CircularProgress, {
className: customClasses.spinner,
size: spinnerSize,
thickness: spinnerThickness
}) : errorMessage ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Tooltip, {
title: errorTooltip || errorMessage
}, /*#__PURE__*/React.createElement(ErrorIcon, {
color: "error"
})), /*#__PURE__*/React.createElement(Typography, {
variant: "caption"
}, errorMessage)) : trend && renderMetricTrend(trend, classes)))));
};
MetricCard.propTypes = {
title: PropTypes.string,
fetching: PropTypes.bool,
errorMessage: PropTypes.string,
errorTooltip: PropTypes.string,
value: PropTypes.string,
spinnerColor: PropTypes.string,
spinnerSize: PropTypes.number,
spinnerThickness: PropTypes.number,
titleColor: PropTypes.string,
titleFontFamily: PropTypes.string,
titleFontSize: PropTypes.string,
valueColor: PropTypes.string,
valueFontFamily: PropTypes.string,
valueFontSize: PropTypes.string,
trend: PropTypes.object,
icon: PropTypes.object,
iconBgColor: PropTypes.string,
iconColor: PropTypes.string,
iconBorderRadius: PropTypes.string,
iconHeight: PropTypes.string,
iconWidth: PropTypes.string,
cardBgColor: PropTypes.string,
cardClick: PropTypes.bool,
cardClickFunction: PropTypes.func
};
var MetricCard$1 = function MetricCard$1(props) {
return /*#__PURE__*/React.createElement(ThemeProvider, {
theme: theme
}, /*#__PURE__*/React.createElement(MetricCard, props));
};
export default MetricCard$1;
export { MetricCard$1 as MetricCard };
//# sourceMappingURL=index.modern.js.map