@mx-cartographer/experiences 8.0.0-alpha.v2 → 8.0.1
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
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
## [8.0.1] - 04-06-2026
|
|
2
|
+
|
|
3
|
+
- **UPDATED** - Documentation to reflect the move of shared types and constants to `src/core`
|
|
4
|
+
- **UPDATED** - Technical support Slack channel reference to the new enterprise link
|
|
5
|
+
- **UPDATED** - Installation and publishing guides to reflect Yarn-only project mandate
|
|
6
|
+
- **UPDATED** - Architectural diagrams to include the new `src/core` layer
|
|
7
|
+
|
|
1
8
|
## [8.0.0] - 04-02-2026
|
|
2
9
|
|
|
3
10
|
- **UPDATED** - types by moving from common/types to core/types (BREAKING CHANGE)
|
|
4
11
|
|
|
12
|
+
## [7.13.21] - 04-03-2026
|
|
13
|
+
|
|
14
|
+
- **FIXED** - `Spending` widget treating negative transactions as expenses
|
|
15
|
+
|
|
5
16
|
## [7.13.20] - 04-02-2026
|
|
6
17
|
|
|
7
18
|
- **ADDED** - DonutChartV2 component for Insights MUI Refresh.
|
package/README.md
CHANGED
|
@@ -1,16 +1,197 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
-
|
|
1
|
+
# @mx-cartographer/experiences
|
|
2
|
+
|
|
3
|
+
@mx-cartographer/experiences is a React-based library of financial experience widgets designed for seamless integration within the MX ecosystem. It provides a robust collection of modular widgets (e.g., Accounts, Budgets, Cashflow) built on top of Material UI (MUI) [^MUI_VER] and the MXUI design system [^MXUI_VER], powered by MobX [^MOBX_VER] for scalable state management.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- [Architecture Overview](docs/ARCHITECTURE.md)
|
|
8
|
+
- [Widget Catalog](docs/WIDGETS.md)
|
|
9
|
+
- [State Management](docs/STATE_MANAGEMENT.md)
|
|
10
|
+
- [API and Data](docs/API_AND_DATA.md)
|
|
11
|
+
- [Styling and Theming](docs/STYLING_AND_THEMING.md)
|
|
12
|
+
- [Testing](docs/TESTING.md)
|
|
13
|
+
|
|
14
|
+
## Tech Stack
|
|
4
15
|
|
|
16
|
+
The library is built using a modern React stack, leveraging industry-standard tools for building performant and accessible UI components.
|
|
5
17
|
|
|
6
|
-
|
|
7
|
-
|
|
18
|
+
| Component | Technology | Description |
|
|
19
|
+
| :--- | :--- | :--- |
|
|
20
|
+
| **Framework** | [React](https://reactjs.org/) | Core library for building declarative UI components. |
|
|
21
|
+
| **Language** | [TypeScript](https://www.typescriptlang.org/) | Provides static typing for improved maintainability and developer experience. |
|
|
22
|
+
| **Styling** | [Material UI (MUI)](https://mui.com/) | Base UI component framework and styling system. |
|
|
23
|
+
| **Design System** | [@mxenabled/mxui](https://mx.atlassian.net/wiki) | MX-themed overrides and consistent UI primitives. |
|
|
24
|
+
| **State Management** | [MobX](https://mobx.js.org/) | Scalable and observable state management for complex widget interactions. |
|
|
25
|
+
| **Data Visualization** | [D3.js](https://d3js.org/) | Powering complex charts and interactive data representations. |
|
|
26
|
+
| **Build Tool** | [Vite](https://vitejs.dev/) | Next-generation frontend tooling for fast builds and development. |
|
|
27
|
+
| **Testing** | [Vitest](https://vitest.dev/) | Modern testing framework compatible with the Vite ecosystem. |
|
|
28
|
+
| **Documentation** | [Storybook](https://storybook.js.org/) | Component-driven development environment and live documentation. |
|
|
8
29
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
30
|
+
## Table of Contents
|
|
31
|
+
- [Getting Started](#getting-started)
|
|
32
|
+
- [Installation](#installation)
|
|
33
|
+
- [Usage](#usage)
|
|
34
|
+
- [Architecture](#architecture)
|
|
35
|
+
- [Project Structure](#project-structure)
|
|
36
|
+
- [Testing](#testing)
|
|
37
|
+
- [Contributing](#contributing)
|
|
38
|
+
- [Support](#support)
|
|
39
|
+
|
|
40
|
+
## Getting Started
|
|
41
|
+
|
|
42
|
+
### Prerequisites
|
|
43
|
+
- **Node.js**: v18.0.0 or higher
|
|
44
|
+
- **Yarn**: 4.11.0 [^YARN_VER]
|
|
45
|
+
- **React**: 18.3.1 [^REACT_VER]
|
|
46
|
+
- **MobX**: 6.13.6 [^MOBX_VER]
|
|
47
|
+
|
|
48
|
+
### Installation
|
|
49
|
+
|
|
50
|
+
Install the library using yarn:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
yarn add @mx-cartographer/experiences
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The QA storybook containing the latest Experience changes is [accessible here](https://experiences.kube.qa.internal.mx/?path=/docs/experiences-introduction--docs).
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
### Integrating a Widget
|
|
61
|
+
To use an experience widget, import it from its feature-specific entry point. Most widgets are designed to automatically wrap themselves in a `WidgetContainer` for consistent layout.
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import React from 'react';
|
|
65
|
+
import { AccountsWidget } from '@mx-cartographer/experiences/accounts';
|
|
66
|
+
|
|
67
|
+
const MyDashboard = () => {
|
|
68
|
+
return (
|
|
69
|
+
<div style={{ height: '600px', width: '100%' }}>
|
|
70
|
+
<AccountsWidget
|
|
71
|
+
onBackClick={() => console.log('User clicked back')}
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Common Configuration
|
|
79
|
+
Widgets often accept `sx` props for styling and specific callbacks for navigation or analytics.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { BudgetsWidget } from '@mx-cartographer/experiences/budgets';
|
|
83
|
+
|
|
84
|
+
<BudgetsWidget
|
|
85
|
+
sx={{ m: 2, borderRadius: '8px' }}
|
|
86
|
+
onBudgetClick={(budgetId) => navigate(`/budgets/${budgetId}`)}
|
|
87
|
+
/>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Architecture
|
|
91
|
+
|
|
92
|
+
The project follows a modular architecture where feature widgets leverage shared infrastructure and a unified design system.
|
|
93
|
+
|
|
94
|
+
```mermaid
|
|
95
|
+
graph TB
|
|
96
|
+
subgraph "Consumer Application"
|
|
97
|
+
App[React Application]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
subgraph "@mx-cartographer/experiences"
|
|
101
|
+
subgraph "Common Infrastructure (src/common)"
|
|
102
|
+
WC[WidgetContainer]
|
|
103
|
+
GP[WidgetContainerProvider]
|
|
104
|
+
GS[GlobalUiStore / GlobalCopyStore]
|
|
105
|
+
API[WidgetApi / Fetch]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
subgraph "Experience Widgets (src/[feature])"
|
|
109
|
+
AW[AccountsWidget]
|
|
110
|
+
BW[BudgetsWidget]
|
|
111
|
+
CW[CashflowWidget]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
subgraph "State Management"
|
|
115
|
+
MX[MobX]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
subgraph "UI Foundation"
|
|
119
|
+
MUI[Material UI]
|
|
120
|
+
MXUI[@mxenabled/mxui]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
App --> AW
|
|
125
|
+
App --> BW
|
|
126
|
+
AW --> WC
|
|
127
|
+
BW --> WC
|
|
128
|
+
WC --> GP
|
|
129
|
+
AW --> GS
|
|
130
|
+
AW --> API
|
|
131
|
+
GS --> MX
|
|
132
|
+
AW --> MXUI
|
|
133
|
+
MXUI --> MUI
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Key Design Patterns
|
|
137
|
+
- **Container Pattern**: Widgets are wrapped in `WidgetContainer` [^1] to provide consistent headers, action buttons, and navigation.
|
|
138
|
+
- **Context-Driven Layout**: The `WidgetContainerProvider` [^2] calculates container dimensions to enable internal responsive rendering logic.
|
|
139
|
+
- **State Isolation**: Each feature (e.g., Budgets, Accounts) maintains its own MobX store, while sharing global state through `GlobalUiStore` and `GlobalCopyStore` [^3].
|
|
140
|
+
- **Responsive Primitives**: All components use the `useScreenSize` hook [^4] for consistent behavior across mobile, tablet, and desktop viewports.
|
|
141
|
+
|
|
142
|
+
## Project Structure
|
|
143
|
+
|
|
144
|
+
The codebase is organized by feature, with a shared `common` directory for cross-cutting concerns and a `core` directory for centralized types and constants.
|
|
145
|
+
|
|
146
|
+
```mermaid
|
|
147
|
+
graph TD
|
|
148
|
+
src["src/"]
|
|
149
|
+
src --> core["core/ (Centralized TypeScript types and constants)"]
|
|
150
|
+
src --> common["common/ (Shared components, hooks, stores, and API utilities)"]
|
|
151
|
+
src --> accounts["accounts/ (Accounts summary, details, and connection management)"]
|
|
152
|
+
src --> budgets["budgets/ (Budget tracking, bubble charts, and categorization)"]
|
|
153
|
+
src --> cashflow["cashflow/ (Cashflow forecasting and event management)"]
|
|
154
|
+
src --> dashboard["dashboard/ (Aggregate view of multiple experience widgets)"]
|
|
155
|
+
src --> debts["debts/ (Debt tracking and payoff visualization)"]
|
|
156
|
+
src --> finstrong["finstrong/ (Financial health scoring and reporting)"]
|
|
157
|
+
src --> goals["goals/ (Savings goal setting, tracking, and progress visualization)"]
|
|
158
|
+
src --> networth["networth/ (Asset and liability tracking with historical trends)"]
|
|
159
|
+
src --> spending["spending/ (Categorized spending analysis)"]
|
|
160
|
+
src --> transactions["transactions/ (Detailed transaction history and rules)"]
|
|
161
|
+
src --> trends["trends/ (Longitudinal spending and income analysis)"]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Testing
|
|
165
|
+
|
|
166
|
+
The library uses `Vitest` [^5] and `@testing-library/react` [^6] for comprehensive unit and integration testing.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# Run all tests
|
|
170
|
+
yarn test
|
|
171
|
+
|
|
172
|
+
# Run tests with interactive UI and coverage reporting
|
|
173
|
+
yarn testui
|
|
174
|
+
|
|
175
|
+
# Run tests in headless mode (CI)
|
|
176
|
+
yarn citest
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Verification logic and test setups are maintained in [src/common/__tests__](src/common/__tests__) and [vitest.setup.insights.tsx](vitest.setup.insights.tsx).
|
|
180
|
+
|
|
181
|
+
## Contributing
|
|
182
|
+
|
|
183
|
+
1. **Local Development**: Preview widgets in isolation using Storybook.
|
|
184
|
+
```bash
|
|
185
|
+
yarn storybook
|
|
186
|
+
```
|
|
187
|
+
2. **Linting**: Maintain code quality and standards.
|
|
188
|
+
```bash
|
|
189
|
+
yarn lint
|
|
190
|
+
```
|
|
191
|
+
3. **Building**: Generate production-ready artifacts.
|
|
192
|
+
```bash
|
|
193
|
+
yarn build
|
|
194
|
+
```
|
|
14
195
|
|
|
15
196
|
<!-- Commented this out to prevent exposing internal operations in the npm registry -->
|
|
16
197
|
|
|
@@ -25,37 +206,23 @@ In order to run the project you will need to make sure that you have yarn instal
|
|
|
25
206
|
1. Once the MR is approved, comment `shipit --publish-version=major|minor|patch`.
|
|
26
207
|
2. Shipit will bump the version in package.json, merge and publish the package to npm. -->
|
|
27
208
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
1.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
1. Open Settings > Repository for the repo
|
|
49
|
-
1. Expand the "Selected branches" section
|
|
50
|
-
1. For the master branch, set the "Allowed to merge" option to "Developers + Maintainers" and the "Allowed to push" option to "No one"
|
|
51
|
-
|
|
52
|
-
#### Merge Request Approvals
|
|
53
|
-
|
|
54
|
-
1. Open Settings > General for the repo
|
|
55
|
-
1. Expand the "Merge request approvals section"
|
|
56
|
-
1. Change approvals required to 1
|
|
57
|
-
|
|
58
|
-
#### Issue board
|
|
59
|
-
|
|
60
|
-
Under Issues > Boards, create a new board to track issues for that specific repo. Copy the labels/lists from the scoped issue board in the Cartographer group to create this one. The labels will be the same, but the new issue board will only shows issues created for this specific repo.
|
|
61
|
-
|
|
209
|
+
## Support
|
|
210
|
+
|
|
211
|
+
For technical assistance or internal inquiries:
|
|
212
|
+
- **Team**: MX Cartographer
|
|
213
|
+
- **Docs**: [MX Developer Portal](https://mx.atlassian.net/wiki)
|
|
214
|
+
- **Slack**: https://mx.enterprise.slack.com/archives/C08M61HSWRF #web-experiences-dev-all
|
|
215
|
+
|
|
216
|
+
## Copyright (c) 2026 MX Technologies, Inc. All Rights Reserved.
|
|
217
|
+
|
|
218
|
+
[^1]: [src/common/components/WidgetContainer.tsx:55](src/common/components/WidgetContainer.tsx#L55)
|
|
219
|
+
[^2]: [src/common/context/WidgetContainerProvider.tsx:10](src/common/context/WidgetContainerProvider.tsx#L10)
|
|
220
|
+
[^3]: [src/common/context/GlobalStoreProvider.tsx:10](src/common/context/GlobalStoreProvider.tsx#L10)
|
|
221
|
+
[^4]: [src/common/hooks/useScreenSize.tsx:4](src/common/hooks/useScreenSize.tsx#L4)
|
|
222
|
+
[^5]: [package.json:267](package.json#L267)
|
|
223
|
+
[^6]: [package.json:160](package.json#L160)
|
|
224
|
+
[^MUI_VER]: [package.json:188](package.json#L188)
|
|
225
|
+
[^MXUI_VER]: [package.json:196](package.json#L196)
|
|
226
|
+
[^MOBX_VER]: [package.json:202](package.json#L202)
|
|
227
|
+
[^REACT_VER]: [package.json:206](package.json#L206)
|
|
228
|
+
[^YARN_VER]: [package.json:284](package.json#L284)
|
|
@@ -13,31 +13,31 @@ import { u as R } from "./useAriaLive-MkYebyUR.mjs";
|
|
|
13
13
|
import { u as v } from "./hooks-BxkfR-Ff.mjs";
|
|
14
14
|
import { u as V } from "./useScreenSize-B6JyS_Lj.mjs";
|
|
15
15
|
import { f as b } from "./NumberFormatting-QCaNwbjv.mjs";
|
|
16
|
-
const D = 5, B = (i, l, g,
|
|
16
|
+
const D = 5, B = (i, l, g, m) => m.reduce((o, n) => {
|
|
17
17
|
const a = i.find((s) => s.guid === n.category_guid);
|
|
18
18
|
if (!a) return o;
|
|
19
19
|
const t = a.parent_guid ?? a.guid, r = i.find((s) => s.guid === t);
|
|
20
|
-
if (!r) return o;
|
|
21
|
-
const
|
|
20
|
+
if (!r || n.total <= 0) return o;
|
|
21
|
+
const c = {
|
|
22
22
|
guid: a.guid,
|
|
23
23
|
name: a.guid === t ? `${l.parent_category_totals_label_general} ${a.name}` : a.name,
|
|
24
24
|
color: _(r.guid, g),
|
|
25
25
|
amount: n.total
|
|
26
26
|
}, e = o.find((s) => s.guid === t);
|
|
27
|
-
return e ? (e.amount += n.total, e.categoryTotals?.push(
|
|
27
|
+
return e ? (e.amount += n.total, e.categoryTotals?.push(c)) : o.push({
|
|
28
28
|
guid: t,
|
|
29
29
|
name: r.name,
|
|
30
30
|
color: _(r.guid, g),
|
|
31
|
-
categoryTotals: [
|
|
31
|
+
categoryTotals: [c],
|
|
32
32
|
amount: n.total
|
|
33
33
|
}), o;
|
|
34
|
-
}, []), nt = (i, l, g,
|
|
35
|
-
const n = B(i, l, g,
|
|
34
|
+
}, []), nt = (i, l, g, m) => {
|
|
35
|
+
const n = B(i, l, g, m).filter(
|
|
36
36
|
(e) => e.guid !== p.INCOME && e.guid !== p.INVESTMENTS && e.guid !== p.TRANSFER && e.amount > 0
|
|
37
37
|
).sort((e, s) => s.amount - e.amount), a = n.reduce(
|
|
38
38
|
(e, s) => e + s.amount,
|
|
39
39
|
0
|
|
40
|
-
), t = n.length > D ? D : n.length, r = n.slice(0, t),
|
|
40
|
+
), t = n.length > D ? D : n.length, r = n.slice(0, t), c = r.map((e) => ({
|
|
41
41
|
id: e.guid,
|
|
42
42
|
color: _(e.guid, g),
|
|
43
43
|
label: e.name,
|
|
@@ -54,7 +54,7 @@ const D = 5, B = (i, l, g, c) => c.reduce((o, n) => {
|
|
|
54
54
|
name: l.saving_goal_other,
|
|
55
55
|
categoryTotals: e,
|
|
56
56
|
amount: s
|
|
57
|
-
}),
|
|
57
|
+
}), c.push({
|
|
58
58
|
id: "other",
|
|
59
59
|
color: g.palette.categories.others || "",
|
|
60
60
|
label: l.saving_goal_other,
|
|
@@ -63,15 +63,15 @@ const D = 5, B = (i, l, g, c) => c.reduce((o, n) => {
|
|
|
63
63
|
}
|
|
64
64
|
return {
|
|
65
65
|
categoryData: r,
|
|
66
|
-
donutData:
|
|
66
|
+
donutData: c,
|
|
67
67
|
totalAmount: a
|
|
68
68
|
};
|
|
69
69
|
}, et = (i, l, g) => {
|
|
70
|
-
const
|
|
70
|
+
const m = i.filter(
|
|
71
71
|
(t) => t.guid === p.INCOME || t.parent_guid === p.INCOME
|
|
72
|
-
), o = l.filter((t) =>
|
|
72
|
+
), o = l.filter((t) => m.some((r) => r.guid === t.category_guid)).sort((t, r) => t.total - r.total).map((t, r) => ({
|
|
73
73
|
guid: t.category_guid,
|
|
74
|
-
name: i.find((
|
|
74
|
+
name: i.find((c) => c.guid === t.category_guid)?.name,
|
|
75
75
|
color: g[r],
|
|
76
76
|
categoryTotals: [],
|
|
77
77
|
amount: Math.abs(t.total)
|
|
@@ -93,13 +93,13 @@ const D = 5, B = (i, l, g, c) => c.reduce((o, n) => {
|
|
|
93
93
|
data: i,
|
|
94
94
|
isIncome: l = !1,
|
|
95
95
|
onSelected: g,
|
|
96
|
-
onViewTransactions:
|
|
96
|
+
onViewTransactions: m,
|
|
97
97
|
selectedId: o,
|
|
98
98
|
size: n = 150,
|
|
99
99
|
totalLabel: a,
|
|
100
100
|
variant: t = "mini"
|
|
101
101
|
}) => {
|
|
102
|
-
const { spending: r } = v(),
|
|
102
|
+
const { spending: r } = v(), c = A(), { isTablet: e } = V(), { announce: s, ariaLive: C } = R(), u = T.useMemo(
|
|
103
103
|
() => o ? i.categoryData.find((x) => x.guid === o) : void 0,
|
|
104
104
|
[o]
|
|
105
105
|
);
|
|
@@ -109,8 +109,8 @@ const D = 5, B = (i, l, g, c) => c.reduce((o, n) => {
|
|
|
109
109
|
s(`${u.name}: ${x}`);
|
|
110
110
|
}
|
|
111
111
|
}, [u, s, t]);
|
|
112
|
-
const E = i.donutData.length > 0 ? i.donutData : [{ id: "0", color:
|
|
113
|
-
|
|
112
|
+
const E = i.donutData.length > 0 ? i.donutData : [{ id: "0", color: c.palette.divider, value: 100 }], I = () => {
|
|
113
|
+
m?.(o);
|
|
114
114
|
}, w = e ? 32 : 48;
|
|
115
115
|
return /* @__PURE__ */ f(N, { children: [
|
|
116
116
|
C,
|
|
@@ -161,7 +161,7 @@ const D = 5, B = (i, l, g, c) => c.reduce((o, n) => {
|
|
|
161
161
|
] }) }) })
|
|
162
162
|
] });
|
|
163
163
|
}, rt = k(P), at = ({ data: i, onSelected: l, selectedId: g }) => {
|
|
164
|
-
const
|
|
164
|
+
const m = (o, n) => {
|
|
165
165
|
(o.key === "Enter" || o.key === " ") && (o.preventDefault(), l(n));
|
|
166
166
|
};
|
|
167
167
|
return /* @__PURE__ */ d(h, { gap: 8, height: "100%", justifyContent: "center", my: "auto", children: i.categoryData.map((o) => /* @__PURE__ */ f(
|
|
@@ -173,7 +173,7 @@ const D = 5, B = (i, l, g, c) => c.reduce((o, n) => {
|
|
|
173
173
|
direction: "row",
|
|
174
174
|
gap: 8,
|
|
175
175
|
onClick: () => l(o.guid),
|
|
176
|
-
onKeyDown: (n) =>
|
|
176
|
+
onKeyDown: (n) => m(n, o.guid),
|
|
177
177
|
role: "button",
|
|
178
178
|
sx: { cursor: "pointer" },
|
|
179
179
|
tabIndex: 0,
|
|
@@ -51,7 +51,7 @@ import { ChartsXAxis as Zn } from "@mui/x-charts/ChartsXAxis";
|
|
|
51
51
|
import { ChartsYAxis as Jn } from "@mui/x-charts/ChartsYAxis";
|
|
52
52
|
import { startOfMonth as Dt } from "date-fns/startOfMonth";
|
|
53
53
|
import { endOfMonth as It } from "date-fns/endOfMonth";
|
|
54
|
-
import { g as eo, S as to, b as no } from "../SpendingLegend-
|
|
54
|
+
import { g as eo, S as to, b as no } from "../SpendingLegend-BCnXkPCD.mjs";
|
|
55
55
|
import { formatISO as oo } from "date-fns/formatISO";
|
|
56
56
|
import { fromUnixTime as ro } from "date-fns/fromUnixTime";
|
|
57
57
|
import { startOfToday as st } from "date-fns/startOfToday";
|
|
@@ -8,7 +8,7 @@ import C from "@mui/material/Stack";
|
|
|
8
8
|
import N from "@mui/material/Tab";
|
|
9
9
|
import it from "@mui/material/Tabs";
|
|
10
10
|
import _t from "@mui/material/styles/useTheme";
|
|
11
|
-
import { g as rt, a as st, S as $, b as Y } from "../SpendingLegend-
|
|
11
|
+
import { g as rt, a as st, S as $, b as Y } from "../SpendingLegend-BCnXkPCD.mjs";
|
|
12
12
|
import { Text as T, Icon as bt } from "@mxenabled/mxui";
|
|
13
13
|
import { f as R } from "../NumberFormatting-QCaNwbjv.mjs";
|
|
14
14
|
import { u as I, l as A, d as lt, b as V, a as F, h as ct, g as yt } from "../hooks-BxkfR-Ff.mjs";
|