@mx-cartographer/experiences 9.4.37 → 9.4.38
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.
- package/CHANGELOG.md +4 -0
- package/dist/common/components/charts/LineChart.d.ts +2 -0
- package/dist/common/components/charts/LineChart.es.js +120 -109
- package/dist/common/components/charts/LineChart.es.js.map +1 -1
- package/dist/trends/components/TrendsChartTotals.es.js +45 -37
- package/dist/trends/components/TrendsChartTotals.es.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## [9.4.38] - 09-22-2026
|
|
2
|
+
|
|
3
|
+
- **FIXED** - `LineChart` x-axis now shows every tick label instead of dropping overlapping ones, so month labels no longer disappear on small views. On the Trends 1 Year (12-month) view on small screens, labels render as single letters so all twelve fit; the full month is preserved as the accessible name so screen readers and tooltips are unchanged (MEW-4096)
|
|
4
|
+
|
|
1
5
|
## [9.4.37] - 09-22-2026
|
|
2
6
|
|
|
3
7
|
- **FIXED** - Trends Categories "View more"/"View less" toggle now scrolls back into the viewport after the list expands, so keyboard users keep the focused control in view instead of losing track of focus below the fold (MEW-3587)
|
|
@@ -1,50 +1,59 @@
|
|
|
1
|
-
import { formatCurrency as
|
|
2
|
-
import { stripChartSlotProps as
|
|
3
|
-
import { getMarkerShape as
|
|
4
|
-
import
|
|
5
|
-
import { CustomLine as
|
|
6
|
-
import { CustomMark as
|
|
7
|
-
import { CustomTooltip as
|
|
1
|
+
import { formatCurrency as R, generateEqualIntervals as I } from "../../../core/utils/NumberFormatting.es.js";
|
|
2
|
+
import { stripChartSlotProps as pt } from "./chartSlotProps.es.js";
|
|
3
|
+
import { getMarkerShape as ct } from "./linechart/utils/markerShapes.es.js";
|
|
4
|
+
import ht from "./linechart/CustomLegend.es.js";
|
|
5
|
+
import { CustomLine as yt } from "./linechart/CustomLine.es.js";
|
|
6
|
+
import { CustomMark as ut } from "./linechart/CustomMark.es.js";
|
|
7
|
+
import { CustomTooltip as dt } from "./linechart/CustomTooltip.es.js";
|
|
8
8
|
import "react";
|
|
9
9
|
import { jsx as e, jsxs as d } from "react/jsx-runtime";
|
|
10
|
-
import { useTheme as
|
|
11
|
-
import
|
|
12
|
-
import { BarPlot as
|
|
13
|
-
import { ChartContainer as
|
|
14
|
-
import { ChartsAxisHighlight as
|
|
10
|
+
import { useTheme as xt } from "@mui/material/styles";
|
|
11
|
+
import gt from "@mui/material/Box";
|
|
12
|
+
import { BarPlot as kt } from "@mui/x-charts/BarChart";
|
|
13
|
+
import { ChartContainer as bt } from "@mui/x-charts/ChartContainer";
|
|
14
|
+
import { ChartsAxisHighlight as Lt } from "@mui/x-charts/ChartsAxisHighlight";
|
|
15
|
+
import { ChartsText as S } from "@mui/x-charts/ChartsText";
|
|
15
16
|
import { ChartsReferenceLine as Mt } from "@mui/x-charts/ChartsReferenceLine";
|
|
16
|
-
import { ChartsTooltipContainer as
|
|
17
|
-
import { ChartsXAxis as
|
|
18
|
-
import { ChartsYAxis as
|
|
19
|
-
import { AreaPlot as
|
|
20
|
-
var
|
|
21
|
-
const a =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
import { ChartsTooltipContainer as Tt } from "@mui/x-charts/ChartsTooltip";
|
|
18
|
+
import { ChartsXAxis as Ct } from "@mui/x-charts/ChartsXAxis";
|
|
19
|
+
import { ChartsYAxis as vt } from "@mui/x-charts/ChartsYAxis";
|
|
20
|
+
import { AreaPlot as At, LinePlot as Pt, MarkPlot as Rt } from "@mui/x-charts/LineChart";
|
|
21
|
+
var It = (r) => {
|
|
22
|
+
const a = typeof r.text == "string" ? r.text : "", c = Array.from(a.trim())[0] ?? "";
|
|
23
|
+
return c ? /* @__PURE__ */ e(S, {
|
|
24
|
+
...r,
|
|
25
|
+
"aria-label": a,
|
|
26
|
+
role: "img",
|
|
27
|
+
text: c
|
|
28
|
+
}) : /* @__PURE__ */ e(S, { ...r });
|
|
29
|
+
}, St = { axisTickLabel: It }, Zt = ({ areaColor: r, axisColor: a, baseline: c = "max", chartFor: x, chartXaxisSx: w, chartYaxisSx: O, colors: b, curveType: _ = "linear", customLegendVariant: D, customLegendSx: G, customLegendBoxSx: N, customTooltipLabels: W, datasets: h, height: X, isCurrency: $, isGraphClippingXAxis: j = !1, labels: L, labelBackgroundColor: M, labelFontColor: E, labelFontSize: q, margin: z, markHandlers: H, markStyles: Y, minRange: B, maxRange: J, narrowXAxisLabels: T = !1, showAllXAxisLabels: K = !1, onItemClick: g, peerAverage: C, showArea: v = !1, showAverage: A = !1, showAxisHighlight: Q = !1, showBars: k = !1, showLegend: U = !1, showMark: V = !0, showMarkLabel: Z = !1, showTooltip: F = !1, showXAxis: tt = !1, showXAxisTicks: et = !1, showYAxis: rt = !1, showYAxisTicks: at = !1, title: it, useCustomMark: ot = !1, valueFormatterString: s, width: nt, xAxisScaleType: st }) => {
|
|
30
|
+
const i = xt(), lt = h.flat().map((t) => t.x), o = h.flat().map((t) => t.y), P = C || (o.length ? Math.round(o.reduce((t, l) => l + t, 0) / o.length) : 0), m = o.length ? Math.floor(Math.min(...o) / 100) * 100 : 0, f = o.length ? Math.ceil(Math.max(...o) / 100) * 100 : 0, y = h.map((t, l) => ({
|
|
31
|
+
type: k ? "bar" : "line",
|
|
32
|
+
curve: _,
|
|
33
|
+
color: k ? i.palette.chart?.chart6 : b[l] ?? i.palette.primary.main,
|
|
34
|
+
data: t.map((n) => n.y),
|
|
35
|
+
area: v,
|
|
36
|
+
baseline: c,
|
|
28
37
|
showMark: !0,
|
|
29
|
-
shape:
|
|
30
|
-
valueFormatter: (
|
|
31
|
-
})),
|
|
38
|
+
shape: ct(l),
|
|
39
|
+
valueFormatter: (n) => s ? R(n || 0, s) : String(n)
|
|
40
|
+
})), mt = {
|
|
32
41
|
top: 60,
|
|
33
42
|
right: 35,
|
|
34
43
|
bottom: 25,
|
|
35
44
|
left: -10,
|
|
36
|
-
...
|
|
45
|
+
...z
|
|
37
46
|
};
|
|
38
|
-
let p =
|
|
39
|
-
if (
|
|
40
|
-
const t =
|
|
41
|
-
p =
|
|
47
|
+
let p = B ?? m, u = J ?? f;
|
|
48
|
+
if (x === "networthChart") {
|
|
49
|
+
const t = f - m, l = t < f * 0.05 ? 0.25 : 0.2, n = Math.max(t * l, f * 0.015);
|
|
50
|
+
p = m - n < 0 ? m : m - n, u = f + n;
|
|
42
51
|
}
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
if (
|
|
52
|
+
const ft = () => {
|
|
53
|
+
if (x === "creditOverTime") return I(p, 850, 5);
|
|
54
|
+
if (x === "networthChart") return I(p, u, 5);
|
|
46
55
|
};
|
|
47
|
-
return /* @__PURE__ */ d(
|
|
56
|
+
return /* @__PURE__ */ d(gt, {
|
|
48
57
|
sx: {
|
|
49
58
|
position: "relative",
|
|
50
59
|
touchAction: "pan-y",
|
|
@@ -54,49 +63,50 @@ var Bt = ({ areaColor: f, axisColor: n, baseline: R = "max", chartFor: u, chartX
|
|
|
54
63
|
},
|
|
55
64
|
"& .recharts-wrapper": { touchAction: "pan-y" }
|
|
56
65
|
},
|
|
57
|
-
children: [/* @__PURE__ */ d(
|
|
58
|
-
height:
|
|
59
|
-
margin:
|
|
60
|
-
series:
|
|
66
|
+
children: [/* @__PURE__ */ d(bt, {
|
|
67
|
+
height: X,
|
|
68
|
+
margin: mt,
|
|
69
|
+
series: y,
|
|
61
70
|
sx: {
|
|
62
71
|
"& .MuiBarLabel-root": {
|
|
63
72
|
fontSize: 10,
|
|
64
73
|
fontWeight: 600
|
|
65
74
|
},
|
|
66
75
|
"& .MuiAreaElement-root": { opacity: 0.15 },
|
|
67
|
-
"& .MuiChartsAxis-tickLabel > tspan": { fontFamily:
|
|
68
|
-
"& .MuiLineChart-markLabel": { fontFamily:
|
|
76
|
+
"& .MuiChartsAxis-tickLabel > tspan": { fontFamily: i.typography.body2.fontFamily },
|
|
77
|
+
"& .MuiLineChart-markLabel": { fontFamily: i.typography.body2.fontFamily }
|
|
69
78
|
},
|
|
70
|
-
width:
|
|
79
|
+
width: nt,
|
|
71
80
|
xAxis: [{
|
|
72
|
-
data:
|
|
73
|
-
scaleType:
|
|
81
|
+
data: lt,
|
|
82
|
+
scaleType: st || (k ? "band" : "point"),
|
|
83
|
+
...(K || T) && { tickLabelInterval: () => !0 }
|
|
74
84
|
}],
|
|
75
85
|
yAxis: [{
|
|
76
|
-
tickInterval:
|
|
77
|
-
min:
|
|
78
|
-
max:
|
|
79
|
-
colorMap:
|
|
86
|
+
tickInterval: ft(),
|
|
87
|
+
min: j ? -22 : p,
|
|
88
|
+
max: u || 100,
|
|
89
|
+
colorMap: v && y.length < 2 ? {
|
|
80
90
|
type: "continuous",
|
|
81
91
|
min: p,
|
|
82
|
-
max:
|
|
83
|
-
color: [
|
|
92
|
+
max: u,
|
|
93
|
+
color: [i.palette.background.paper, b[0] ?? i.palette.primary.main]
|
|
84
94
|
} : void 0,
|
|
85
|
-
valueFormatter: (t) =>
|
|
95
|
+
valueFormatter: (t) => s ? R(t, s) : String(t),
|
|
86
96
|
width: 62
|
|
87
97
|
}],
|
|
88
98
|
children: [
|
|
89
|
-
|
|
99
|
+
A && /* @__PURE__ */ e(Mt, {
|
|
90
100
|
lineStyle: {
|
|
91
|
-
stroke:
|
|
101
|
+
stroke: M ? i.palette.neutral.main : i.palette.neutral.dark,
|
|
92
102
|
strokeDasharray: "10, 8",
|
|
93
103
|
strokeWidth: 2
|
|
94
104
|
},
|
|
95
|
-
y:
|
|
105
|
+
y: P
|
|
96
106
|
}),
|
|
97
|
-
/* @__PURE__ */ e(
|
|
98
|
-
onItemClick:
|
|
99
|
-
...
|
|
107
|
+
/* @__PURE__ */ e(At, {
|
|
108
|
+
onItemClick: g,
|
|
109
|
+
...r && { slots: { area: (t) => /* @__PURE__ */ d("g", { children: [/* @__PURE__ */ e("defs", { children: /* @__PURE__ */ d("linearGradient", {
|
|
100
110
|
id: "customGradient",
|
|
101
111
|
x1: "0",
|
|
102
112
|
x2: "0",
|
|
@@ -104,92 +114,93 @@ var Bt = ({ areaColor: f, axisColor: n, baseline: R = "max", chartFor: u, chartX
|
|
|
104
114
|
y2: "1",
|
|
105
115
|
children: [/* @__PURE__ */ e("stop", {
|
|
106
116
|
offset: "0%",
|
|
107
|
-
stopColor:
|
|
117
|
+
stopColor: r
|
|
108
118
|
}), /* @__PURE__ */ e("stop", {
|
|
109
119
|
offset: "100%",
|
|
110
|
-
stopColor:
|
|
120
|
+
stopColor: r,
|
|
111
121
|
stopOpacity: 0.02
|
|
112
122
|
})]
|
|
113
123
|
}) }), /* @__PURE__ */ e("path", {
|
|
114
|
-
...
|
|
124
|
+
...pt(t),
|
|
115
125
|
fill: "url(#customGradient)"
|
|
116
126
|
})] }) } }
|
|
117
127
|
}),
|
|
118
|
-
/* @__PURE__ */ e(
|
|
119
|
-
onItemClick:
|
|
120
|
-
slots: { line: (t) => /* @__PURE__ */ e(
|
|
128
|
+
/* @__PURE__ */ e(Pt, {
|
|
129
|
+
onItemClick: g,
|
|
130
|
+
slots: { line: (t) => /* @__PURE__ */ e(yt, {
|
|
121
131
|
...t,
|
|
122
|
-
lineColor:
|
|
132
|
+
lineColor: r ?? t.ownerState.color ?? i.palette.primary.main
|
|
123
133
|
}) }
|
|
124
134
|
}),
|
|
125
|
-
/* @__PURE__ */ e(
|
|
126
|
-
onItemClick:
|
|
127
|
-
slots:
|
|
128
|
-
handlers:
|
|
129
|
-
labelBackgroundColor:
|
|
130
|
-
labelFontColor:
|
|
131
|
-
labelFontSize:
|
|
132
|
-
showLabel:
|
|
133
|
-
showMark:
|
|
134
|
-
style:
|
|
135
|
-
valueFormatterString:
|
|
136
|
-
yData:
|
|
135
|
+
/* @__PURE__ */ e(Rt, {
|
|
136
|
+
onItemClick: g,
|
|
137
|
+
slots: ot ? { mark: (t) => /* @__PURE__ */ e(ut, {
|
|
138
|
+
handlers: H,
|
|
139
|
+
labelBackgroundColor: M,
|
|
140
|
+
labelFontColor: E,
|
|
141
|
+
labelFontSize: q,
|
|
142
|
+
showLabel: Z,
|
|
143
|
+
showMark: V || t.dataIndex === h[0].length - 1,
|
|
144
|
+
style: Y?.(t.dataIndex) ?? {},
|
|
145
|
+
valueFormatterString: s,
|
|
146
|
+
yData: o,
|
|
137
147
|
...t
|
|
138
148
|
}) } : void 0
|
|
139
149
|
}),
|
|
140
|
-
/* @__PURE__ */ e(
|
|
150
|
+
/* @__PURE__ */ e(kt, {
|
|
141
151
|
barLabel: (t) => Number(t.value) > 0 ? `$${t.value}` : null,
|
|
142
152
|
borderRadius: 10
|
|
143
153
|
}),
|
|
144
|
-
/* @__PURE__ */ e(
|
|
145
|
-
disableLine: !
|
|
146
|
-
disableTicks: !
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
154
|
+
/* @__PURE__ */ e(Ct, {
|
|
155
|
+
disableLine: !tt,
|
|
156
|
+
disableTicks: !et,
|
|
157
|
+
slots: T ? St : void 0,
|
|
158
|
+
slotProps: a ? {
|
|
159
|
+
axisLine: { style: { stroke: a } },
|
|
160
|
+
axisTick: { style: { stroke: a } }
|
|
150
161
|
} : {},
|
|
151
162
|
sx: { ...w }
|
|
152
163
|
}),
|
|
153
|
-
/* @__PURE__ */ e(
|
|
154
|
-
disableLine: !
|
|
155
|
-
disableTicks: !
|
|
156
|
-
slotProps:
|
|
157
|
-
axisLine: { style: { stroke:
|
|
158
|
-
axisTick: { style: { stroke:
|
|
164
|
+
/* @__PURE__ */ e(vt, {
|
|
165
|
+
disableLine: !rt,
|
|
166
|
+
disableTicks: !at,
|
|
167
|
+
slotProps: a ? {
|
|
168
|
+
axisLine: { style: { stroke: a } },
|
|
169
|
+
axisTick: { style: { stroke: a } }
|
|
159
170
|
} : {},
|
|
160
|
-
sx: { ...
|
|
171
|
+
sx: { ...O }
|
|
161
172
|
}),
|
|
162
|
-
|
|
163
|
-
|
|
173
|
+
Q && /* @__PURE__ */ e(Lt, { x: "line" }),
|
|
174
|
+
F && /* @__PURE__ */ e(Tt, {
|
|
164
175
|
trigger: "axis",
|
|
165
|
-
children: /* @__PURE__ */ e(
|
|
166
|
-
customLabels:
|
|
167
|
-
isCurrency:
|
|
168
|
-
labels:
|
|
169
|
-
series:
|
|
170
|
-
valueFormatterString:
|
|
176
|
+
children: /* @__PURE__ */ e(dt, {
|
|
177
|
+
customLabels: W,
|
|
178
|
+
isCurrency: $,
|
|
179
|
+
labels: L,
|
|
180
|
+
series: y,
|
|
181
|
+
valueFormatterString: s
|
|
171
182
|
})
|
|
172
183
|
})
|
|
173
184
|
]
|
|
174
|
-
}),
|
|
175
|
-
average:
|
|
176
|
-
customLegendBoxSx:
|
|
177
|
-
customLegendVariant:
|
|
178
|
-
labels:
|
|
179
|
-
series:
|
|
185
|
+
}), U && /* @__PURE__ */ e(ht, {
|
|
186
|
+
average: A ? P : void 0,
|
|
187
|
+
customLegendBoxSx: N,
|
|
188
|
+
customLegendVariant: D,
|
|
189
|
+
labels: L,
|
|
190
|
+
series: y,
|
|
180
191
|
style: {
|
|
181
192
|
position: "absolute",
|
|
182
193
|
top: 16,
|
|
183
194
|
left: 16,
|
|
184
|
-
|
|
195
|
+
...G
|
|
185
196
|
},
|
|
186
|
-
title:
|
|
187
|
-
valueFormatterString:
|
|
197
|
+
title: it,
|
|
198
|
+
valueFormatterString: s
|
|
188
199
|
})]
|
|
189
200
|
});
|
|
190
201
|
};
|
|
191
202
|
export {
|
|
192
|
-
|
|
203
|
+
Zt as LineChart
|
|
193
204
|
};
|
|
194
205
|
|
|
195
206
|
//# sourceMappingURL=LineChart.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineChart.es.js","names":[],"sources":["../../../../src/common/components/charts/LineChart.tsx"],"sourcesContent":["import React from 'react'\n\nimport Box from '@mui/material/Box'\nimport type { SxProps } from '@mui/material/styles'\nimport { useTheme } from '@mui/material/styles'\n\nimport type { AllSeriesType } from '@mui/x-charts'\nimport { BarPlot } from '@mui/x-charts/BarChart'\nimport { ChartContainer as ResponsiveChartContainer } from '@mui/x-charts/ChartContainer'\nimport { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight'\nimport { ChartsReferenceLine } from '@mui/x-charts/ChartsReferenceLine'\nimport { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'\nimport { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'\nimport { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'\nimport { AreaPlot, LinePlot, MarkPlot } from '@mui/x-charts/LineChart'\n\nimport { stripChartSlotProps } from './chartSlotProps'\nimport CustomLegend from './linechart/CustomLegend'\nimport { getMarkerShape } from './linechart/utils/markerShapes'\nimport { CustomLine } from './linechart/CustomLine'\nimport { CustomMark, MarkHandlers } from './linechart/CustomMark'\nimport { CustomTooltip } from './linechart/CustomTooltip'\nimport { formatCurrency } from '../../../core/utils/NumberFormatting'\nimport { generateEqualIntervals } from '../../../core/utils/NumberFormatting'\n\nexport type LineChartDataset = { x: string; y: number }[]\nexport type LineChartLabel = string | { label: string; amount: number }\nexport type TooltipLabel = LineChartLabel & { header?: string }\n\ntype LineChartCurve =\n | 'catmullRom'\n | 'linear'\n | 'monotoneX'\n | 'monotoneY'\n | 'natural'\n | 'step'\n | 'stepBefore'\n | 'stepAfter'\n | 'bump'\n | 'bumpX'\n | 'bumpY'\n\ninterface LineChartProps {\n areaColor?: string\n axisColor?: string\n baseline?: string\n chartFor?: string\n chartXaxisSx?: SxProps\n chartYaxisSx?: SxProps\n // Because theme chart colors are typed string|undefined\n colors: (string | undefined)[]\n curveType?: LineChartCurve\n customLegendVariant?: string\n customLegendSx?: SxProps\n customLegendBoxSx?: SxProps\n customTooltipLabels?: TooltipLabel[][]\n datasets: LineChartDataset[]\n height?: number\n isCurrency?: boolean\n isGraphClippingXAxis?: boolean\n labels: LineChartLabel[]\n labelBackgroundColor?: string\n labelFontColor?: string\n labelFontSize?: number\n margin?: { top?: number; right?: number; bottom?: number; left?: number }\n markHandlers?: MarkHandlers\n markStyles?: (markIndex: number) => React.CSSProperties & {\n markLabelStyles?: React.CSSProperties\n }\n minRange?: number\n maxRange?: number\n onItemClick?: () => void\n peerAverage?: number\n showArea?: boolean\n showAverage?: boolean\n showAxisHighlight?: boolean\n showBars?: boolean\n showLegend?: boolean\n showMark?: boolean\n showMarkLabel?: boolean\n showTooltip?: boolean\n showXAxis?: boolean\n showXAxisTicks?: boolean\n showYAxis?: boolean\n showYAxisTicks?: boolean\n tickIntervals?: any[] | 'auto' | ((value: any, index: number) => boolean) | undefined\n title?: string\n useCustomMark?: boolean\n valueFormatterString?: string\n width?: number\n xAxisScaleType?: 'band' | 'point'\n}\n\n// TODO: Remove negative values and use a proper layout to support X-Charts v8\n\nexport const LineChart: React.FC<LineChartProps> = ({\n areaColor,\n axisColor,\n baseline = 'max',\n chartFor,\n chartXaxisSx,\n chartYaxisSx,\n colors,\n curveType = 'linear',\n customLegendVariant,\n customLegendSx,\n customLegendBoxSx,\n customTooltipLabels,\n datasets,\n height,\n isCurrency,\n isGraphClippingXAxis = false,\n labels,\n labelBackgroundColor,\n labelFontColor,\n labelFontSize,\n margin,\n markHandlers,\n markStyles,\n minRange,\n maxRange,\n onItemClick,\n peerAverage,\n showArea = false,\n showAverage = false,\n showAxisHighlight = false,\n showBars = false,\n showLegend = false,\n showMark = true,\n showMarkLabel = false,\n showTooltip = false,\n showXAxis = false,\n showXAxisTicks = false,\n showYAxis = false,\n showYAxisTicks = false,\n title,\n useCustomMark = false,\n valueFormatterString,\n width,\n xAxisScaleType,\n}) => {\n const theme = useTheme()\n\n // Data for the X axis\n const xData = datasets.flat().map((item) => item.x)\n const yData = datasets.flat().map((item) => item.y)\n\n // Guard the empty-data case: with no points, reduce()/Math.min()/Math.max()\n // produce NaN/±Infinity which flow into the y-axis and make x-charts warn\n // \"the value NaN does not exist in the data of y axis\". Default to 0 so an\n // empty/loading chart renders a valid (flat) axis instead.\n const average = peerAverage\n ? peerAverage\n : yData.length\n ? Math.round(yData.reduce((value, total) => total + value, 0) / yData.length)\n : 0\n\n // Used for the min and max Y axis values\n const yMin = yData.length ? Math.floor(Math.min(...yData) / 100) * 100 : 0\n const yMax = yData.length ? Math.ceil(Math.max(...yData) / 100) * 100 : 0\n\n const series = datasets.map((data, index) => {\n return {\n type: showBars ? 'bar' : 'line',\n curve: curveType,\n color: showBars ? theme.palette.chart?.chart6 : (colors[index] ?? theme.palette.primary.main),\n data: data.map((item) => item.y),\n area: showArea,\n baseline: baseline,\n showMark: true,\n shape: getMarkerShape(index),\n valueFormatter: (value: number) =>\n valueFormatterString ? formatCurrency(value || 0, valueFormatterString) : String(value),\n }\n })\n\n const defaultMargin = {\n top: 60,\n right: 35,\n bottom: 25,\n left: -10,\n }\n\n // Merge default margin with any provided custom margin\n const chartMargin = {\n ...defaultMargin,\n ...margin,\n }\n\n let rangeMin = minRange ?? yMin\n let rangeMax = maxRange ?? yMax\n if (chartFor === 'networthChart') {\n const valueRange = yMax - yMin\n\n const paddingRatio = valueRange < yMax * 0.05 ? 0.25 : 0.2\n const padding = Math.max(valueRange * paddingRatio, yMax * 0.015)\n rangeMin = yMin - padding < 0 ? yMin : yMin - padding\n rangeMax = yMax + padding\n }\n\n const getTickInterval = () => {\n if (chartFor === 'creditOverTime') {\n return generateEqualIntervals(rangeMin, 850, 5)\n } else if (chartFor === 'networthChart') {\n return generateEqualIntervals(rangeMin, rangeMax, 5)\n }\n return undefined\n }\n return (\n <Box\n sx={{\n position: 'relative',\n touchAction: 'pan-y', // Allow vertical scrolling\n '& svg': {\n touchAction: 'pan-y', // Allow vertical scrolling on SVG\n userSelect: 'none', // Prevent text selection\n },\n '& .recharts-wrapper': {\n touchAction: 'pan-y', // For Recharts library specifically\n },\n }}\n >\n <ResponsiveChartContainer\n height={height}\n margin={chartMargin}\n series={series as AllSeriesType[]}\n sx={{\n '& .MuiBarLabel-root': {\n fontSize: 10,\n fontWeight: 600,\n },\n '& .MuiAreaElement-root': {\n opacity: 0.15,\n },\n '& .MuiChartsAxis-tickLabel > tspan': {\n fontFamily: theme.typography.body2.fontFamily,\n },\n '& .MuiLineChart-markLabel': {\n fontFamily: theme.typography.body2.fontFamily,\n },\n }}\n width={width}\n xAxis={[{ data: xData, scaleType: xAxisScaleType || (showBars ? 'band' : 'point') }]}\n yAxis={[\n {\n tickInterval: getTickInterval(),\n min: isGraphClippingXAxis ? -22 : rangeMin,\n max: rangeMax || 100,\n colorMap:\n showArea && series.length < 2\n ? {\n type: 'continuous',\n min: rangeMin,\n max: rangeMax,\n color: [\n theme.palette.background.paper,\n colors[0] ?? theme.palette.primary.main,\n ],\n }\n : undefined,\n valueFormatter: (value: number) =>\n valueFormatterString ? formatCurrency(value, valueFormatterString) : String(value),\n width: 62,\n },\n ]}\n >\n {/** Provides the average line - positioned first to be behind other elements **/}\n {showAverage && (\n <ChartsReferenceLine\n lineStyle={{\n stroke: labelBackgroundColor\n ? theme.palette.neutral.main\n : theme.palette.neutral.dark,\n strokeDasharray: '10, 8',\n strokeWidth: 2,\n }}\n y={average}\n />\n )}\n\n {/** Area plot provides gradiant below the line **/}\n {/* Note: Must be above the LinePlot for some style rules to work */}\n <AreaPlot\n onItemClick={onItemClick}\n {...(areaColor && {\n slots: {\n area: (props) => {\n return (\n <g>\n <defs>\n <linearGradient id=\"customGradient\" x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={areaColor} />\n <stop offset=\"100%\" stopColor={areaColor} stopOpacity={0.02} />\n </linearGradient>\n </defs>\n <path {...stripChartSlotProps(props)} fill={`url(#customGradient)`} />\n </g>\n )\n },\n },\n })}\n />\n\n {/** Line plot provides the data line **/}\n <LinePlot\n onItemClick={onItemClick}\n slots={{\n line: (props) => (\n <CustomLine\n {...props}\n lineColor={areaColor ?? props.ownerState.color ?? theme.palette.primary.main}\n />\n ),\n }}\n />\n\n {/** Mark plot provides the circles **/}\n <MarkPlot\n onItemClick={onItemClick}\n slots={\n useCustomMark\n ? {\n mark: (props) => {\n return (\n <CustomMark\n handlers={markHandlers}\n labelBackgroundColor={labelBackgroundColor}\n labelFontColor={labelFontColor}\n labelFontSize={labelFontSize}\n showLabel={showMarkLabel}\n showMark={showMark || props.dataIndex === datasets[0].length - 1}\n style={markStyles?.(props.dataIndex) ?? {}}\n valueFormatterString={valueFormatterString}\n yData={yData}\n {...props}\n />\n )\n },\n }\n : undefined\n }\n />\n\n <BarPlot\n barLabel={(item) => (Number(item.value) > 0 ? `$${item.value}` : null)}\n borderRadius={10}\n />\n\n {/** Provides the X axis line and values **/}\n <ChartsXAxis\n disableLine={!showXAxis}\n disableTicks={!showXAxisTicks}\n slotProps={\n axisColor\n ? {\n axisLine: {\n style: {\n stroke: axisColor,\n },\n },\n axisTick: {\n style: {\n stroke: axisColor,\n },\n },\n }\n : {}\n }\n sx={{ ...chartXaxisSx }}\n />\n\n {/** Provides the Y axis values **/}\n <ChartsYAxis\n disableLine={!showYAxis}\n disableTicks={!showYAxisTicks}\n slotProps={\n axisColor\n ? {\n axisLine: {\n style: {\n stroke: axisColor,\n },\n },\n axisTick: {\n style: {\n stroke: axisColor,\n },\n },\n }\n : {}\n }\n sx={{ ...chartYaxisSx }}\n />\n\n {/* Add vertical crosshair on hover */}\n {showAxisHighlight && <ChartsAxisHighlight x=\"line\" />}\n\n {showTooltip && (\n <ChartsTooltipContainer trigger=\"axis\">\n <CustomTooltip\n customLabels={customTooltipLabels}\n isCurrency={isCurrency}\n labels={labels}\n series={series}\n valueFormatterString={valueFormatterString}\n />\n </ChartsTooltipContainer>\n )}\n </ResponsiveChartContainer>\n\n {showLegend && (\n <CustomLegend\n average={showAverage ? average : undefined}\n customLegendBoxSx={customLegendBoxSx}\n customLegendVariant={customLegendVariant}\n labels={labels}\n series={series}\n style={{\n position: 'absolute',\n top: 16,\n left: 16,\n ...customLegendSx,\n }}\n title={title}\n valueFormatterString={valueFormatterString}\n />\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LineChart.es.js","names":[],"sources":["../../../../src/common/components/charts/LineChart.tsx"],"sourcesContent":["import React from 'react'\n\nimport Box from '@mui/material/Box'\nimport type { SxProps } from '@mui/material/styles'\nimport { useTheme } from '@mui/material/styles'\n\nimport type { AllSeriesType } from '@mui/x-charts'\nimport { BarPlot } from '@mui/x-charts/BarChart'\nimport { ChartContainer as ResponsiveChartContainer } from '@mui/x-charts/ChartContainer'\nimport { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight'\nimport { ChartsText, type ChartsTextProps } from '@mui/x-charts/ChartsText'\nimport { ChartsReferenceLine } from '@mui/x-charts/ChartsReferenceLine'\nimport { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'\nimport { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'\nimport { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'\nimport { AreaPlot, LinePlot, MarkPlot } from '@mui/x-charts/LineChart'\n\nimport { stripChartSlotProps } from './chartSlotProps'\nimport CustomLegend from './linechart/CustomLegend'\nimport { getMarkerShape } from './linechart/utils/markerShapes'\nimport { CustomLine } from './linechart/CustomLine'\nimport { CustomMark, MarkHandlers } from './linechart/CustomMark'\nimport { CustomTooltip } from './linechart/CustomTooltip'\nimport { formatCurrency } from '../../../core/utils/NumberFormatting'\nimport { generateEqualIntervals } from '../../../core/utils/NumberFormatting'\n\nexport type LineChartDataset = { x: string; y: number }[]\nexport type LineChartLabel = string | { label: string; amount: number }\nexport type TooltipLabel = LineChartLabel & { header?: string }\n\n// X-axis tick that shows only the first letter of the label (e.g. \"J\" for\n// \"Jan\") so all labels fit in small/narrow views. role=\"img\" + aria-label give\n// the tick a reliable accessible name (aria-label alone on a bare SVG <text> is\n// inconsistently announced), so screen readers still get the full label.\nconst NarrowXAxisTickLabel = (props: ChartsTextProps) => {\n const fullLabel = typeof props.text === 'string' ? props.text : ''\n // Array.from keeps surrogate pairs / combining marks intact (non-Latin locales).\n const singleLetter = Array.from(fullLabel.trim())[0] ?? ''\n if (!singleLetter) return <ChartsText {...props} />\n return <ChartsText {...props} aria-label={fullLabel} role=\"img\" text={singleLetter} />\n}\n\nconst NARROW_X_AXIS_SLOTS = { axisTickLabel: NarrowXAxisTickLabel }\n\ntype LineChartCurve =\n | 'catmullRom'\n | 'linear'\n | 'monotoneX'\n | 'monotoneY'\n | 'natural'\n | 'step'\n | 'stepBefore'\n | 'stepAfter'\n | 'bump'\n | 'bumpX'\n | 'bumpY'\n\ninterface LineChartProps {\n areaColor?: string\n axisColor?: string\n baseline?: string\n chartFor?: string\n chartXaxisSx?: SxProps\n chartYaxisSx?: SxProps\n // Because theme chart colors are typed string|undefined\n colors: (string | undefined)[]\n curveType?: LineChartCurve\n customLegendVariant?: string\n customLegendSx?: SxProps\n customLegendBoxSx?: SxProps\n customTooltipLabels?: TooltipLabel[][]\n datasets: LineChartDataset[]\n height?: number\n isCurrency?: boolean\n isGraphClippingXAxis?: boolean\n labels: LineChartLabel[]\n labelBackgroundColor?: string\n labelFontColor?: string\n labelFontSize?: number\n margin?: { top?: number; right?: number; bottom?: number; left?: number }\n markHandlers?: MarkHandlers\n markStyles?: (markIndex: number) => React.CSSProperties & {\n markLabelStyles?: React.CSSProperties\n }\n minRange?: number\n maxRange?: number\n // When true, x-axis labels render as a single letter (with the full label kept\n // as the accessible name), so months don't overlap and get dropped in\n // small/narrow views. Implies showAllXAxisLabels.\n narrowXAxisLabels?: boolean\n onItemClick?: () => void\n // When true, every x-axis tick label is shown instead of letting x-charts drop\n // overlapping ones. Opt-in so it doesn't affect other charts that rely on the\n // default thinning.\n showAllXAxisLabels?: boolean\n peerAverage?: number\n showArea?: boolean\n showAverage?: boolean\n showAxisHighlight?: boolean\n showBars?: boolean\n showLegend?: boolean\n showMark?: boolean\n showMarkLabel?: boolean\n showTooltip?: boolean\n showXAxis?: boolean\n showXAxisTicks?: boolean\n showYAxis?: boolean\n showYAxisTicks?: boolean\n tickIntervals?: any[] | 'auto' | ((value: any, index: number) => boolean) | undefined\n title?: string\n useCustomMark?: boolean\n valueFormatterString?: string\n width?: number\n xAxisScaleType?: 'band' | 'point'\n}\n\n// TODO: Remove negative values and use a proper layout to support X-Charts v8\n\nexport const LineChart: React.FC<LineChartProps> = ({\n areaColor,\n axisColor,\n baseline = 'max',\n chartFor,\n chartXaxisSx,\n chartYaxisSx,\n colors,\n curveType = 'linear',\n customLegendVariant,\n customLegendSx,\n customLegendBoxSx,\n customTooltipLabels,\n datasets,\n height,\n isCurrency,\n isGraphClippingXAxis = false,\n labels,\n labelBackgroundColor,\n labelFontColor,\n labelFontSize,\n margin,\n markHandlers,\n markStyles,\n minRange,\n maxRange,\n narrowXAxisLabels = false,\n showAllXAxisLabels = false,\n onItemClick,\n peerAverage,\n showArea = false,\n showAverage = false,\n showAxisHighlight = false,\n showBars = false,\n showLegend = false,\n showMark = true,\n showMarkLabel = false,\n showTooltip = false,\n showXAxis = false,\n showXAxisTicks = false,\n showYAxis = false,\n showYAxisTicks = false,\n title,\n useCustomMark = false,\n valueFormatterString,\n width,\n xAxisScaleType,\n}) => {\n const theme = useTheme()\n\n // Data for the X axis\n const xData = datasets.flat().map((item) => item.x)\n const yData = datasets.flat().map((item) => item.y)\n\n // Guard the empty-data case: with no points, reduce()/Math.min()/Math.max()\n // produce NaN/±Infinity which flow into the y-axis and make x-charts warn\n // \"the value NaN does not exist in the data of y axis\". Default to 0 so an\n // empty/loading chart renders a valid (flat) axis instead.\n const average = peerAverage\n ? peerAverage\n : yData.length\n ? Math.round(yData.reduce((value, total) => total + value, 0) / yData.length)\n : 0\n\n // Used for the min and max Y axis values\n const yMin = yData.length ? Math.floor(Math.min(...yData) / 100) * 100 : 0\n const yMax = yData.length ? Math.ceil(Math.max(...yData) / 100) * 100 : 0\n\n const series = datasets.map((data, index) => {\n return {\n type: showBars ? 'bar' : 'line',\n curve: curveType,\n color: showBars ? theme.palette.chart?.chart6 : (colors[index] ?? theme.palette.primary.main),\n data: data.map((item) => item.y),\n area: showArea,\n baseline: baseline,\n showMark: true,\n shape: getMarkerShape(index),\n valueFormatter: (value: number) =>\n valueFormatterString ? formatCurrency(value || 0, valueFormatterString) : String(value),\n }\n })\n\n const defaultMargin = {\n top: 60,\n right: 35,\n bottom: 25,\n left: -10,\n }\n\n // Merge default margin with any provided custom margin\n const chartMargin = {\n ...defaultMargin,\n ...margin,\n }\n\n let rangeMin = minRange ?? yMin\n let rangeMax = maxRange ?? yMax\n if (chartFor === 'networthChart') {\n const valueRange = yMax - yMin\n\n const paddingRatio = valueRange < yMax * 0.05 ? 0.25 : 0.2\n const padding = Math.max(valueRange * paddingRatio, yMax * 0.015)\n rangeMin = yMin - padding < 0 ? yMin : yMin - padding\n rangeMax = yMax + padding\n }\n\n const getTickInterval = () => {\n if (chartFor === 'creditOverTime') {\n return generateEqualIntervals(rangeMin, 850, 5)\n } else if (chartFor === 'networthChart') {\n return generateEqualIntervals(rangeMin, rangeMax, 5)\n }\n return undefined\n }\n return (\n <Box\n sx={{\n position: 'relative',\n touchAction: 'pan-y', // Allow vertical scrolling\n '& svg': {\n touchAction: 'pan-y', // Allow vertical scrolling on SVG\n userSelect: 'none', // Prevent text selection\n },\n '& .recharts-wrapper': {\n touchAction: 'pan-y', // For Recharts library specifically\n },\n }}\n >\n <ResponsiveChartContainer\n height={height}\n margin={chartMargin}\n series={series as AllSeriesType[]}\n sx={{\n '& .MuiBarLabel-root': {\n fontSize: 10,\n fontWeight: 600,\n },\n '& .MuiAreaElement-root': {\n opacity: 0.15,\n },\n '& .MuiChartsAxis-tickLabel > tspan': {\n fontFamily: theme.typography.body2.fontFamily,\n },\n '& .MuiLineChart-markLabel': {\n fontFamily: theme.typography.body2.fontFamily,\n },\n }}\n width={width}\n xAxis={[\n {\n data: xData,\n scaleType: xAxisScaleType || (showBars ? 'band' : 'point'),\n // Show every tick instead of letting x-charts drop overlapping ones.\n ...((showAllXAxisLabels || narrowXAxisLabels) && { tickLabelInterval: () => true }),\n },\n ]}\n yAxis={[\n {\n tickInterval: getTickInterval(),\n min: isGraphClippingXAxis ? -22 : rangeMin,\n max: rangeMax || 100,\n colorMap:\n showArea && series.length < 2\n ? {\n type: 'continuous',\n min: rangeMin,\n max: rangeMax,\n color: [\n theme.palette.background.paper,\n colors[0] ?? theme.palette.primary.main,\n ],\n }\n : undefined,\n valueFormatter: (value: number) =>\n valueFormatterString ? formatCurrency(value, valueFormatterString) : String(value),\n width: 62,\n },\n ]}\n >\n {/** Provides the average line - positioned first to be behind other elements **/}\n {showAverage && (\n <ChartsReferenceLine\n lineStyle={{\n stroke: labelBackgroundColor\n ? theme.palette.neutral.main\n : theme.palette.neutral.dark,\n strokeDasharray: '10, 8',\n strokeWidth: 2,\n }}\n y={average}\n />\n )}\n\n {/** Area plot provides gradiant below the line **/}\n {/* Note: Must be above the LinePlot for some style rules to work */}\n <AreaPlot\n onItemClick={onItemClick}\n {...(areaColor && {\n slots: {\n area: (props) => {\n return (\n <g>\n <defs>\n <linearGradient id=\"customGradient\" x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={areaColor} />\n <stop offset=\"100%\" stopColor={areaColor} stopOpacity={0.02} />\n </linearGradient>\n </defs>\n <path {...stripChartSlotProps(props)} fill={`url(#customGradient)`} />\n </g>\n )\n },\n },\n })}\n />\n\n {/** Line plot provides the data line **/}\n <LinePlot\n onItemClick={onItemClick}\n slots={{\n line: (props) => (\n <CustomLine\n {...props}\n lineColor={areaColor ?? props.ownerState.color ?? theme.palette.primary.main}\n />\n ),\n }}\n />\n\n {/** Mark plot provides the circles **/}\n <MarkPlot\n onItemClick={onItemClick}\n slots={\n useCustomMark\n ? {\n mark: (props) => {\n return (\n <CustomMark\n handlers={markHandlers}\n labelBackgroundColor={labelBackgroundColor}\n labelFontColor={labelFontColor}\n labelFontSize={labelFontSize}\n showLabel={showMarkLabel}\n showMark={showMark || props.dataIndex === datasets[0].length - 1}\n style={markStyles?.(props.dataIndex) ?? {}}\n valueFormatterString={valueFormatterString}\n yData={yData}\n {...props}\n />\n )\n },\n }\n : undefined\n }\n />\n\n <BarPlot\n barLabel={(item) => (Number(item.value) > 0 ? `$${item.value}` : null)}\n borderRadius={10}\n />\n\n {/** Provides the X axis line and values **/}\n <ChartsXAxis\n disableLine={!showXAxis}\n disableTicks={!showXAxisTicks}\n slots={narrowXAxisLabels ? NARROW_X_AXIS_SLOTS : undefined}\n slotProps={\n axisColor\n ? {\n axisLine: {\n style: {\n stroke: axisColor,\n },\n },\n axisTick: {\n style: {\n stroke: axisColor,\n },\n },\n }\n : {}\n }\n sx={{ ...chartXaxisSx }}\n />\n\n {/** Provides the Y axis values **/}\n <ChartsYAxis\n disableLine={!showYAxis}\n disableTicks={!showYAxisTicks}\n slotProps={\n axisColor\n ? {\n axisLine: {\n style: {\n stroke: axisColor,\n },\n },\n axisTick: {\n style: {\n stroke: axisColor,\n },\n },\n }\n : {}\n }\n sx={{ ...chartYaxisSx }}\n />\n\n {/* Add vertical crosshair on hover */}\n {showAxisHighlight && <ChartsAxisHighlight x=\"line\" />}\n\n {showTooltip && (\n <ChartsTooltipContainer trigger=\"axis\">\n <CustomTooltip\n customLabels={customTooltipLabels}\n isCurrency={isCurrency}\n labels={labels}\n series={series}\n valueFormatterString={valueFormatterString}\n />\n </ChartsTooltipContainer>\n )}\n </ResponsiveChartContainer>\n\n {showLegend && (\n <CustomLegend\n average={showAverage ? average : undefined}\n customLegendBoxSx={customLegendBoxSx}\n customLegendVariant={customLegendVariant}\n labels={labels}\n series={series}\n style={{\n position: 'absolute',\n top: 16,\n left: 16,\n ...customLegendSx,\n }}\n title={title}\n valueFormatterString={valueFormatterString}\n />\n )}\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { useEvent as
|
|
2
|
-
import { useScreenSize as
|
|
3
|
-
import { ANALYTICS_EVENTS as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
1
|
+
import { useEvent as E, useGlobalCopyStore as H } from "../../common/context/hooks.es.js";
|
|
2
|
+
import { useScreenSize as I } from "../../common/hooks/useScreenSize.es.js";
|
|
3
|
+
import { ANALYTICS_EVENTS as N } from "../../common/constants/Analytics.es.js";
|
|
4
|
+
import { useDimensions as D } from "../../common/hooks/useDimensions.es.js";
|
|
5
|
+
import { LineChart as M } from "../../common/components/charts/LineChart.es.js";
|
|
6
|
+
import { getIncomeTotals as k, getSpendingTotals as R } from "../utils/SpendingData.es.js";
|
|
7
|
+
import { TRENDS_ANALYTICS_METADATA as X } from "../constants/TrendsWidget.es.js";
|
|
8
|
+
import p from "react";
|
|
9
|
+
import { observer as Y } from "mobx-react-lite";
|
|
10
|
+
import { jsx as T } from "react/jsx-runtime";
|
|
11
|
+
import { useTheme as y } from "@mui/material/styles";
|
|
12
|
+
import B from "@mui/material/Box";
|
|
13
|
+
var W = 12, O = 380, j = (t, e) => [k(t, e), R(t, e)].filter((o) => o.length > 0), z = (t, e) => {
|
|
12
14
|
const [o, c] = t, s = o, l = c ?? o, r = [];
|
|
13
15
|
if (s) {
|
|
14
16
|
const a = s.reduce((n, i) => n + i.y, 0);
|
|
@@ -25,34 +27,40 @@ var N = (t, e) => [I(t, e), _(t, e)].filter((o) => o.length > 0), y = (t, e) =>
|
|
|
25
27
|
});
|
|
26
28
|
}
|
|
27
29
|
return r;
|
|
28
|
-
},
|
|
29
|
-
const s =
|
|
30
|
-
return
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
}, [t]), /* @__PURE__ */
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
30
|
+
}, F = ({ availableHeight: t = 0, minHeight: e = 500, selectedDateRange: o, totals: c }) => {
|
|
31
|
+
const s = y(), { onEvent: l } = E(), { trends: r } = H(), { isSmallMobile: a, isMobile: n, isSmallTablet: i, isTablet: d } = I(), [A, { width: u }] = D(), f = [s.palette.chart?.chart1, s.palette.chart?.chart2], h = j(c, o), b = z(h, r), g = Math.max(0, ...h.map((m) => m.length)), C = u > 0 && u <= O && g >= W, [S, w] = p.useState(0), x = 458, _ = 195, L = 56, v = n || a ? _ : i || d ? x : S;
|
|
32
|
+
return p.useEffect(() => {
|
|
33
|
+
const m = Math.max(t - L, e);
|
|
34
|
+
w(m);
|
|
35
|
+
}, [t]), /* @__PURE__ */ T(B, {
|
|
36
|
+
ref: A,
|
|
37
|
+
sx: { width: "100%" },
|
|
38
|
+
children: /* @__PURE__ */ T(M, {
|
|
39
|
+
baseline: "min",
|
|
40
|
+
colors: f,
|
|
41
|
+
curveType: "bump",
|
|
42
|
+
datasets: h,
|
|
43
|
+
height: v,
|
|
44
|
+
labels: b,
|
|
45
|
+
narrowXAxisLabels: C,
|
|
46
|
+
onItemClick: () => {
|
|
47
|
+
l(N.TRENDS_CLICK_CHART, X);
|
|
48
|
+
},
|
|
49
|
+
showAllXAxisLabels: !0,
|
|
50
|
+
showArea: !0,
|
|
51
|
+
showAxisHighlight: !0,
|
|
52
|
+
showLegend: !0,
|
|
53
|
+
showTooltip: !0,
|
|
54
|
+
showXAxis: !0,
|
|
55
|
+
showXAxisTicks: !0,
|
|
56
|
+
showYAxis: !0,
|
|
57
|
+
showYAxisTicks: !0,
|
|
58
|
+
valueFormatterString: "0.0a"
|
|
59
|
+
})
|
|
52
60
|
});
|
|
53
|
-
},
|
|
61
|
+
}, st = Y(F);
|
|
54
62
|
export {
|
|
55
|
-
|
|
63
|
+
st as default
|
|
56
64
|
};
|
|
57
65
|
|
|
58
66
|
//# sourceMappingURL=TrendsChartTotals.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TrendsChartTotals.es.js","names":[],"sources":["../../../src/trends/components/TrendsChartTotals.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport { useTheme } from '@mui/material/styles'\n\nimport { ANALYTICS_EVENTS, useEvent, useGlobalCopyStore, useScreenSize } from '../../common'\nimport { DateRange, MonthlyCategoryTotals, TrendsCopy } from '../../core'\nimport { LineChart } from '../../common/components/charts/LineChart'\nimport type { LineChartDataset, LineChartLabel } from '../../common/components/charts/LineChart'\n\nimport { TRENDS_ANALYTICS_METADATA } from '../constants/TrendsWidget'\nimport { getIncomeTotals, getSpendingTotals } from '../utils/SpendingData'\n\nconst getDatasets = (totals: MonthlyCategoryTotals[], dateRange: DateRange): LineChartDataset[] => {\n const incomeData = getIncomeTotals(totals, dateRange)\n const spendingData = getSpendingTotals(totals, dateRange)\n return [incomeData, spendingData].filter((data) => data.length > 0)\n}\n\nconst getLabels = (datasets: LineChartDataset[], copy: TrendsCopy) => {\n const [dataA, dataB] = datasets\n const credits = dataA\n const debits = dataB ?? dataA\n const labels: LineChartLabel[] = []\n\n if (credits) {\n const totalIncome = credits.reduce((sum, item) => sum + item.y, 0)\n labels.push({ label: copy.income_label, amount: totalIncome })\n }\n\n if (debits) {\n const totalSpending = debits.reduce((sum, item) => sum + item.y, 0)\n labels.push({ label: copy.spending_label, amount: totalSpending })\n }\n\n return labels\n}\n\ninterface TrendsChartTotalsProps {\n availableHeight?: number\n minHeight?: number\n selectedDateRange: DateRange\n totals: MonthlyCategoryTotals[]\n}\n\nconst TrendsChartTotals: React.FC<TrendsChartTotalsProps> = ({\n availableHeight = 0,\n minHeight = 500,\n selectedDateRange,\n totals,\n}) => {\n const theme = useTheme()\n const { onEvent } = useEvent()\n const { trends: trendsCopy } = useGlobalCopyStore()\n const { isSmallMobile, isMobile, isSmallTablet, isTablet } = useScreenSize()\n\n const colors = [theme.palette.chart?.chart1, theme.palette.chart?.chart2]\n const datasets = getDatasets(totals, selectedDateRange)\n const labels = getLabels(datasets, trendsCopy)\n\n const [chartDesktopHeight, setChartDesktopHeight] = React.useState<number>(0)\n const chartTabletHeight = 458\n const chartMobileHeight = 195\n const legendHeight = 56\n\n // prettier-ignore\n // eslint-disable-next-line no-nested-ternary\n const chartHeight = (isMobile || isSmallMobile) ? chartMobileHeight :\n (isSmallTablet || isTablet) ? chartTabletHeight : chartDesktopHeight;\n\n // Control responsive chart height based on available height\n React.useEffect(() => {\n const newChartHeight = Math.max(availableHeight - legendHeight, minHeight)\n setChartDesktopHeight(newChartHeight)\n }, [availableHeight])\n\n const handleItemClick = () => {\n onEvent(ANALYTICS_EVENTS.TRENDS_CLICK_CHART, TRENDS_ANALYTICS_METADATA)\n }\n\n return (\n <LineChart\n
|
|
1
|
+
{"version":3,"file":"TrendsChartTotals.es.js","names":[],"sources":["../../../src/trends/components/TrendsChartTotals.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport { useTheme } from '@mui/material/styles'\n\nimport { ANALYTICS_EVENTS, useEvent, useGlobalCopyStore, useScreenSize } from '../../common'\nimport { DateRange, MonthlyCategoryTotals, TrendsCopy } from '../../core'\nimport { useDimensions } from '../../common/hooks/useDimensions'\nimport { LineChart } from '../../common/components/charts/LineChart'\nimport type { LineChartDataset, LineChartLabel } from '../../common/components/charts/LineChart'\n\nimport { TRENDS_ANALYTICS_METADATA } from '../constants/TrendsWidget'\nimport { getIncomeTotals, getSpendingTotals } from '../utils/SpendingData'\n\n// Single-letter month labels only kick in for the 12-month (1 Year) view once\n// the chart container is this narrow; wider containers keep full labels.\nconst MONTHS_IN_YEAR = 12\nconst NARROW_LABELS_MAX_WIDTH_PX = 380\n\nconst getDatasets = (totals: MonthlyCategoryTotals[], dateRange: DateRange): LineChartDataset[] => {\n const incomeData = getIncomeTotals(totals, dateRange)\n const spendingData = getSpendingTotals(totals, dateRange)\n return [incomeData, spendingData].filter((data) => data.length > 0)\n}\n\nconst getLabels = (datasets: LineChartDataset[], copy: TrendsCopy) => {\n const [dataA, dataB] = datasets\n const credits = dataA\n const debits = dataB ?? dataA\n const labels: LineChartLabel[] = []\n\n if (credits) {\n const totalIncome = credits.reduce((sum, item) => sum + item.y, 0)\n labels.push({ label: copy.income_label, amount: totalIncome })\n }\n\n if (debits) {\n const totalSpending = debits.reduce((sum, item) => sum + item.y, 0)\n labels.push({ label: copy.spending_label, amount: totalSpending })\n }\n\n return labels\n}\n\ninterface TrendsChartTotalsProps {\n availableHeight?: number\n minHeight?: number\n selectedDateRange: DateRange\n totals: MonthlyCategoryTotals[]\n}\n\nconst TrendsChartTotals: React.FC<TrendsChartTotalsProps> = ({\n availableHeight = 0,\n minHeight = 500,\n selectedDateRange,\n totals,\n}) => {\n const theme = useTheme()\n const { onEvent } = useEvent()\n const { trends: trendsCopy } = useGlobalCopyStore()\n const { isSmallMobile, isMobile, isSmallTablet, isTablet } = useScreenSize()\n const [chartRef, { width: chartWidth }] = useDimensions()\n\n const colors = [theme.palette.chart?.chart1, theme.palette.chart?.chart2]\n const datasets = getDatasets(totals, selectedDateRange)\n const labels = getLabels(datasets, trendsCopy)\n\n // Measured from the chart container, not the device, so it also handles the\n // widget embedded in a small iframe on a larger screen.\n const monthCount = Math.max(0, ...datasets.map((data) => data.length))\n const useNarrowXAxisLabels =\n chartWidth > 0 && chartWidth <= NARROW_LABELS_MAX_WIDTH_PX && monthCount >= MONTHS_IN_YEAR\n\n const [chartDesktopHeight, setChartDesktopHeight] = React.useState<number>(0)\n const chartTabletHeight = 458\n const chartMobileHeight = 195\n const legendHeight = 56\n\n // prettier-ignore\n // eslint-disable-next-line no-nested-ternary\n const chartHeight = (isMobile || isSmallMobile) ? chartMobileHeight :\n (isSmallTablet || isTablet) ? chartTabletHeight : chartDesktopHeight;\n\n // Control responsive chart height based on available height\n React.useEffect(() => {\n const newChartHeight = Math.max(availableHeight - legendHeight, minHeight)\n setChartDesktopHeight(newChartHeight)\n }, [availableHeight])\n\n const handleItemClick = () => {\n onEvent(ANALYTICS_EVENTS.TRENDS_CLICK_CHART, TRENDS_ANALYTICS_METADATA)\n }\n\n return (\n <Box ref={chartRef} sx={{ width: '100%' }}>\n <LineChart\n baseline=\"min\"\n colors={colors}\n curveType=\"bump\"\n datasets={datasets}\n height={chartHeight}\n labels={labels}\n narrowXAxisLabels={useNarrowXAxisLabels}\n onItemClick={handleItemClick}\n showAllXAxisLabels={true}\n showArea={true}\n showAxisHighlight={true}\n showLegend={true}\n showTooltip={true}\n showXAxis={true}\n showXAxisTicks={true}\n showYAxis={true}\n showYAxisTicks={true}\n valueFormatterString=\"0.0a\"\n />\n </Box>\n )\n}\n\nexport default observer(TrendsChartTotals)\n"],"mappings":";;;;;;;;;;;;AAiBA,IAAM,IAAiB,IACjB,IAA6B,KAE7B,IAAA,CAAe,GAAiC,MAG7C,CAFY,EAAgB,GAAQ,CAEnC,GADa,EAAkB,GAAQ,CAC3B,CAAY,EAAE,OAAA,CAAQ,MAAS,EAAK,SAAS,CAAC,GAG9D,IAAA,CAAa,GAA8B,MAAqB;AACpE,QAAM,CAAC,GAAO,CAAA,IAAS,GACjB,IAAU,GACV,IAAS,KAAS,GAClB,IAA2B,CAAC;AAElC,MAAI,GAAS;AACX,UAAM,IAAc,EAAQ,OAAA,CAAQ,GAAK,MAAS,IAAM,EAAK,GAAG,CAAC;AACjE,IAAA,EAAO,KAAK;AAAA,MAAE,OAAO,EAAK;AAAA,MAAc,QAAQ;AAAA,IAAY,CAAC;AAAA,EAC/D;AAEA,MAAI,GAAQ;AACV,UAAM,IAAgB,EAAO,OAAA,CAAQ,GAAK,MAAS,IAAM,EAAK,GAAG,CAAC;AAClE,IAAA,EAAO,KAAK;AAAA,MAAE,OAAO,EAAK;AAAA,MAAgB,QAAQ;AAAA,IAAc,CAAC;AAAA,EACnE;AAEA,SAAO;AACT,GASM,IAAA,CAAuD,EAC3D,iBAAA,IAAkB,GAClB,WAAA,IAAY,KACZ,mBAAA,GACA,QAAA,EAAA,MACI;AACJ,QAAM,IAAQ,EAAS,GACjB,EAAE,SAAA,EAAA,IAAY,EAAS,GACvB,EAAE,QAAQ,EAAA,IAAe,EAAmB,GAC5C,EAAE,eAAA,GAAe,UAAA,GAAU,eAAA,GAAe,UAAA,EAAA,IAAa,EAAc,GACrE,CAAC,GAAU,EAAE,OAAO,EAAA,CAAA,IAAgB,EAAc,GAElD,IAAS,CAAC,EAAM,QAAQ,OAAO,QAAQ,EAAM,QAAQ,OAAO,MAAM,GAClE,IAAW,EAAY,GAAQ,CAAiB,GAChD,IAAS,EAAU,GAAU,CAAU,GAIvC,IAAa,KAAK,IAAI,GAAG,GAAG,EAAS,IAAA,CAAK,MAAS,EAAK,MAAM,CAAC,GAC/D,IACJ,IAAa,KAAK,KAAc,KAA8B,KAAc,GAExE,CAAC,GAAoB,CAAA,IAAyB,EAAM,SAAiB,CAAC,GACtE,IAAoB,KACpB,IAAoB,KACpB,IAAe,IAIf,IAAe,KAAY,IAAiB,IACjD,KAAiB,IAAY,IAAoB;AAGlD,SAAA,EAAM,UAAA,MAAgB;AACpB,UAAM,IAAiB,KAAK,IAAI,IAAkB,GAAc,CAAS;AACzE,IAAA,EAAsB,CAAc;AAAA,EACtC,GAAG,CAAC,CAAe,CAAC,GAOlB,gBAAA,EAAC,GAAD;AAAA,IAAK,KAAK;AAAA,IAAU,IAAI,EAAE,OAAO,OAAO;AAAA,IACtC,UAAA,gBAAA,EAAC,GAAD;AAAA,MACE,UAAS;AAAA,MACD,QAAA;AAAA,MACR,WAAU;AAAA,MACA,UAAA;AAAA,MACV,QAAQ;AAAA,MACA,QAAA;AAAA,MACR,mBAAmB;AAAA,MACnB,aAdA,MAAwB;AAC5B,QAAA,EAAQ,EAAiB,oBAAoB,CAAyB;AAAA,MACxE;AAAA,MAaM,oBAAoB;AAAA,MACpB,UAAU;AAAA,MACV,mBAAmB;AAAA,MACnB,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,sBAAqB;AAAA,IACtB,CAAA;AAAA,EACE,CAAA;AAET,GAEA,KAAe,EAAS,CAAiB"}
|