UNPKG

@octopusdeploy/design-system-components

Version:
86 lines (85 loc) 6.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LineChart = LineChart; const jsx_runtime_1 = require("react/jsx-runtime"); /* eslint-disable @typescript-eslint/no-explicit-any */ const css_1 = require("@emotion/css"); const design_system_tokens_1 = require("@octopusdeploy/design-system-tokens"); const react_1 = require("react"); const recharts_1 = require("recharts"); const Theme_1 = require("../../Theme"); const CircularProgress_1 = require("../Progress/CircularProgress"); const chartColors_1 = require("./chartColors"); const truncateSeriesName = (str, len = 50) => { if (str.length >= len) return `${str.slice(0, len - 3)}...`; return str; }; function LineChart({ data, dataKey, xAxisDataKey, yAxisDataKey, xAxisLabel, yAxisLabel, xTickFormatter, yTickFormatter, xAxisDomain, yAxisDomain, xAxisType, yAxisType, margin, tooltip, showLegend, loading, yAxisTickArray, xAxisTickInterval, }) { const palette = (0, Theme_1.useDesignSystemTheme)(); const isLightMode = palette === design_system_tokens_1.lightTheme; const [hiddenSeries, setHiddenSeries] = (0, react_1.useState)([]); const [hoveredSeries, setHoveredSeries] = (0, react_1.useState)(null); const chartColors = (0, chartColors_1.useThemedChartColors)(); const { strokes } = chartColors; const dataWithColors = (0, chartColors_1.addColorToDataset)(data); const handleLegendClick = (seriesId) => { if (!seriesId) return; if (hiddenSeries.some((s) => s === seriesId)) setHiddenSeries((p) => p.filter((s) => s !== seriesId)); else setHiddenSeries((p) => [...p, seriesId]); }; const handleLegendMouseEnter = (seriesId) => { if (!seriesId) return; setHoveredSeries(seriesId); }; const handleLegendMouseLeave = () => setHoveredSeries(null); const DEFAULT_MARGIN = { top: 10, right: showLegend ? 10 : 40, left: 80, bottom: 10, }; if (loading) return ((0, jsx_runtime_1.jsx)("div", { className: loadingStyles, children: (0, jsx_runtime_1.jsx)(CircularProgress_1.CircularProgress, { size: "large" }) })); return ((0, jsx_runtime_1.jsx)(recharts_1.ResponsiveContainer, { width: "100%", height: "100%", children: (0, jsx_runtime_1.jsxs)(recharts_1.LineChart, { margin: margin ?? DEFAULT_MARGIN, className: toggleableLegendStyles, children: [(0, jsx_runtime_1.jsx)(recharts_1.CartesianGrid, { strokeDasharray: "6", stroke: chartColors.grid, vertical: false }), (0, jsx_runtime_1.jsx)(recharts_1.XAxis, { dataKey: xAxisDataKey, domain: xAxisDomain, type: xAxisType, stroke: chartColors.xAxis, tickFormatter: xTickFormatter, allowDuplicatedCategory: false, tickMargin: 16, tickLine: false, color: chartColors.xAxis, interval: xAxisTickInterval, children: xAxisLabel && (0, jsx_runtime_1.jsx)(recharts_1.Label, { value: xAxisLabel, position: "bottom", stroke: chartColors.label, fontSize: 20, fontWeight: 300, strokeWidth: 1, style: { textAnchor: "middle" } }) }), (0, jsx_runtime_1.jsx)(recharts_1.YAxis, { dataKey: yAxisDataKey, domain: yAxisDomain, type: yAxisType, stroke: chartColors.yAxis, tickFormatter: yTickFormatter, width: 20, axisLine: false, tickMargin: 16, tickLine: false, color: chartColors.yAxis, ticks: yAxisTickArray, children: yAxisLabel && (0, jsx_runtime_1.jsx)(recharts_1.Label, { angle: -90, value: yAxisLabel, position: "left", stroke: chartColors.label, fontSize: 20, fontWeight: 300, strokeWidth: 1, style: { textAnchor: "middle" }, dx: -60 }) }), showLegend && ((0, jsx_runtime_1.jsx)(recharts_1.Legend // The types for Payload from recharts don't seem to match what is received at runtime, so typing these as any instead and type asserting // eslint-disable-next-line @typescript-eslint/consistent-type-assertions , { // The types for Payload from recharts don't seem to match what is received at runtime, so typing these as any instead and type asserting // eslint-disable-next-line @typescript-eslint/consistent-type-assertions onClick: (e) => handleLegendClick(e?.payload?.id), // eslint-disable-next-line @typescript-eslint/consistent-type-assertions onMouseOver: (e) => handleLegendMouseEnter(e?.payload?.id), onMouseOut: handleLegendMouseLeave, iconType: "plainline", layout: "vertical", verticalAlign: "top", align: "right", formatter: (val) => truncateSeriesName(val), wrapperStyle: { paddingLeft: 36, maxWidth: 250, height: "calc(100% - 36px)", overflow: "auto", fontWeight: 500, } })), tooltip && (0, jsx_runtime_1.jsx)(recharts_1.Tooltip, { content: tooltip, wrapperStyle: { zIndex: 1 }, animationDuration: 200 }), dataWithColors.map((d) => { const hoveredIsHidden = hiddenSeries.some((h) => h === hoveredSeries); const stroke = strokes[d.color]; const white = "#FFFFFF"; const activeDot = { stroke: isLightMode ? stroke : white, fill: isLightMode ? white : stroke, strokeWidth: 2, r: 6 }; return ((0, jsx_runtime_1.jsx)(recharts_1.Line, { name: d.name, id: d.id, type: "monotone", dataKey: dataKey, data: d.data, stroke: stroke, hide: hiddenSeries.some((s) => s === d.id), strokeOpacity: hoveredSeries === d.id || !hoveredSeries || hoveredIsHidden ? 1 : 0.1, strokeWidth: 3, dot: false, activeDot: activeDot, animationDuration: 500 }, `data-${d.name}`)); })] }) })); } const toggleableLegendStyles = (0, css_1.css)({ li: { cursor: "pointer", marginRight: "0px !important", "&:not(:last-child)": { paddingBottom: design_system_tokens_1.space[8], }, }, }); const loadingStyles = (0, css_1.css)({ display: "flex", height: "100%", width: "100%", alignItems: "center", justifyContent: "center", });