@mx-cartographer/experiences 9.4.65 → 9.4.67

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 (35) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/{transactions/components/shared/transactionlist → common/components}/ZeroState.es.js +11 -9
  3. package/dist/common/components/ZeroState.es.js.map +1 -0
  4. package/dist/common/components/index.d.ts +1 -0
  5. package/dist/common/index.es.js +44 -42
  6. package/dist/core/types/Beat.d.ts +2 -0
  7. package/dist/core/types/Beat.es.js.map +1 -1
  8. package/dist/core/types/Insights.d.ts +6 -0
  9. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.d.ts +17 -0
  10. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.es.js +39 -0
  11. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.es.js.map +1 -0
  12. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/index.d.ts +2 -0
  13. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/subscriptionBeats.d.ts +19 -0
  14. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/subscriptionBeats.es.js +12 -0
  15. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/subscriptionBeats.es.js.map +1 -0
  16. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionBlock.d.ts +23 -0
  17. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionBlock.es.js +21 -0
  18. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionBlock.es.js.map +1 -0
  19. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.d.ts +25 -0
  20. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.es.js +24 -0
  21. package/dist/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.es.js.map +1 -0
  22. package/dist/insights-v2/components/BaseLayout.es.js +16 -16
  23. package/dist/insights-v2/index.es.js +10 -10
  24. package/dist/insights-v2/mappings/actionBlocksKey.d.ts +1 -0
  25. package/dist/insights-v2/mappings/actionBlocksKey.es.js +2 -1
  26. package/dist/insights-v2/mappings/actionBlocksKey.es.js.map +1 -1
  27. package/dist/insights-v2/mappings/blocks.es.js +52 -45
  28. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  29. package/dist/transactions/components/shared/TransactionList.es.js +8 -8
  30. package/dist/transactions/components/shared/TransactionList.es.js.map +1 -1
  31. package/dist/trends/components/trendstable/TrendsTable.es.js +29 -25
  32. package/dist/trends/components/trendstable/TrendsTable.es.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/transactions/components/shared/transactionlist/ZeroState.es.js.map +0 -1
  35. /package/dist/{transactions/components/shared/transactionlist → common/components}/ZeroState.d.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [9.4.67] - 10-08-2026
2
+
3
+ - **FIXED** - Trends tabular view shows the shared zero-state message instead of the grid's default "No rows" when a table is empty MEW-4097
4
+
5
+ ## [9.4.66] - 10-08-2026
6
+
7
+ - **ADDED** - `recurring_transaction_block` (Recurring Transaction) action block: opens the Expense Details drawer for one recurring subscription, shared by the Upcoming Subscription and Subscription Price Increase beats. The drawer content is the recurring module's `RecurringTransactionDetails` (merchant, amount, next due date, schedule, account/category, past activity, mark as paid/unpaid, delete), so the block only resolves *which* subscription and hands off, as `TransactionDetailsBlock` does. The subscription is `primary_repeating_transaction_guid` (V2 payload, then the legacy beat envelope), else the beat's primary transaction is walked to the repeating transaction it is linked to. `usePrepare` loads recurring data on open through `loadRepeatingTransactionData`; when nothing resolves the drawer shows `recurring.no_activities`, never the generic error; when the open-time load fails it shows the feed's `ErrorCard` with a Try Again retry instead of an endless loader. The shared transaction filter is restored on close only if the details view actually narrowed it. (WEC-1428)
8
+ - **ADDED** - `InsightsPayload.primary_repeating_transaction_guid` and `Beat.primary_repeating_transaction_guid` (legacy pulse envelope). (WEC-1428)
9
+ - **ADDED** - Mock subscription beats (`mock/BlockBeatsData/RecurringTransactionBeats.ts`, pointing at the mock Netflix subscription), `InsightsV2/ActionBlock/RecurringTransactionBlock` stories, and `docs/action-blocks/` (index + block doc). (WEC-1428)
10
+
1
11
  ## [9.4.65] - 10-08-2026
2
12
 
3
13
  - **ADDED** - Insights V2 CTA action layer (`src/insights-v2/ctaActions`): a card CTA whose backend-named `action_key` (ditto `*_cta_action`, passed through by tupac on `primary_cta` / `secondary_cta`) has a registered step runs that step first: a typed store handler, `onSuccess` effects (`refreshBeat`), a client-only disable (`disabledWhen`), then its drawer or message. No key, or an unknown key, keeps the default (drawer if the CTA has a block, else post). First key: `dismiss_beat` (ConnectDiscoveredAccounts). Per-beat `ctaStatus` and `beatContext` on `InsightsV2Store`; `useBeatCtaActions` for the card and `useCtaHandler` for saves inside a drawer (WEC-1852)
@@ -1,20 +1,22 @@
1
- import { useGlobalCopyStore as n } from "../../../../common/context/hooks.es.js";
1
+ import { useGlobalCopyStore as i } from "../context/hooks.es.js";
2
2
  import "react";
3
- import { observer as i } from "mobx-react-lite";
4
- import c from "@mui/material/Stack";
3
+ import { observer as n } from "mobx-react-lite";
4
+ import s from "@mui/material/Stack";
5
5
  import { Text as o } from "@mxenabled/mxui";
6
- import { Receipt as s } from "@mxenabled/mx-icons";
6
+ import { Receipt as c } from "@mxenabled/mx-icons";
7
7
  import { jsx as t, jsxs as m } from "react/jsx-runtime";
8
- var p = ({ showIcon: e = !0, showSubtitle: a = !0 }) => {
9
- const { transactions: r } = n();
10
- return /* @__PURE__ */ m(c, {
8
+ var l = ({ showIcon: e = !0, showSubtitle: a = !0 }) => {
9
+ const { transactions: r } = i();
10
+ return /* @__PURE__ */ m(s, {
11
11
  alignItems: "center",
12
12
  gap: 12,
13
13
  height: "auto",
14
14
  mb: 24,
15
15
  mt: 24,
16
+ role: "status",
16
17
  children: [
17
- e && /* @__PURE__ */ t(s, {
18
+ e && /* @__PURE__ */ t(c, {
19
+ "aria-hidden": "true",
18
20
  color: "action",
19
21
  sx: { fontSize: 32 }
20
22
  }),
@@ -31,7 +33,7 @@ var p = ({ showIcon: e = !0, showSubtitle: a = !0 }) => {
31
33
  })
32
34
  ]
33
35
  });
34
- }, v = i(p);
36
+ }, v = n(l);
35
37
  export {
36
38
  v as default
37
39
  };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZeroState.es.js","names":[],"sources":["../../../src/common/components/ZeroState.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport { Receipt as ReceiptOutlinedIcon } from '@mxenabled/mx-icons'\n\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { useGlobalCopyStore } from '../context'\n\ninterface ZeroStateProps {\n showIcon?: boolean\n showSubtitle?: boolean\n}\n\nconst ZeroState: React.FC<ZeroStateProps> = ({ showIcon = true, showSubtitle = true }) => {\n const { transactions: copy } = useGlobalCopyStore()\n\n return (\n <Stack alignItems=\"center\" gap={12} height=\"auto\" mb={24} mt={24} role=\"status\">\n {showIcon && <ReceiptOutlinedIcon aria-hidden=\"true\" color=\"action\" sx={{ fontSize: 32 }} />}\n <Text bold={true} color=\"text.secondary\" variant=\"body2\">\n {copy.zero_state_no_transactions}\n </Text>\n {showSubtitle && (\n <Text color=\"text.secondary\" variant=\"caption\">\n {copy.zero_state_there_are_no_transactions}\n </Text>\n )}\n </Stack>\n )\n}\n\nexport default observer(ZeroState)\n"],"mappings":";;;;;;;AAgBA,IAAM,IAAA,CAAuC,EAAE,UAAA,IAAW,IAAM,cAAA,IAAe,GAAA,MAAW;AACxF,QAAM,EAAE,cAAc,EAAA,IAAS,EAAmB;AAElD,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,YAAW;AAAA,IAAS,KAAK;AAAA,IAAI,QAAO;AAAA,IAAO,IAAI;AAAA,IAAI,IAAI;AAAA,IAAI,MAAK;AAAA,IAAvE,UAAA;AAAA,MACG,KAAY,gBAAA,EAAC,GAAD;AAAA,QAAqB,eAAY;AAAA,QAAO,OAAM;AAAA,QAAS,IAAI,EAAE,UAAU,GAAG;AAAA,MAAI,CAAA;AAAA,MAC3F,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,OAAM;AAAA,QAAiB,SAAQ;AAAA,QAC9C,UAAA,EAAK;AAAA,MACF,CAAA;AAAA,MACL,KACC,gBAAA,EAAC,GAAD;AAAA,QAAM,OAAM;AAAA,QAAiB,SAAQ;AAAA,QAClC,UAAA,EAAK;AAAA,MACF,CAAA;AAAA,IAEH;AAAA;AAEX,GAEA,IAAe,EAAS,CAAS"}
@@ -19,6 +19,7 @@ export { default as SelectionBox } from './SelectionBox';
19
19
  export { default as TabContentContainer } from './TabContentContainer';
20
20
  export { default as IconBacking } from './IconBacking';
21
21
  export { default as DataRow } from './DataRow';
22
+ export { default as ZeroState } from './ZeroState';
22
23
  export { default as InformationTooltip } from './InformationTooltip';
23
24
  export { ConnectCard } from './ConnectCard';
24
25
  export { CurrencyText } from './CurrencyText';
@@ -2,11 +2,11 @@ import { buildDynamicCopy as r, buildPluralCopy as t } from "../core/utils/Local
2
2
  import m, { CalendarSelectionTypes as i } from "./components/calendar/Calendar.es.js";
3
3
  import a from "./components/charts/StatusBar.es.js";
4
4
  import p from "./components/charts/Donut.es.js";
5
- import f from "./hooks/useAccountDisplayName.es.js";
5
+ import u from "./hooks/useAccountDisplayName.es.js";
6
6
  import { useCombineEvents as C, useCombinePageviews as S } from "./hooks/useCombineEvents.es.js";
7
7
  import { GlobalDataContext as c, GlobalDataProvider as T } from "./context/GlobalDataProvider.es.js";
8
8
  import { WidgetContainerContext as E, WidgetContainerProvider as D } from "./context/WidgetContainerProvider.es.js";
9
- import { useAccountStore as _, useActionContext as N, useAppConfig as A, useBudgetsStore as y, useCashflowStore as P, useCategoryStore as b, useDebtStore as O, useError as G, useEvent as W, useFinstrongStore as L, useGlobalCopyStore as R, useGlobalStore as U, useGlobalUiStore as v, useGoalStore as B, useHelpStore as h, useHoldingStore as w, useInsightsV2Store as x, useLoad as M, useMerchantStore as Y, useNetWorthStore as H, useNotificationStore as F, usePageView as z, useRecurringTransactionsStore as V, useSettingsStore as k, useTransactionStore as q, useTrendsStore as K, useUserStore as Z, useWidgetContainerProvider as j } from "./context/hooks.es.js";
9
+ import { useAccountStore as _, useActionContext as N, useAppConfig as A, useBudgetsStore as y, useCashflowStore as P, useCategoryStore as b, useDebtStore as O, useError as G, useEvent as W, useFinstrongStore as L, useGlobalCopyStore as R, useGlobalStore as U, useGlobalUiStore as v, useGoalStore as B, useHelpStore as h, useHoldingStore as w, useInsightsV2Store as x, useLoad as M, useMerchantStore as Y, useNetWorthStore as H, useNotificationStore as F, usePageView as z, useRecurringTransactionsStore as V, useSettingsStore as Z, useTransactionStore as k, useTrendsStore as q, useUserStore as K, useWidgetContainerProvider as j } from "./context/hooks.es.js";
10
10
  import { useInsightsEnabled as Q } from "./hooks/useInsightsEnabled.es.js";
11
11
  import { useScreenSize as $ } from "./hooks/useScreenSize.es.js";
12
12
  import ro from "./hooks/usePrevious.es.js";
@@ -14,7 +14,7 @@ import { useWidgetHeaderStyles as eo } from "./hooks/useWidgetHeaderStyles.es.js
14
14
  import { useWidgetLoadTimer as io } from "./hooks/useWidgetLoadTimer.es.js";
15
15
  import ao from "./components/dialog/Dialog.es.js";
16
16
  import po from "./components/drawer/Drawer.es.js";
17
- import fo from "./components/daterangeselector/DateRangeSelector.es.js";
17
+ import uo from "./components/daterangeselector/DateRangeSelector.es.js";
18
18
  import { ANALYTICS_EVENTS as Co } from "./constants/Analytics.es.js";
19
19
  import { CONNECTIONS_WIDGET_ID as go, CONNECT_WIDGET_ID as co, MemberConnectionStatus as To } from "./constants/Connect.es.js";
20
20
  import { formatCurrency as Do, formatOrdinal as Io, formatPercentage as _o, generateEqualIntervals as No, getCurrencyCodes as Ao, getPluralRules as yo } from "../core/utils/NumberFormatting.es.js";
@@ -25,8 +25,8 @@ import { LOADING_STATUS as Bo } from "./constants/SpendingPlan.es.js";
25
25
  import { DEFAULT_DONUT_SIZE as wo, DEFAULT_STROKE_WIDTH as xo } from "./constants/Donut.es.js";
26
26
  import { Sizes as Yo, TOUCH_TARGET as Ho } from "./constants/Sizes.es.js";
27
27
  import zo from "./components/donuts/MultiSegmentDonut.es.js";
28
- import ko from "./components/donuts/SingleSegmentDonut.es.js";
29
- import Ko from "./components/ErrorBoundary.es.js";
28
+ import Zo from "./components/donuts/SingleSegmentDonut.es.js";
29
+ import qo from "./components/ErrorBoundary.es.js";
30
30
  import jo from "./components/Error.es.js";
31
31
  import Qo from "./components/MicroWidgetContainer.es.js";
32
32
  import $o from "./components/MiniWidgetContainer.es.js";
@@ -35,57 +35,58 @@ import er from "./components/Loader.es.js";
35
35
  import { WidgetContainer as ir } from "./components/WidgetContainer.es.js";
36
36
  import ar from "./components/ConnectDrawer.es.js";
37
37
  import pr from "./components/CurrencyDialog.es.js";
38
- import fr from "./components/CurrencyInput.es.js";
38
+ import ur from "./components/CurrencyInput.es.js";
39
39
  import Cr from "./components/ResponsiveButton.es.js";
40
40
  import gr from "./components/SearchBox.es.js";
41
41
  import Tr from "./components/SelectionBox.es.js";
42
42
  import Er from "./components/TabContentContainer.es.js";
43
43
  import Ir from "./components/IconBacking.es.js";
44
44
  import Nr from "./components/DataRow.es.js";
45
- import yr from "./components/InformationTooltip.es.js";
46
- import { ConnectCard as br } from "./components/ConnectCard.es.js";
47
- import { CurrencyText as Gr } from "./components/CurrencyText.es.js";
48
- import { EmptyState as Lr } from "./components/EmptyState.es.js";
49
- import { ListItemAction as Ur } from "./components/ListItemAction.es.js";
50
- import { ListItemRow as Br } from "./components/ListItemRow.es.js";
51
- import { ListItemWrapper as wr } from "./components/ListItemWrapper.es.js";
52
- import { Select as Mr } from "./components/Select.es.js";
53
- import { ToggleButtonListItem as Hr } from "./components/listitems/ToggleButtonListItem.es.js";
54
- import { ToggleListItem as zr } from "./components/listitems/ToggleListItem.es.js";
55
- import { analyticsSession as kr } from "./utils/Analytics.es.js";
56
- import { getClientComponentOverrides as Kr, getClientCustomizations as Zr, getClientPaletteOptions as jr, getClientTheme as Jr } from "./utils/Theme.es.js";
45
+ import yr from "./components/ZeroState.es.js";
46
+ import br from "./components/InformationTooltip.es.js";
47
+ import { ConnectCard as Gr } from "./components/ConnectCard.es.js";
48
+ import { CurrencyText as Lr } from "./components/CurrencyText.es.js";
49
+ import { EmptyState as Ur } from "./components/EmptyState.es.js";
50
+ import { ListItemAction as Br } from "./components/ListItemAction.es.js";
51
+ import { ListItemRow as wr } from "./components/ListItemRow.es.js";
52
+ import { ListItemWrapper as Mr } from "./components/ListItemWrapper.es.js";
53
+ import { Select as Hr } from "./components/Select.es.js";
54
+ import { ToggleButtonListItem as zr } from "./components/listitems/ToggleButtonListItem.es.js";
55
+ import { ToggleListItem as Zr } from "./components/listitems/ToggleListItem.es.js";
56
+ import { analyticsSession as qr } from "./utils/Analytics.es.js";
57
+ import { getClientComponentOverrides as jr, getClientCustomizations as Jr, getClientPaletteOptions as Qr, getClientTheme as Xr } from "./utils/Theme.es.js";
57
58
  export {
58
59
  Co as ANALYTICS_EVENTS,
59
60
  go as CONNECTIONS_WIDGET_ID,
60
61
  co as CONNECT_WIDGET_ID,
61
62
  m as Calendar,
62
63
  i as CalendarSelectionTypes,
63
- br as ConnectCard,
64
+ Gr as ConnectCard,
64
65
  ar as ConnectDrawer,
65
66
  pr as CurrencyDialog,
66
- fr as CurrencyInput,
67
- Gr as CurrencyText,
67
+ ur as CurrencyInput,
68
+ Lr as CurrencyText,
68
69
  wo as DEFAULT_DONUT_SIZE,
69
70
  xo as DEFAULT_STROKE_WIDTH,
70
71
  Nr as DataRow,
71
- fo as DateRangeSelector,
72
+ uo as DateRangeSelector,
72
73
  ao as Dialog,
73
74
  p as Donut,
74
75
  po as Drawer,
75
- Lr as EmptyState,
76
+ Ur as EmptyState,
76
77
  jo as Error,
77
- Ko as ErrorBoundary,
78
+ qo as ErrorBoundary,
78
79
  rr as GlobalAccountFilter,
79
80
  c as GlobalDataContext,
80
81
  T as GlobalDataProvider,
81
82
  bo as GlobalStore,
82
83
  Go as INCOME_ACCOUNT_TYPES,
83
84
  Ir as IconBacking,
84
- yr as InformationTooltip,
85
+ br as InformationTooltip,
85
86
  Bo as LOADING_STATUS,
86
- Ur as ListItemAction,
87
- Br as ListItemRow,
88
- wr as ListItemWrapper,
87
+ Br as ListItemAction,
88
+ wr as ListItemRow,
89
+ Mr as ListItemWrapper,
89
90
  er as Loader,
90
91
  To as MemberConnectionStatus,
91
92
  Qo as MicroWidgetContainer,
@@ -96,32 +97,33 @@ export {
96
97
  Cr as ResponsiveButton,
97
98
  Lo as SPENDING_ACCOUNT_TYPES,
98
99
  gr as SearchBox,
99
- Mr as Select,
100
+ Hr as Select,
100
101
  Tr as SelectionBox,
101
- ko as SingleSegmentDonut,
102
+ Zo as SingleSegmentDonut,
102
103
  Yo as Sizes,
103
104
  a as StatusBar,
104
105
  Ho as TOUCH_TARGET,
105
106
  Er as TabContentContainer,
106
- Hr as ToggleButtonListItem,
107
- zr as ToggleListItem,
107
+ zr as ToggleButtonListItem,
108
+ Zr as ToggleListItem,
108
109
  ir as WidgetContainer,
109
110
  E as WidgetContainerContext,
110
111
  D as WidgetContainerProvider,
111
- kr as analyticsSession,
112
+ yr as ZeroState,
113
+ qr as analyticsSession,
112
114
  r as buildDynamicCopy,
113
115
  t as buildPluralCopy,
114
116
  Do as formatCurrency,
115
117
  Io as formatOrdinal,
116
118
  _o as formatPercentage,
117
119
  No as generateEqualIntervals,
118
- Kr as getClientComponentOverrides,
119
- Zr as getClientCustomizations,
120
- jr as getClientPaletteOptions,
121
- Jr as getClientTheme,
120
+ jr as getClientComponentOverrides,
121
+ Jr as getClientCustomizations,
122
+ Qr as getClientPaletteOptions,
123
+ Xr as getClientTheme,
122
124
  Ao as getCurrencyCodes,
123
125
  yo as getPluralRules,
124
- f as useAccountDisplayName,
126
+ u as useAccountDisplayName,
125
127
  _ as useAccountStore,
126
128
  N as useActionContext,
127
129
  A as useAppConfig,
@@ -150,10 +152,10 @@ export {
150
152
  ro as usePrevious,
151
153
  V as useRecurringTransactionsStore,
152
154
  $ as useScreenSize,
153
- k as useSettingsStore,
154
- q as useTransactionStore,
155
- K as useTrendsStore,
156
- Z as useUserStore,
155
+ Z as useSettingsStore,
156
+ k as useTransactionStore,
157
+ q as useTrendsStore,
158
+ K as useUserStore,
157
159
  j as useWidgetContainerProvider,
158
160
  eo as useWidgetHeaderStyles,
159
161
  io as useWidgetLoadTimer
@@ -42,6 +42,8 @@ export interface Beat {
42
42
  primary_category_guid?: string | null;
43
43
  primary_goal_guid?: string | null;
44
44
  primary_merchant_guid?: string | null;
45
+ /** Legacy pulse envelope: the subscription an Upcoming Subscription beat is about. */
46
+ primary_repeating_transaction_guid?: string | null;
45
47
  primary_scheduled_payment_guid?: string | null;
46
48
  primary_transaction?: Transaction;
47
49
  primary_transaction_guid?: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"Beat.es.js","names":[],"sources":["../../../src/core/types/Beat.ts"],"sourcesContent":["import { Account } from './Account'\nimport { InsightsPayload } from './Insights'\nimport { Transaction } from './Transaction'\n\nexport interface Beat {\n account_guids: string[] | []\n active_at?: string | number\n associated_transaction_guid?: string | null\n call_to_action?: string | null\n category_guids?: string[] | []\n created_at?: string | number\n cta_clicked_at?: number | null\n data_series: DataSeries\n description?: string\n digest?: string\n dismissed_at?: number | null\n displayed_at?: string | null\n errors?: any\n guid: string\n has_been_displayed: boolean\n html_description?: string\n html_in_description_cta?: string\n html_micro_call_to_action?: string\n html_micro_description?: string\n html_micro_title?: string\n html_short_title?: string\n html_title: string\n icon_color?: string | null\n icon_type?: number | null\n in_description_cta?: string | null\n is_dismissed: boolean\n is_obsolete: boolean\n is_refreshable: boolean\n is_sampled: boolean\n merchant_guids: string[] | []\n metadata?: string | null\n micro_call_to_action?: string | null\n micro_description?: string | null\n micro_title?: string | null\n payload: any\n primary_account?: Account\n primary_account_guid?: string | null\n primary_category_guid?: string | null\n primary_goal_guid?: string | null\n primary_merchant_guid?: string | null\n primary_scheduled_payment_guid?: string | null\n primary_transaction?: Transaction\n primary_transaction_guid?: string | null\n power_action_completed_at?: string | null\n power_action_has_been_completed?: boolean\n scheduled_payment_guids: string[] | []\n short_title?: string | null\n supporting_action?: string | null\n template: string\n title: string\n transaction_guids: string[] | []\n transactions?: Transaction[]\n user_guid: string\n user_verification: UserVerification\n\n // Added for UI: optional institution info for displaying logos\n institutionGuid?: string | null\n institutionName?: string | null\n\n insights_payload?: InsightsPayload\n /**\n * Written by firefly, never by a template: true when the insight's Insights 2.0 flag is on (or\n * the envelope is present). It gates which renderer draws the beat — see `resolveInsightRender`.\n * Absent on an older firefly or on cortex, which renders the legacy path unchanged.\n */\n is_insights_v2?: boolean\n}\n\nexport interface DataSeries {\n names?: string[]\n types?: string[]\n data?: any[]\n}\n\nexport enum UserVerification {\n UNKNOWN = 0,\n CORRECT = 1,\n INCORRECT = 2,\n}\n"],"mappings":"AA+EA,IAAY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,YAAA,CAAA,IAAA;AACF,GAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"Beat.es.js","names":[],"sources":["../../../src/core/types/Beat.ts"],"sourcesContent":["import { Account } from './Account'\nimport { InsightsPayload } from './Insights'\nimport { Transaction } from './Transaction'\n\nexport interface Beat {\n account_guids: string[] | []\n active_at?: string | number\n associated_transaction_guid?: string | null\n call_to_action?: string | null\n category_guids?: string[] | []\n created_at?: string | number\n cta_clicked_at?: number | null\n data_series: DataSeries\n description?: string\n digest?: string\n dismissed_at?: number | null\n displayed_at?: string | null\n errors?: any\n guid: string\n has_been_displayed: boolean\n html_description?: string\n html_in_description_cta?: string\n html_micro_call_to_action?: string\n html_micro_description?: string\n html_micro_title?: string\n html_short_title?: string\n html_title: string\n icon_color?: string | null\n icon_type?: number | null\n in_description_cta?: string | null\n is_dismissed: boolean\n is_obsolete: boolean\n is_refreshable: boolean\n is_sampled: boolean\n merchant_guids: string[] | []\n metadata?: string | null\n micro_call_to_action?: string | null\n micro_description?: string | null\n micro_title?: string | null\n payload: any\n primary_account?: Account\n primary_account_guid?: string | null\n primary_category_guid?: string | null\n primary_goal_guid?: string | null\n primary_merchant_guid?: string | null\n /** Legacy pulse envelope: the subscription an Upcoming Subscription beat is about. */\n primary_repeating_transaction_guid?: string | null\n primary_scheduled_payment_guid?: string | null\n primary_transaction?: Transaction\n primary_transaction_guid?: string | null\n power_action_completed_at?: string | null\n power_action_has_been_completed?: boolean\n scheduled_payment_guids: string[] | []\n short_title?: string | null\n supporting_action?: string | null\n template: string\n title: string\n transaction_guids: string[] | []\n transactions?: Transaction[]\n user_guid: string\n user_verification: UserVerification\n\n // Added for UI: optional institution info for displaying logos\n institutionGuid?: string | null\n institutionName?: string | null\n\n insights_payload?: InsightsPayload\n /**\n * Written by firefly, never by a template: true when the insight's Insights 2.0 flag is on (or\n * the envelope is present). It gates which renderer draws the beat — see `resolveInsightRender`.\n * Absent on an older firefly or on cortex, which renders the legacy path unchanged.\n */\n is_insights_v2?: boolean\n}\n\nexport interface DataSeries {\n names?: string[]\n types?: string[]\n data?: any[]\n}\n\nexport enum UserVerification {\n UNKNOWN = 0,\n CORRECT = 1,\n INCORRECT = 2,\n}\n"],"mappings":"AAiFA,IAAY,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,UAAA,CAAA,IAAA,WACA,EAAA,EAAA,YAAA,CAAA,IAAA;AACF,GAAA,CAAA,CAAA"}
@@ -95,6 +95,12 @@ export interface InsightsPayload {
95
95
  primary_transaction_guid?: string | null;
96
96
  primary_category_guid?: string | null;
97
97
  primary_merchant_guid?: string | null;
98
+ /**
99
+ * V2: the repeating transaction a subscription beat is about (Upcoming Subscription, Subscription
100
+ * Price Increase). Read by `recurring_transaction_block`, see
101
+ * `actionBlocks/RecurringTransactionBlock/subscriptionBeats.ts`.
102
+ */
103
+ primary_repeating_transaction_guid?: string | null;
98
104
  }
99
105
  export interface Legends {
100
106
  label: string;
@@ -0,0 +1,17 @@
1
+ import { ActionBlockProps } from '../../mappings/blocks';
2
+ /**
3
+ * Expense Details drawer content for one recurring subscription (WEC-1428), shared by the Upcoming
4
+ * Subscription (WEC-1469) and Subscription Price Increase (WEC-1470) beats.
5
+ *
6
+ * The detail rendering (merchant header, next-due card, account/category/schedule rows, past
7
+ * activity, mark-as-paid/unpaid, delete) all lives in the recurring module's
8
+ * `RecurringTransactionDetails`, the same component behind the recurring widget's Expense Details
9
+ * drawer. This block's job is only to resolve *which* subscription (`subscriptionBeats.ts`) and hand
10
+ * off, exactly as `TransactionDetailsBlock` does with `TransactionDetails`.
11
+ *
12
+ * `observer` is required: the resolved subscription comes from RecurringTransactionsStore, and
13
+ * `usePrepare` may still be loading it when this first renders.
14
+ */
15
+ export declare const RecurringTransactionBlock: (({ beat, }: ActionBlockProps) => import("react/jsx-runtime").JSX.Element) & {
16
+ displayName: string;
17
+ };
@@ -0,0 +1,39 @@
1
+ import { useGlobalCopyStore as R, useInsightsV2Store as g, useTransactionStore as T } from "../../../common/context/hooks.es.js";
2
+ import v from "../../../common/components/Loader.es.js";
3
+ import { RecurringTransactionDetails as x } from "../../../recurringtransactions/components/RecurringTransactionDetails.es.js";
4
+ import { ErrorCard as y } from "../../components/ErrorCard.es.js";
5
+ import { useRecurringTransactionBlock as D } from "./useRecurringTransactionBlock.es.js";
6
+ import { useRecurringTransactionLoad as L } from "./useRecurringTransactionPrepare.es.js";
7
+ import r from "react";
8
+ import { observer as B } from "mobx-react-lite";
9
+ import { Text as E } from "@mxenabled/mxui";
10
+ import { jsx as t } from "react/jsx-runtime";
11
+ var O = B(function({ beat: f }) {
12
+ const { closeActionDrawer: l } = g(), { recurring: m } = R(), { filter: d, setFilter: n } = T(), { hasLoadError: i, isLoading: c, repeatingTransaction: o } = D(f), p = L(), e = r.useRef(null);
13
+ e.current === null && (e.current = { ...d });
14
+ const s = r.useRef(n), a = r.useRef(!1), u = !c && !i && o !== void 0;
15
+ return s.current = n, r.useEffect(() => {
16
+ u && (a.current = !0);
17
+ }, [u]), r.useEffect(() => () => {
18
+ a.current && e.current && s.current(e.current);
19
+ }, []), c ? /* @__PURE__ */ t(v, {}) : i ? /* @__PURE__ */ t(y, { onRetry: () => {
20
+ p();
21
+ } }) : o ? /* @__PURE__ */ t(x, {
22
+ onDeleted: l,
23
+ recurringTransaction: o,
24
+ selectedRecurrence: null
25
+ }) : /* @__PURE__ */ t(E, {
26
+ color: "text.secondary",
27
+ sx: {
28
+ m: 24,
29
+ textAlign: "center"
30
+ },
31
+ variant: "body1",
32
+ children: m.no_activities
33
+ });
34
+ });
35
+ export {
36
+ O as RecurringTransactionBlock
37
+ };
38
+
39
+ //# sourceMappingURL=RecurringTransactionBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecurringTransactionBlock.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.tsx"],"sourcesContent":["import React from 'react'\n\nimport { Text } from '@mxenabled/mxui'\nimport { observer } from 'mobx-react-lite'\n\nimport {\n Loader,\n useGlobalCopyStore,\n useInsightsV2Store,\n useTransactionStore,\n} from '../../../common'\nimport type { TransactionFilter } from '../../../core/stores/TransactionStore'\nimport { RecurringTransactionDetails } from '../../../recurringtransactions/components/RecurringTransactionDetails'\nimport { ErrorCard } from '../../components/ErrorCard'\nimport type { ActionBlockProps } from '../../mappings/blocks'\n\nimport { useRecurringTransactionBlock } from './useRecurringTransactionBlock'\nimport { useRecurringTransactionLoad } from './useRecurringTransactionPrepare'\n\n/**\n * Expense Details drawer content for one recurring subscription (WEC-1428), shared by the Upcoming\n * Subscription (WEC-1469) and Subscription Price Increase (WEC-1470) beats.\n *\n * The detail rendering (merchant header, next-due card, account/category/schedule rows, past\n * activity, mark-as-paid/unpaid, delete) all lives in the recurring module's\n * `RecurringTransactionDetails`, the same component behind the recurring widget's Expense Details\n * drawer. This block's job is only to resolve *which* subscription (`subscriptionBeats.ts`) and hand\n * off, exactly as `TransactionDetailsBlock` does with `TransactionDetails`.\n *\n * `observer` is required: the resolved subscription comes from RecurringTransactionsStore, and\n * `usePrepare` may still be loading it when this first renders.\n */\nexport const RecurringTransactionBlock = observer(function RecurringTransactionBlock({\n beat,\n}: ActionBlockProps) {\n const { closeActionDrawer } = useInsightsV2Store()\n const { recurring: copy } = useGlobalCopyStore()\n const { filter, setFilter } = useTransactionStore()\n const { hasLoadError, isLoading, repeatingTransaction } = useRecurringTransactionBlock(beat)\n const retryLoad = useRecurringTransactionLoad()\n\n // `RecurringTransactionDetails` narrows the shared `TransactionStore.filter` to this one\n // subscription (90-day window + guid predicate) and never restores it. Inside the recurring widget\n // that is fine, but a Transactions widget on the same page would be left showing only this\n // subscription's charges after the drawer closes. The runner mounts this block on open and\n // unmounts it on close, so the filter is put back on unmount, with two guards:\n // - the snapshot is taken BY VALUE on the first render (the store's `filter` is a live observable\n // object, so holding the reference would hold whatever it was later changed to);\n // - the restore only runs if the details view actually mounted. While loading, on a failed load\n // or when nothing resolved, this block changed nothing and must not overwrite a filter some\n // other widget may have set in the meantime.\n const filterBeforeOpen = React.useRef<TransactionFilter | null>(null)\n\n if (filterBeforeOpen.current === null) filterBeforeOpen.current = { ...filter }\n\n const setFilterRef = React.useRef(setFilter)\n const didRenderDetails = React.useRef(false)\n const isDetailsRendered = !isLoading && !hasLoadError && repeatingTransaction !== undefined\n\n setFilterRef.current = setFilter\n\n React.useEffect(() => {\n if (isDetailsRendered) didRenderDetails.current = true\n }, [isDetailsRendered])\n\n React.useEffect(\n () => () => {\n if (didRenderDetails.current && filterBeforeOpen.current) {\n setFilterRef.current(filterBeforeOpen.current)\n }\n },\n [],\n )\n\n if (isLoading) return <Loader />\n\n // The open-time load finished without data (API failure, reported through the store). Offer the\n // feed's standard error card with a retry rather than leaving the loader up forever.\n if (hasLoadError) return <ErrorCard onRetry={() => void retryLoad()} />\n\n // Loading finished and the beat still resolves to nothing (deleted, never detected, or a beat that\n // names none). Say so in the recurring module's own words rather than the generic error drawer.\n if (!repeatingTransaction) {\n return (\n <Text color=\"text.secondary\" sx={{ m: 24, textAlign: 'center' }} variant=\"body1\">\n {copy.no_activities}\n </Text>\n )\n }\n\n return (\n <RecurringTransactionDetails\n // Deleting the subscription from inside the drawer leaves nothing to show; close it, as the\n // recurring widget's own drawer does.\n onDeleted={closeActionDrawer}\n recurringTransaction={repeatingTransaction}\n // No specific occurrence was tapped (the CTA opens the subscription itself), so the next-due\n // card falls back to the subscription's next upcoming date.\n selectedRecurrence={null}\n />\n )\n})\n"],"mappings":";;;;;;;;;;AAgCA,IAAa,IAA4B,EAAS,SAAmC,EACnF,MAAA,EAAA,GACmB;AACnB,QAAM,EAAE,mBAAA,EAAA,IAAsB,EAAmB,GAC3C,EAAE,WAAW,EAAA,IAAS,EAAmB,GACzC,EAAE,QAAA,GAAQ,WAAA,EAAA,IAAc,EAAoB,GAC5C,EAAE,cAAA,GAAc,WAAA,GAAW,sBAAA,EAAA,IAAyB,EAA6B,CAAI,GACrF,IAAY,EAA4B,GAYxC,IAAmB,EAAM,OAAiC,IAAI;AAEpE,EAAI,EAAiB,YAAY,SAAM,EAAiB,UAAU,EAAE,GAAG,EAAO;AAE9E,QAAM,IAAe,EAAM,OAAO,CAAS,GACrC,IAAmB,EAAM,OAAO,EAAK,GACrC,IAAoB,CAAC,KAAa,CAAC,KAAgB,MAAyB;AAiBlF,SAfA,EAAa,UAAU,GAEvB,EAAM,UAAA,MAAgB;AACpB,IAAI,MAAmB,EAAiB,UAAU;AAAA,EACpD,GAAG,CAAC,CAAiB,CAAC,GAEtB,EAAM,UAAA,MAAA,MACQ;AACV,IAAI,EAAiB,WAAW,EAAiB,WAC/C,EAAa,QAAQ,EAAiB,OAAO;AAAA,EAEjD,GACA,CAAC,CACH,GAEI,IAAkB,gBAAA,EAAC,GAAD,CAAS,CAAA,IAI3B,IAAqB,gBAAA,EAAC,GAAD,EAAW,SAAA,MAAA;AAAe,IAAK,EAAU;AAAA,IAAI,CAAA,IAIjE,IASH,gBAAA,EAAC,GAAD;AAAA,IAGE,WAAW;AAAA,IACX,sBAAsB;AAAA,IAGtB,oBAAoB;AAAA,EACrB,CAAA,IAfC,gBAAA,EAAC,GAAD;AAAA,IAAM,OAAM;AAAA,IAAiB,IAAI;AAAA,MAAE,GAAG;AAAA,MAAI,WAAW;AAAA,IAAS;AAAA,IAAG,SAAQ;AAAA,IACtE,UAAA,EAAK;AAAA,EACF,CAAA;AAeZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { RecurringTransactionBlock } from './RecurringTransactionBlock';
2
+ export { useRecurringTransactionPrepare } from './useRecurringTransactionPrepare';
@@ -0,0 +1,19 @@
1
+ import { Beat, RepeatingTransaction, Transaction } from '../../../core';
2
+ interface SubscriptionContext {
3
+ /** `recurringTransactionsStore.repeatingTransactions`, with linked transactions when augmented. */
4
+ repeatingTransactions: RepeatingTransaction[];
5
+ /** `transactionStore.transactions`, consulted to walk a transaction to its repeating transaction. */
6
+ transactions: Transaction[];
7
+ }
8
+ /**
9
+ * Which repeating transaction the beat is about, or `undefined` if it cannot tell.
10
+ *
11
+ * The direct pointer wins: V2 carries `primary_repeating_transaction_guid` on the payload beside the
12
+ * other `primary_*` guids, and the legacy pulse envelope carries it on the beat (Upcoming
13
+ * Subscription, WEC-1469). Failing that, the beat's primary transaction is walked to the repeating
14
+ * transaction it is linked to (Subscription Price Increase, WEC-1470, whose pulse fixture names only
15
+ * `primary_transaction`): the hydrated `beat.primary_transaction` first, then the transaction store,
16
+ * then each repeating transaction's own linked `transactions`.
17
+ */
18
+ export declare const resolveSubscriptionGuid: (beat: Beat, { repeatingTransactions, transactions }: SubscriptionContext) => string | undefined;
19
+ export {};
@@ -0,0 +1,12 @@
1
+ var s = (i, { repeatingTransactions: t, transactions: o }) => {
2
+ const a = i.insights_payload?.primary_repeating_transaction_guid || i.primary_repeating_transaction_guid;
3
+ if (a) return a;
4
+ const r = i.insights_payload?.primary_transaction_guid || i.primary_transaction?.guid || i.primary_transaction_guid;
5
+ if (r)
6
+ return (i.primary_transaction?.guid === r ? i.primary_transaction : void 0)?.repeating_transaction_guid || o.find((n) => n.guid === r)?.repeating_transaction_guid || t.find((n) => n.transactions?.some((d) => d.guid === r))?.guid || void 0;
7
+ };
8
+ export {
9
+ s as resolveSubscriptionGuid
10
+ };
11
+
12
+ //# sourceMappingURL=subscriptionBeats.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptionBeats.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/RecurringTransactionBlock/subscriptionBeats.ts"],"sourcesContent":["import type { Beat, RepeatingTransaction, Transaction } from '../../../core'\n\ninterface SubscriptionContext {\n /** `recurringTransactionsStore.repeatingTransactions`, with linked transactions when augmented. */\n repeatingTransactions: RepeatingTransaction[]\n /** `transactionStore.transactions`, consulted to walk a transaction to its repeating transaction. */\n transactions: Transaction[]\n}\n\n/**\n * Which repeating transaction the beat is about, or `undefined` if it cannot tell.\n *\n * The direct pointer wins: V2 carries `primary_repeating_transaction_guid` on the payload beside the\n * other `primary_*` guids, and the legacy pulse envelope carries it on the beat (Upcoming\n * Subscription, WEC-1469). Failing that, the beat's primary transaction is walked to the repeating\n * transaction it is linked to (Subscription Price Increase, WEC-1470, whose pulse fixture names only\n * `primary_transaction`): the hydrated `beat.primary_transaction` first, then the transaction store,\n * then each repeating transaction's own linked `transactions`.\n */\nexport const resolveSubscriptionGuid = (\n beat: Beat,\n { repeatingTransactions, transactions }: SubscriptionContext,\n): string | undefined => {\n const direct =\n beat.insights_payload?.primary_repeating_transaction_guid ||\n beat.primary_repeating_transaction_guid\n\n if (direct) return direct\n\n const transactionGuid =\n beat.insights_payload?.primary_transaction_guid ||\n beat.primary_transaction?.guid ||\n beat.primary_transaction_guid\n\n if (!transactionGuid) return undefined\n\n const snapshot =\n beat.primary_transaction?.guid === transactionGuid ? beat.primary_transaction : undefined\n\n return (\n snapshot?.repeating_transaction_guid ||\n transactions.find((transaction) => transaction.guid === transactionGuid)\n ?.repeating_transaction_guid ||\n repeatingTransactions.find((repeating) =>\n repeating.transactions?.some((transaction) => transaction.guid === transactionGuid),\n )?.guid ||\n undefined\n )\n}\n"],"mappings":"AAmBA,IAAa,IAAA,CACX,GACA,EAAE,uBAAA,GAAuB,cAAA,EAAA,MACF;AACvB,QAAM,IACJ,EAAK,kBAAkB,sCACvB,EAAK;AAEP,MAAI,EAAQ,QAAO;AAEnB,QAAM,IACJ,EAAK,kBAAkB,4BACvB,EAAK,qBAAqB,QAC1B,EAAK;AAEP,MAAK;AAKL,YAFE,EAAK,qBAAqB,SAAS,IAAkB,EAAK,sBAAsB,SAGtE,8BACV,EAAa,KAAA,CAAM,MAAgB,EAAY,SAAS,CAAe,GACnE,8BACJ,EAAsB,KAAA,CAAM,MAC1B,EAAU,cAAc,KAAA,CAAM,MAAgB,EAAY,SAAS,CAAe,CACpF,GAAG,QACH;AAEJ"}
@@ -0,0 +1,23 @@
1
+ import { Beat, RepeatingTransaction } from '../../../core';
2
+ export interface RecurringTransactionBlockState {
3
+ /** True when the open-time load finished without leaving the store loaded; the block offers a retry. */
4
+ hasLoadError: boolean;
5
+ /** True until the recurring store has loaded; the block shows a loader instead of an empty state. */
6
+ isLoading: boolean;
7
+ /** `undefined` once loading finishes means the subscription could not be resolved. */
8
+ repeatingTransaction?: RepeatingTransaction;
9
+ }
10
+ /**
11
+ * Resolves which repeating transaction this drawer is about.
12
+ *
13
+ * The guid comes from the beat (`resolveSubscriptionGuid`), then is looked up in
14
+ * `RecurringTransactionsStore` rather than rebuilt from the beat, because the Expense Details view
15
+ * edits (payment schedule, mark as paid, delete) must write through to the same store object the
16
+ * recurring widget renders.
17
+ *
18
+ * `detailedRepeatingTransactions` joins the account and linked transactions in, but it is empty until
19
+ * the transaction store has loaded (see `augmentRepeatingTransactions`). The raw record is the
20
+ * fallback so a subscription the store has is never reported missing just because transactions are
21
+ * still on their way.
22
+ */
23
+ export declare const useRecurringTransactionBlock: (beat: Beat) => RecurringTransactionBlockState;
@@ -0,0 +1,21 @@
1
+ import { useActionContext as p, useRecurringTransactionsStore as T, useTransactionStore as f } from "../../../common/context/hooks.es.js";
2
+ import { resolveSubscriptionGuid as l } from "./subscriptionBeats.es.js";
3
+ var L = (s) => {
4
+ const { detailedRepeatingTransactions: e, isDataLoaded: o, repeatingTransactions: r } = T(), { transactions: c } = f(), t = p()?.recurringLoadFailed === !0 && !o, i = l(s, {
5
+ repeatingTransactions: r,
6
+ transactions: c
7
+ }), a = (u) => u.find((g) => g.guid === i), n = i ? a(r) : void 0, d = n ? a(e) ?? {
8
+ ...n,
9
+ transactions: n.transactions ?? []
10
+ } : void 0;
11
+ return {
12
+ hasLoadError: t,
13
+ isLoading: !o && !t,
14
+ repeatingTransaction: d
15
+ };
16
+ };
17
+ export {
18
+ L as useRecurringTransactionBlock
19
+ };
20
+
21
+ //# sourceMappingURL=useRecurringTransactionBlock.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRecurringTransactionBlock.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionBlock.ts"],"sourcesContent":["import {\n useActionContext,\n useRecurringTransactionsStore,\n useTransactionStore,\n} from '../../../common'\nimport type { Beat, RepeatingTransaction } from '../../../core'\n\nimport { resolveSubscriptionGuid } from './subscriptionBeats'\nimport type { RecurringTransactionActionContext } from './useRecurringTransactionPrepare'\n\nexport interface RecurringTransactionBlockState {\n /** True when the open-time load finished without leaving the store loaded; the block offers a retry. */\n hasLoadError: boolean\n /** True until the recurring store has loaded; the block shows a loader instead of an empty state. */\n isLoading: boolean\n /** `undefined` once loading finishes means the subscription could not be resolved. */\n repeatingTransaction?: RepeatingTransaction\n}\n\n/**\n * Resolves which repeating transaction this drawer is about.\n *\n * The guid comes from the beat (`resolveSubscriptionGuid`), then is looked up in\n * `RecurringTransactionsStore` rather than rebuilt from the beat, because the Expense Details view\n * edits (payment schedule, mark as paid, delete) must write through to the same store object the\n * recurring widget renders.\n *\n * `detailedRepeatingTransactions` joins the account and linked transactions in, but it is empty until\n * the transaction store has loaded (see `augmentRepeatingTransactions`). The raw record is the\n * fallback so a subscription the store has is never reported missing just because transactions are\n * still on their way.\n */\nexport const useRecurringTransactionBlock = (beat: Beat): RecurringTransactionBlockState => {\n const { detailedRepeatingTransactions, isDataLoaded, repeatingTransactions } =\n useRecurringTransactionsStore()\n const { transactions } = useTransactionStore()\n // The failure flag is per drawer session and only cleared by an explicit retry, but the store is\n // shared: another widget on the page (e.g. Recurring Transactions on a dashboard) may load it\n // successfully while this drawer is still open. Data that has since arrived wins over the flag.\n const loadFailed =\n useActionContext<RecurringTransactionActionContext>()?.recurringLoadFailed === true\n const hasLoadError = loadFailed && !isDataLoaded\n\n const guid = resolveSubscriptionGuid(beat, { repeatingTransactions, transactions })\n\n const findByGuid = (list: RepeatingTransaction[]) =>\n list.find((repeating) => repeating.guid === guid)\n\n const raw = guid ? findByGuid(repeatingTransactions) : undefined\n const repeatingTransaction = raw\n ? (findByGuid(detailedRepeatingTransactions) ?? {\n ...raw,\n transactions: raw.transactions ?? [],\n })\n : undefined\n\n return { hasLoadError, isLoading: !isDataLoaded && !hasLoadError, repeatingTransaction }\n}\n"],"mappings":";;AAgCA,IAAa,IAAA,CAAgC,MAA+C;AAC1F,QAAM,EAAE,+BAAA,GAA+B,cAAA,GAAc,uBAAA,EAAA,IACnD,EAA8B,GAC1B,EAAE,cAAA,EAAA,IAAiB,EAAoB,GAMvC,IADJ,EAAoD,GAAG,wBAAwB,MAC9C,CAAC,GAE9B,IAAO,EAAwB,GAAM;AAAA,IAAE,uBAAA;AAAA,IAAuB,cAAA;AAAA,EAAa,CAAC,GAE5E,IAAA,CAAc,MAClB,EAAK,KAAA,CAAM,MAAc,EAAU,SAAS,CAAI,GAE5C,IAAM,IAAO,EAAW,CAAqB,IAAI,QACjD,IAAuB,IACxB,EAAW,CAA6B,KAAK;AAAA,IAC5C,GAAG;AAAA,IACH,cAAc,EAAI,gBAAgB,CAAC;AAAA,EACrC,IACA;AAEJ,SAAO;AAAA,IAAE,cAAA;AAAA,IAAc,WAAW,CAAC,KAAgB,CAAC;AAAA,IAAc,sBAAA;AAAA,EAAqB;AACzF"}
@@ -0,0 +1,25 @@
1
+ import { ActionBlockProps } from '../../mappings/blocks';
2
+ /** The key this block layers onto the drawer's action context when its open-time load fails. */
3
+ export interface RecurringTransactionActionContext {
4
+ recurringLoadFailed?: boolean;
5
+ }
6
+ /**
7
+ * Runs the recurring widget's loader and records whether it left the store loaded.
8
+ *
9
+ * `RecurringTransactionsStore` swallows API failures into `captureError`, so on a failed request
10
+ * `isDataLoaded` simply stays false and nothing else changes. Left alone, that would keep the block
11
+ * on its loader forever. This is the one place that turns the outcome into a flag the block can
12
+ * render an error state (with retry) from. The flag lives on the drawer's action context, which is
13
+ * per drawer session: a new open starts clean.
14
+ */
15
+ export declare const useRecurringTransactionLoad: () => () => Promise<void>;
16
+ /**
17
+ * Open-time data guarantee for the Expense Details drawer. Wired as the block's `usePrepare`, so
18
+ * `ActionBlockLayer` runs it once each time a CTA opens the drawer.
19
+ *
20
+ * A beat is rendered in the feed long before the recurring module has loaded, so the store is
21
+ * usually cold at open time. The loader is the recurring widget's own (accounts, categories and
22
+ * transactions first, then repeating transactions). Guarded on `isDataLoaded` so re-opening does
23
+ * not refetch, and on a ref so a failed load does not refire on every render (retry is explicit).
24
+ */
25
+ export declare const useRecurringTransactionPrepare: (_props: ActionBlockProps) => void;
@@ -0,0 +1,24 @@
1
+ import { useInsightsV2Store as o, useRecurringTransactionsStore as s } from "../../../common/context/hooks.es.js";
2
+ import e from "react";
3
+ var c = () => {
4
+ const a = s(), { setActionContext: r } = o();
5
+ return e.useCallback(async () => {
6
+ r({ recurringLoadFailed: !1 });
7
+ try {
8
+ await a.loadRepeatingTransactionData();
9
+ } catch {
10
+ }
11
+ a.isDataLoaded || r({ recurringLoadFailed: !0 });
12
+ }, [a, r]);
13
+ }, d = (a) => {
14
+ const { isDataLoaded: r } = s(), t = c(), n = e.useRef(!1);
15
+ e.useEffect(() => {
16
+ n.current || r || (n.current = !0, t());
17
+ }, [r, t]);
18
+ };
19
+ export {
20
+ c as useRecurringTransactionLoad,
21
+ d as useRecurringTransactionPrepare
22
+ };
23
+
24
+ //# sourceMappingURL=useRecurringTransactionPrepare.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRecurringTransactionPrepare.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.ts"],"sourcesContent":["import React from 'react'\n\nimport { useInsightsV2Store, useRecurringTransactionsStore } from '../../../common'\nimport type { ActionBlockProps } from '../../mappings/blocks'\n\n/** The key this block layers onto the drawer's action context when its open-time load fails. */\nexport interface RecurringTransactionActionContext {\n recurringLoadFailed?: boolean\n}\n\n/**\n * Runs the recurring widget's loader and records whether it left the store loaded.\n *\n * `RecurringTransactionsStore` swallows API failures into `captureError`, so on a failed request\n * `isDataLoaded` simply stays false and nothing else changes. Left alone, that would keep the block\n * on its loader forever. This is the one place that turns the outcome into a flag the block can\n * render an error state (with retry) from. The flag lives on the drawer's action context, which is\n * per drawer session: a new open starts clean.\n */\nexport const useRecurringTransactionLoad = () => {\n const recurringTransactionsStore = useRecurringTransactionsStore()\n const { setActionContext } = useInsightsV2Store()\n\n return React.useCallback(async () => {\n setActionContext({ recurringLoadFailed: false })\n\n try {\n await recurringTransactionsStore.loadRepeatingTransactionData()\n } catch {\n // Already reported through the store's captureError; the flag below is the UI signal.\n }\n\n if (!recurringTransactionsStore.isDataLoaded) setActionContext({ recurringLoadFailed: true })\n }, [recurringTransactionsStore, setActionContext])\n}\n\n/**\n * Open-time data guarantee for the Expense Details drawer. Wired as the block's `usePrepare`, so\n * `ActionBlockLayer` runs it once each time a CTA opens the drawer.\n *\n * A beat is rendered in the feed long before the recurring module has loaded, so the store is\n * usually cold at open time. The loader is the recurring widget's own (accounts, categories and\n * transactions first, then repeating transactions). Guarded on `isDataLoaded` so re-opening does\n * not refetch, and on a ref so a failed load does not refire on every render (retry is explicit).\n */\nexport const useRecurringTransactionPrepare = (_props: ActionBlockProps) => {\n const { isDataLoaded } = useRecurringTransactionsStore()\n const load = useRecurringTransactionLoad()\n const hasStarted = React.useRef(false)\n\n React.useEffect(() => {\n if (hasStarted.current || isDataLoaded) return\n\n hasStarted.current = true\n void load()\n }, [isDataLoaded, load])\n}\n"],"mappings":";;AAmBA,IAAa,IAAA,MAAoC;AAC/C,QAAM,IAA6B,EAA8B,GAC3D,EAAE,kBAAA,EAAA,IAAqB,EAAmB;AAEhD,SAAO,EAAM,YAAY,YAAY;AACnC,IAAA,EAAiB,EAAE,qBAAqB,GAAM,CAAC;AAE/C,QAAI;AACF,YAAM,EAA2B,6BAA6B;AAAA,IAChE,QAAQ;AAAA,IAER;AAEA,IAAK,EAA2B,gBAAc,EAAiB,EAAE,qBAAqB,GAAK,CAAC;AAAA,EAC9F,GAAG,CAAC,GAA4B,CAAgB,CAAC;AACnD,GAWa,IAAA,CAAkC,MAA6B;AAC1E,QAAM,EAAE,cAAA,EAAA,IAAiB,EAA8B,GACjD,IAAO,EAA4B,GACnC,IAAa,EAAM,OAAO,EAAK;AAErC,EAAA,EAAM,UAAA,MAAgB;AACpB,IAAI,EAAW,WAAW,MAE1B,EAAW,UAAU,IACrB,EAAU;AAAA,EACZ,GAAG,CAAC,GAAc,CAAI,CAAC;AACzB"}
@@ -3,14 +3,14 @@ import { BeatActionsProvider as R } from "../beatActions.es.js";
3
3
  import { isContactSupportCtaDisabled as H } from "../actionBlocks/ContactSupportActionBlock.es.js";
4
4
  import { logoFromRef as M } from "./shared/EntityLogo.es.js";
5
5
  import { actionBlocksKey as P } from "../mappings/actionBlocksKey.es.js";
6
- import { blocks as U } from "../mappings/blocks.es.js";
7
- import j from "./Footer.es.js";
8
- import z from "./Header.es.js";
9
- import { FeedbackBar as G } from "./FeedbackBar.es.js";
10
- import K from "./FeedbackDialog.es.js";
11
- import { DismissInsightDialog as X } from "./DismissInsightDialog.es.js";
12
- import { HiddenConfirmationCard as V } from "./HiddenConfirmationCard.es.js";
13
- import { ErrorCard as W } from "./ErrorCard.es.js";
6
+ import { ErrorCard as U } from "./ErrorCard.es.js";
7
+ import { blocks as j } from "../mappings/blocks.es.js";
8
+ import z from "./Footer.es.js";
9
+ import G from "./Header.es.js";
10
+ import { FeedbackBar as K } from "./FeedbackBar.es.js";
11
+ import X from "./FeedbackDialog.es.js";
12
+ import { DismissInsightDialog as V } from "./DismissInsightDialog.es.js";
13
+ import { HiddenConfirmationCard as W } from "./HiddenConfirmationCard.es.js";
14
14
  import { LoadingCard as Y } from "./LoadingCard.es.js";
15
15
  import { ObsolesceBanner as q } from "./ObsolesceBanner.es.js";
16
16
  import { ActionBlockLayer as J } from "../actionBlocks/ActionBlockLayer.es.js";
@@ -43,7 +43,7 @@ var so = {}, no = {
43
43
  textTransform: "none"
44
44
  }, Ro = $(({ beat: t, beatActions: s = so, obsolete: c, isLoading: x = !1, isError: _ = !1 }) => {
45
45
  const v = N(), { config: S } = E(), o = Z(t, s), { runCta: T, primary: C, secondary: g } = Q(t, s, t.insights_payload?.primary_cta, t.insights_payload?.secondary_cta);
46
- if (_) return /* @__PURE__ */ i(W, {});
46
+ if (_) return /* @__PURE__ */ i(U, {});
47
47
  const e = t.insights_payload;
48
48
  if (!e || o.cardState === "dismissed") return null;
49
49
  const { instance_slot: B, primary_cta: r, secondary_cta: n, sub_title: O, title: D, widget_type: L, guid: I, dismissed_at: F } = e, { block: A } = B, w = O ?? (e.subtitle ? {
@@ -57,13 +57,13 @@ var so = {}, no = {
57
57
  }
58
58
  await T(f, u);
59
59
  }
60
- }, k = U[A], d = L === "mini", m = v.insights_feed?.general, p = c?.state === "not_refreshable" && !F && !!m;
60
+ }, k = j[A], d = L === "mini", m = v.insights_feed?.general, p = c?.state === "not_refreshable" && !F && !!m;
61
61
  return /* @__PURE__ */ i(R, {
62
62
  value: o.wrappedActions,
63
63
  children: /* @__PURE__ */ a(b, {
64
64
  sx: { mb: 16 },
65
65
  children: [
66
- o.cardState === "confirming" ? /* @__PURE__ */ i(V, {
66
+ o.cardState === "confirming" ? /* @__PURE__ */ i(W, {
67
67
  onClose: o.collapseConfirmation,
68
68
  onLeaveFeedback: o.openHideSurvey,
69
69
  onUndo: o.undoDismiss
@@ -79,7 +79,7 @@ var so = {}, no = {
79
79
  } },
80
80
  children: [
81
81
  p && /* @__PURE__ */ i(ro, { sx: no }),
82
- /* @__PURE__ */ i(z, {
82
+ /* @__PURE__ */ i(G, {
83
83
  isMini: d,
84
84
  subtitle: w,
85
85
  title: D ?? ""
@@ -136,19 +136,19 @@ var so = {}, no = {
136
136
  children: n.label
137
137
  })]
138
138
  }),
139
- /* @__PURE__ */ i(G, {
139
+ /* @__PURE__ */ i(K, {
140
140
  onTellUsMore: o.openRatingSurvey,
141
141
  show: o.isFeedbackBarShown
142
142
  })
143
143
  ]
144
144
  })] }),
145
145
  /* @__PURE__ */ i(J, { beat: t }),
146
- /* @__PURE__ */ i(X, {
146
+ /* @__PURE__ */ i(V, {
147
147
  isOpen: o.isDismissOpen,
148
148
  onClose: o.closeDismissDialog,
149
149
  onDismiss: o.confirmDismiss
150
150
  }),
151
- o.isSurveyOpen && /* @__PURE__ */ i(K, {
151
+ o.isSurveyOpen && /* @__PURE__ */ i(X, {
152
152
  characterLimitLabel: o.survey.characterLimitLabel,
153
153
  closeAriaLabel: o.survey.closeAriaLabel,
154
154
  isOpen: !0,
@@ -161,7 +161,7 @@ var so = {}, no = {
161
161
  secondaryText: o.survey.backText,
162
162
  title: o.survey.title
163
163
  }),
164
- o.cardState === "visible" && e.footer && /* @__PURE__ */ i(j, { footer: e.footer })
164
+ o.cardState === "visible" && e.footer && /* @__PURE__ */ i(z, { footer: e.footer })
165
165
  ]
166
166
  })
167
167
  });
@@ -29,11 +29,11 @@ import { SVGImageBlock as pr } from "./blocks/ImageBlocks/SVGImageBlock/SVGImage
29
29
  import er from "./components/AccountHeroCard.es.js";
30
30
  import sr from "./components/AmountPill.es.js";
31
31
  import lr from "./components/DesignateEmergencySavingsCard.es.js";
32
- import { FeedbackBar as Cr } from "./components/FeedbackBar.es.js";
33
- import Br from "./components/FeedbackDialog.es.js";
34
- import { DismissInsightDialog as hr } from "./components/DismissInsightDialog.es.js";
35
- import { HiddenConfirmationCard as Sr } from "./components/HiddenConfirmationCard.es.js";
36
- import { ErrorCard as Tr } from "./components/ErrorCard.es.js";
32
+ import { ErrorCard as Cr } from "./components/ErrorCard.es.js";
33
+ import { FeedbackBar as Br } from "./components/FeedbackBar.es.js";
34
+ import hr from "./components/FeedbackDialog.es.js";
35
+ import { DismissInsightDialog as Sr } from "./components/DismissInsightDialog.es.js";
36
+ import { HiddenConfirmationCard as Tr } from "./components/HiddenConfirmationCard.es.js";
37
37
  import { LoadingCard as Dr } from "./components/LoadingCard.es.js";
38
38
  import { ObsolesceBanner as Lr } from "./components/ObsolesceBanner.es.js";
39
39
  import { HOST_ACTIONS as vr } from "./ctaActions/hostActions.es.js";
@@ -59,15 +59,15 @@ export {
59
59
  U as BudgetBlock,
60
60
  h as CompactInsightCard,
61
61
  lr as DesignateEmergencySavingsCard,
62
- hr as DismissInsightDialog,
62
+ Sr as DismissInsightDialog,
63
63
  R as DonutChartBlock,
64
64
  O as DoubleBarChartBlock,
65
65
  V as DoubleProgressBarBlock,
66
- Tr as ErrorCard,
67
- Cr as FeedbackBar,
68
- Br as FeedbackDialog,
66
+ Cr as ErrorCard,
67
+ Br as FeedbackBar,
68
+ hr as FeedbackDialog,
69
69
  vr as HOST_ACTIONS,
70
- Sr as HiddenConfirmationCard,
70
+ Tr as HiddenConfirmationCard,
71
71
  S as InsightErrorCard,
72
72
  c as InsightOptionsMenu,
73
73
  Q as InsightTransactionRow,
@@ -4,4 +4,5 @@ export declare const actionBlocksKey: {
4
4
  TRANSCATION_HISTORY_ACTION_BLOCK: string;
5
5
  TRANSACTION_DETAILS_ACTION_BLOCK: string;
6
6
  CONTACT_SUPPORT_ACTION_BLOCK: string;
7
+ RECURRING_TRANSACTION_ACTION_BLOCK: string;
7
8
  };
@@ -3,7 +3,8 @@ var _ = {
3
3
  MAKE_TRANSFER_ACTION_BLOCK: "make_transfer",
4
4
  TRANSCATION_HISTORY_ACTION_BLOCK: "transaction_history_block",
5
5
  TRANSACTION_DETAILS_ACTION_BLOCK: "transaction_details_block",
6
- CONTACT_SUPPORT_ACTION_BLOCK: "contact_support_block"
6
+ CONTACT_SUPPORT_ACTION_BLOCK: "contact_support_block",
7
+ RECURRING_TRANSACTION_ACTION_BLOCK: "recurring_transaction_block"
7
8
  };
8
9
  export {
9
10
  _ as actionBlocksKey
@@ -1 +1 @@
1
- {"version":3,"file":"actionBlocksKey.es.js","names":[],"sources":["../../../src/insights-v2/mappings/actionBlocksKey.ts"],"sourcesContent":["// Keys for the drawer drilldown registry in `blocks.ts`, extracted into their own module.\n//\n// Why: chart blocks (e.g. BarchartBlock, DoubleBarChartBlock) need\n// `TRANSCATION_HISTORY_ACTION_BLOCK` to tag a chart bar's drilldown context, but they are\n// themselves re-exported through `../blocks` -> `mappings/blocks.ts` imports from that same\n// barrel to build its `blocks` registry. Importing the key straight from `mappings/blocks.ts`\n// closed that loop into a circular import: evaluating `mappings/blocks.ts` pulled in the\n// `blocks` barrel, which (before it got to `ComponentBlocks`/`AccountBlock`) loaded\n// `BarchartBlock`, which imported back into the still-initializing `mappings/blocks.ts` —\n// tripping a \"Cannot access 'AccountBlock' before initialization\" TDZ error in Storybook/Vite.\n//\n// Keeping the keys here (no dependency on `mappings/blocks.ts`) lets chart blocks reference\n// them without re-entering that module.\n//\n// Names follow ditto: its registry ends every CTA block in `_block` and the V2 envelope copies those\n// names verbatim (`transaction_details_block`, `contact_support_block`). `make_transfer` is a legacy\n// name that stays as an alias until the last legacy payload is gone.\nexport const actionBlocksKey = {\n PLACEHOLDER_ACTION_BLOCK: 'PlaceholderActionBlock',\n MAKE_TRANSFER_ACTION_BLOCK: 'make_transfer',\n TRANSCATION_HISTORY_ACTION_BLOCK: 'transaction_history_block',\n TRANSACTION_DETAILS_ACTION_BLOCK: 'transaction_details_block',\n CONTACT_SUPPORT_ACTION_BLOCK: 'contact_support_block',\n}\n"],"mappings":"AAiBA,IAAa,IAAkB;AAAA,EAC7B,0BAA0B;AAAA,EAC1B,4BAA4B;AAAA,EAC5B,kCAAkC;AAAA,EAClC,kCAAkC;AAAA,EAClC,8BAA8B;AAChC"}
1
+ {"version":3,"file":"actionBlocksKey.es.js","names":[],"sources":["../../../src/insights-v2/mappings/actionBlocksKey.ts"],"sourcesContent":["// Keys for the drawer drilldown registry in `blocks.ts`, extracted into their own module.\n//\n// Why: chart blocks (e.g. BarchartBlock, DoubleBarChartBlock) need\n// `TRANSCATION_HISTORY_ACTION_BLOCK` to tag a chart bar's drilldown context, but they are\n// themselves re-exported through `../blocks` -> `mappings/blocks.ts` imports from that same\n// barrel to build its `blocks` registry. Importing the key straight from `mappings/blocks.ts`\n// closed that loop into a circular import: evaluating `mappings/blocks.ts` pulled in the\n// `blocks` barrel, which (before it got to `ComponentBlocks`/`AccountBlock`) loaded\n// `BarchartBlock`, which imported back into the still-initializing `mappings/blocks.ts` —\n// tripping a \"Cannot access 'AccountBlock' before initialization\" TDZ error in Storybook/Vite.\n//\n// Keeping the keys here (no dependency on `mappings/blocks.ts`) lets chart blocks reference\n// them without re-entering that module.\n//\n// Names follow ditto: its registry ends every CTA block in `_block` and the V2 envelope copies those\n// names verbatim (`transaction_details_block`, `contact_support_block`). `make_transfer` is a legacy\n// name that stays as an alias until the last legacy payload is gone.\nexport const actionBlocksKey = {\n PLACEHOLDER_ACTION_BLOCK: 'PlaceholderActionBlock',\n MAKE_TRANSFER_ACTION_BLOCK: 'make_transfer',\n TRANSCATION_HISTORY_ACTION_BLOCK: 'transaction_history_block',\n TRANSACTION_DETAILS_ACTION_BLOCK: 'transaction_details_block',\n CONTACT_SUPPORT_ACTION_BLOCK: 'contact_support_block',\n RECURRING_TRANSACTION_ACTION_BLOCK: 'recurring_transaction_block',\n}\n"],"mappings":"AAiBA,IAAa,IAAkB;AAAA,EAC7B,0BAA0B;AAAA,EAC1B,4BAA4B;AAAA,EAC5B,kCAAkC;AAAA,EAClC,kCAAkC;AAAA,EAClC,8BAA8B;AAAA,EAC9B,oCAAoC;AACtC"}
@@ -1,78 +1,85 @@
1
1
  import { ContactSupportActionBlock as a } from "../actionBlocks/ContactSupportActionBlock.es.js";
2
- import { actionBlocksKey as o } from "./actionBlocksKey.es.js";
2
+ import { actionBlocksKey as r } from "./actionBlocksKey.es.js";
3
3
  import { BarchartBlock as c } from "../blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js";
4
- import { DoubleBarChartBlock as l } from "../blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
5
- import i from "../blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
4
+ import { DoubleBarChartBlock as i } from "../blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js";
5
+ import l from "../blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js";
6
6
  import m from "../blocks/ChartBlocks/DonutChartBlock/DonutChartBlock.es.js";
7
7
  import n from "../blocks/ChartBlocks/DoubleProgressBarBlock/DoubleProgressBarBlock.es.js";
8
8
  import p from "../blocks/ComponentBlocks/AccountBlock/AccountBlock.es.js";
9
9
  import _ from "../blocks/ComponentBlocks/AccountSwitchBlock/AccountSwitchBlock.es.js";
10
- import { BudgetBlock as k } from "../blocks/ComponentBlocks/BudgetBlock/BudgetBlock.es.js";
11
- import s from "../blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
10
+ import { BudgetBlock as s } from "../blocks/ComponentBlocks/BudgetBlock/BudgetBlock.es.js";
11
+ import k from "../blocks/ComponentBlocks/SaveExtraBlock/SaveExtraBlock.es.js";
12
12
  import { TransactionBlock as B } from "../blocks/ComponentBlocks/TransactionBlock/TransactionBlock.es.js";
13
13
  import C from "../blocks/ComponentBlocks/WithdrawalBlock/WithdrawalBlock.es.js";
14
- import f from "../blocks/ImageBlocks/ImageBlock.es.js";
15
- import { SVGImageBlock as u } from "../blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
16
- import { PlaceholderActionBlock as T } from "../actionBlocks/PlaceholderActionBlock.es.js";
17
- import { getMakeTransferDrawerTitle as b } from "../actionBlocks/MakeTransferActionBlock/layout.es.js";
18
- import { MakeTransferActionBlockLayer as A } from "../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer.es.js";
14
+ import u from "../blocks/ImageBlocks/ImageBlock.es.js";
15
+ import { SVGImageBlock as T } from "../blocks/ImageBlocks/SVGImageBlock/SVGImageBlock.es.js";
16
+ import { PlaceholderActionBlock as f } from "../actionBlocks/PlaceholderActionBlock.es.js";
17
+ import { getMakeTransferDrawerTitle as A } from "../actionBlocks/MakeTransferActionBlock/layout.es.js";
18
+ import { MakeTransferActionBlockLayer as b } from "../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer.es.js";
19
19
  import { getDrawerHeaderTitle as O } from "../actionBlocks/TransactionHistoryBlock/utils.es.js";
20
- import { TransactionDetailsBlock as h } from "../actionBlocks/TransactionDetailsBlock/TransactionDetailsBlock.es.js";
21
- import { useTransactionDetailsPrepare as d } from "../actionBlocks/TransactionDetailsBlock/useTransactionDetailsPrepare.es.js";
22
- import { TransactionHistoryBlock as L } from "../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js";
23
- var t = (e) => {
24
- }, N = /* @__PURE__ */ new Set([
20
+ import { TransactionDetailsBlock as N } from "../actionBlocks/TransactionDetailsBlock/TransactionDetailsBlock.es.js";
21
+ import { useTransactionDetailsPrepare as h } from "../actionBlocks/TransactionDetailsBlock/useTransactionDetailsPrepare.es.js";
22
+ import { TransactionHistoryBlock as d } from "../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js";
23
+ import { useRecurringTransactionPrepare as g } from "../actionBlocks/RecurringTransactionBlock/useRecurringTransactionPrepare.es.js";
24
+ import { RecurringTransactionBlock as I } from "../actionBlocks/RecurringTransactionBlock/RecurringTransactionBlock.es.js";
25
+ var e = (t) => {
26
+ }, L = /* @__PURE__ */ new Set([
25
27
  "",
26
28
  "null",
27
29
  "undefined"
28
- ]), j = (e) => {
29
- const r = e?.trim().toLowerCase();
30
- return !!r && !N.has(r);
31
- }, J = {
32
- [o.PLACEHOLDER_ACTION_BLOCK]: {
33
- Component: T,
34
- usePrepare: t,
30
+ ]), Z = (t) => {
31
+ const o = t?.trim().toLowerCase();
32
+ return !!o && !L.has(o);
33
+ }, $ = {
34
+ [r.PLACEHOLDER_ACTION_BLOCK]: {
35
+ Component: f,
36
+ usePrepare: e,
35
37
  title: () => "Action Block Layer Drilldown"
36
38
  },
37
- [o.MAKE_TRANSFER_ACTION_BLOCK]: {
38
- Component: A,
39
- usePrepare: t,
40
- title: b
39
+ [r.MAKE_TRANSFER_ACTION_BLOCK]: {
40
+ Component: b,
41
+ usePrepare: e,
42
+ title: A
41
43
  },
42
- [o.TRANSCATION_HISTORY_ACTION_BLOCK]: {
43
- Component: L,
44
- usePrepare: t,
44
+ [r.TRANSCATION_HISTORY_ACTION_BLOCK]: {
45
+ Component: d,
46
+ usePrepare: e,
45
47
  title: O
46
48
  },
47
- [o.TRANSACTION_DETAILS_ACTION_BLOCK]: {
48
- Component: h,
49
- usePrepare: d,
49
+ [r.TRANSACTION_DETAILS_ACTION_BLOCK]: {
50
+ Component: N,
51
+ usePrepare: h,
50
52
  title: () => "Transaction Details"
51
53
  },
52
- [o.CONTACT_SUPPORT_ACTION_BLOCK]: {
54
+ [r.RECURRING_TRANSACTION_ACTION_BLOCK]: {
55
+ Component: I,
56
+ usePrepare: g,
57
+ title: (t, o) => o.recurring?.expense_details ?? ""
58
+ },
59
+ [r.CONTACT_SUPPORT_ACTION_BLOCK]: {
53
60
  Component: a,
54
- usePrepare: t,
55
- title: (e, r) => r.help?.request_support ?? ""
61
+ usePrepare: e,
62
+ title: (t, o) => o.help?.request_support ?? ""
56
63
  }
57
- }, Q = {
64
+ }, oo = {
58
65
  account_block: p,
59
66
  account_switch_block: _,
60
67
  bar_chart_block: c,
61
- budget_block: k,
68
+ budget_block: s,
62
69
  donut_chart_block: m,
63
- double_bar_chart_block: l,
70
+ double_bar_chart_block: i,
64
71
  double_progress_bar_block: n,
65
- image_block: f,
66
- save_extra_block: s,
67
- step_chart_block: i,
68
- svg_image_block: u,
72
+ image_block: u,
73
+ save_extra_block: k,
74
+ step_chart_block: l,
75
+ svg_image_block: T,
69
76
  withdrawal_block: C,
70
77
  transaction_block: B
71
78
  };
72
79
  export {
73
- J as actionBlocks,
74
- Q as blocks,
75
- j as hasDrawerBlock
80
+ $ as actionBlocks,
81
+ oo as blocks,
82
+ Z as hasDrawerBlock
76
83
  };
77
84
 
78
85
  //# sourceMappingURL=blocks.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.es.js","names":[],"sources":["../../../src/insights-v2/mappings/blocks.ts"],"sourcesContent":["import {\n AccountBlock,\n AccountSwitchBlock,\n BarchartBlock,\n BudgetBlock,\n DonutChartBlock,\n DoubleBarChartBlock,\n DoubleProgressBarBlock,\n SaveExtraBlock,\n SVGImageBlock,\n WithdrawalBlock,\n TransactionBlock,\n} from '../blocks'\nimport StepChartBlock from '../blocks/ChartBlocks/StepChartBlock'\nimport ImageBlock from '../blocks/ImageBlocks/ImageBlock'\n\nimport type { Beat, GlobalCopy, InsightsPayload } from '../../core'\nimport { ContactSupportActionBlock } from '../actionBlocks/ContactSupportActionBlock'\nimport { PlaceholderActionBlock } from '../actionBlocks/PlaceholderActionBlock'\nimport { MakeTransferActionBlockLayer } from '../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer'\nimport { getMakeTransferDrawerTitle } from '../actionBlocks/MakeTransferActionBlock/layout'\nimport { TransactionHistoryBlock } from '../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock'\nimport { getDrawerHeaderTitle } from '../actionBlocks/TransactionHistoryBlock/utils'\nimport {\n TransactionDetailsBlock,\n useTransactionDetailsPrepare,\n} from '../actionBlocks/TransactionDetailsBlock'\n// Keys live in ./actionBlocksKey (imported directly by chart blocks/tests too) to avoid a\n// circular import between this module and the chart blocks — see that file for details.\nimport { actionBlocksKey } from './actionBlocksKey'\n\n// Drilldown indexes are not passed down: action blocks read them from\n// InsightsV2Store (useInsightsV2Store().actionDrawer).\nexport interface ActionBlockProps {\n beat: Beat\n}\n\nconst noop = (_: ActionBlockProps) => {}\n\n// A CTA opens a drawer only when it carries a real `block`. The backend may send\n// an empty/absent block (or the literal strings \"null\"/\"undefined\") for CTAs\n// that trigger something else (e.g. a postMessage) instead of a drilldown.\nconst NON_BLOCK_VALUES = new Set(['', 'null', 'undefined'])\nexport const hasDrawerBlock = (block?: string | null): boolean => {\n const normalized = block?.trim().toLowerCase()\n return !!normalized && !NON_BLOCK_VALUES.has(normalized)\n}\n\nexport interface ActionBlockEntry {\n Component: React.ComponentType<ActionBlockProps>\n usePrepare: (props: ActionBlockProps) => void // required; default to noop in each entry\n // Resolves the drawer title from the clicked CTA's variant + copy (e.g.\n // MakeTransfer reads its variant title from layout.ts). Falls back to the CTA label.\n title?: (variant: string | null | undefined, copy: GlobalCopy) => string\n}\n\n// Registry of drawer drilldowns, keyed by the `block` name the backend sends\n// on a beat's CTA. To add one: create a component taking ActionBlockProps,\n// read the clicked indexes from useInsightsV2Store().actionDrawer, and\n// register it here. Add\n// `usePrepare` when the block needs to load data before rendering.\n\nexport const actionBlocks = {\n [actionBlocksKey.PLACEHOLDER_ACTION_BLOCK]: {\n Component: PlaceholderActionBlock,\n usePrepare: noop,\n title: () => 'Action Block Layer Drilldown',\n },\n [actionBlocksKey.MAKE_TRANSFER_ACTION_BLOCK]: {\n Component: MakeTransferActionBlockLayer,\n usePrepare: noop,\n title: getMakeTransferDrawerTitle,\n },\n [actionBlocksKey.TRANSCATION_HISTORY_ACTION_BLOCK]: {\n Component: TransactionHistoryBlock,\n usePrepare: noop,\n title: getDrawerHeaderTitle,\n },\n [actionBlocksKey.TRANSACTION_DETAILS_ACTION_BLOCK]: {\n Component: TransactionDetailsBlock,\n usePrepare: useTransactionDetailsPrepare,\n title: () => 'Transaction Details',\n },\n // The block renders its own drawer (the help module's RequestSupport) on top of the action\n // drawer, so the action drawer's title is the CTA label.\n [actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK]: {\n Component: ContactSupportActionBlock,\n usePrepare: noop,\n title: (_variant, copy) => copy.help?.request_support ?? '',\n },\n} as Record<string, ActionBlockEntry>\n\nexport const blocks = {\n account_block: AccountBlock,\n account_switch_block: AccountSwitchBlock,\n bar_chart_block: BarchartBlock,\n budget_block: BudgetBlock,\n donut_chart_block: DonutChartBlock,\n double_bar_chart_block: DoubleBarChartBlock,\n double_progress_bar_block: DoubleProgressBarBlock,\n image_block: ImageBlock,\n save_extra_block: SaveExtraBlock,\n step_chart_block: StepChartBlock,\n svg_image_block: SVGImageBlock,\n withdrawal_block: WithdrawalBlock,\n transaction_block: TransactionBlock,\n} as Record<string, React.ComponentType<{ payload: InsightsPayload; beatGuid?: string }>>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAM,IAAA,CAAQ,MAAwB;AAAC,GAKjC,IAAmB,oBAAI,IAAI;AAAA,EAAC;AAAA,EAAI;AAAA,EAAQ;AAAW,CAAC,GAC7C,IAAA,CAAkB,MAAmC;AAChE,QAAM,IAAa,GAAO,KAAK,EAAE,YAAY;AAC7C,SAAO,CAAC,CAAC,KAAc,CAAC,EAAiB,IAAI,CAAU;AACzD,GAgBa,IAAe;AAAA,EACzB,CAAA,EAAgB,wBAAA,GAA2B;AAAA,IAC1C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EACC,CAAA,EAAgB,0BAAA,GAA6B;AAAA,IAC5C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EAGC,CAAA,EAAgB,4BAAA,GAA+B;AAAA,IAC9C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,MAAM,mBAAmB;AAAA,EAC3D;AACF,GAEa,IAAS;AAAA,EACpB,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,mBAAmB;AACrB"}
1
+ {"version":3,"file":"blocks.es.js","names":[],"sources":["../../../src/insights-v2/mappings/blocks.ts"],"sourcesContent":["import {\n AccountBlock,\n AccountSwitchBlock,\n BarchartBlock,\n BudgetBlock,\n DonutChartBlock,\n DoubleBarChartBlock,\n DoubleProgressBarBlock,\n SaveExtraBlock,\n SVGImageBlock,\n WithdrawalBlock,\n TransactionBlock,\n} from '../blocks'\nimport StepChartBlock from '../blocks/ChartBlocks/StepChartBlock'\nimport ImageBlock from '../blocks/ImageBlocks/ImageBlock'\n\nimport type { Beat, GlobalCopy, InsightsPayload } from '../../core'\nimport { ContactSupportActionBlock } from '../actionBlocks/ContactSupportActionBlock'\nimport { PlaceholderActionBlock } from '../actionBlocks/PlaceholderActionBlock'\nimport { MakeTransferActionBlockLayer } from '../actionBlocks/MakeTransferActionBlock/MakeTransferActionBlockLayer'\nimport { getMakeTransferDrawerTitle } from '../actionBlocks/MakeTransferActionBlock/layout'\nimport { TransactionHistoryBlock } from '../actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock'\nimport { getDrawerHeaderTitle } from '../actionBlocks/TransactionHistoryBlock/utils'\nimport {\n TransactionDetailsBlock,\n useTransactionDetailsPrepare,\n} from '../actionBlocks/TransactionDetailsBlock'\nimport {\n RecurringTransactionBlock,\n useRecurringTransactionPrepare,\n} from '../actionBlocks/RecurringTransactionBlock'\n// Keys live in ./actionBlocksKey (imported directly by chart blocks/tests too) to avoid a\n// circular import between this module and the chart blocks — see that file for details.\nimport { actionBlocksKey } from './actionBlocksKey'\n\n// Drilldown indexes are not passed down: action blocks read them from\n// InsightsV2Store (useInsightsV2Store().actionDrawer).\nexport interface ActionBlockProps {\n beat: Beat\n}\n\nconst noop = (_: ActionBlockProps) => {}\n\n// A CTA opens a drawer only when it carries a real `block`. The backend may send\n// an empty/absent block (or the literal strings \"null\"/\"undefined\") for CTAs\n// that trigger something else (e.g. a postMessage) instead of a drilldown.\nconst NON_BLOCK_VALUES = new Set(['', 'null', 'undefined'])\nexport const hasDrawerBlock = (block?: string | null): boolean => {\n const normalized = block?.trim().toLowerCase()\n return !!normalized && !NON_BLOCK_VALUES.has(normalized)\n}\n\nexport interface ActionBlockEntry {\n Component: React.ComponentType<ActionBlockProps>\n usePrepare: (props: ActionBlockProps) => void // required; default to noop in each entry\n // Resolves the drawer title from the clicked CTA's variant + copy (e.g.\n // MakeTransfer reads its variant title from layout.ts). Falls back to the CTA label.\n title?: (variant: string | null | undefined, copy: GlobalCopy) => string\n}\n\n// Registry of drawer drilldowns, keyed by the `block` name the backend sends\n// on a beat's CTA. To add one: create a component taking ActionBlockProps,\n// read the clicked indexes from useInsightsV2Store().actionDrawer, and\n// register it here. Add\n// `usePrepare` when the block needs to load data before rendering.\n\nexport const actionBlocks = {\n [actionBlocksKey.PLACEHOLDER_ACTION_BLOCK]: {\n Component: PlaceholderActionBlock,\n usePrepare: noop,\n title: () => 'Action Block Layer Drilldown',\n },\n [actionBlocksKey.MAKE_TRANSFER_ACTION_BLOCK]: {\n Component: MakeTransferActionBlockLayer,\n usePrepare: noop,\n title: getMakeTransferDrawerTitle,\n },\n [actionBlocksKey.TRANSCATION_HISTORY_ACTION_BLOCK]: {\n Component: TransactionHistoryBlock,\n usePrepare: noop,\n title: getDrawerHeaderTitle,\n },\n [actionBlocksKey.TRANSACTION_DETAILS_ACTION_BLOCK]: {\n Component: TransactionDetailsBlock,\n usePrepare: useTransactionDetailsPrepare,\n title: () => 'Transaction Details',\n },\n // Expense Details for one recurring subscription. Which subscription a beat names is resolved in\n // `RecurringTransactionBlock/subscriptionBeats.ts`, not through this registry.\n [actionBlocksKey.RECURRING_TRANSACTION_ACTION_BLOCK]: {\n Component: RecurringTransactionBlock,\n usePrepare: useRecurringTransactionPrepare,\n title: (_variant, copy) => copy.recurring?.expense_details ?? '',\n },\n // The block renders its own drawer (the help module's RequestSupport) on top of the action\n // drawer, so the action drawer's title is the CTA label.\n [actionBlocksKey.CONTACT_SUPPORT_ACTION_BLOCK]: {\n Component: ContactSupportActionBlock,\n usePrepare: noop,\n title: (_variant, copy) => copy.help?.request_support ?? '',\n },\n} as Record<string, ActionBlockEntry>\n\nexport const blocks = {\n account_block: AccountBlock,\n account_switch_block: AccountSwitchBlock,\n bar_chart_block: BarchartBlock,\n budget_block: BudgetBlock,\n donut_chart_block: DonutChartBlock,\n double_bar_chart_block: DoubleBarChartBlock,\n double_progress_bar_block: DoubleProgressBarBlock,\n image_block: ImageBlock,\n save_extra_block: SaveExtraBlock,\n step_chart_block: StepChartBlock,\n svg_image_block: SVGImageBlock,\n withdrawal_block: WithdrawalBlock,\n transaction_block: TransactionBlock,\n} as Record<string, React.ComponentType<{ payload: InsightsPayload; beatGuid?: string }>>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAM,IAAA,CAAQ,MAAwB;AAAC,GAKjC,IAAmB,oBAAI,IAAI;AAAA,EAAC;AAAA,EAAI;AAAA,EAAQ;AAAW,CAAC,GAC7C,IAAA,CAAkB,MAAmC;AAChE,QAAM,IAAa,GAAO,KAAK,EAAE,YAAY;AAC7C,SAAO,CAAC,CAAC,KAAc,CAAC,EAAiB,IAAI,CAAU;AACzD,GAgBa,IAAe;AAAA,EACzB,CAAA,EAAgB,wBAAA,GAA2B;AAAA,IAC1C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EACC,CAAA,EAAgB,0BAAA,GAA6B;AAAA,IAC5C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,EACT;AAAA,EACC,CAAA,EAAgB,gCAAA,GAAmC;AAAA,IAClD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,MAAa;AAAA,EACf;AAAA,EAGC,CAAA,EAAgB,kCAAA,GAAqC;AAAA,IACpD,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,WAAW,mBAAmB;AAAA,EAChE;AAAA,EAGC,CAAA,EAAgB,4BAAA,GAA+B;AAAA,IAC9C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAA,CAAQ,GAAU,MAAS,EAAK,MAAM,mBAAmB;AAAA,EAC3D;AACF,GAEa,KAAS;AAAA,EACpB,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,mBAAmB;AACrB"}
@@ -2,10 +2,10 @@ import { useEvent as z, useTransactionStore as N } from "../../../common/context
2
2
  import { ANALYTICS_EVENTS as O } from "../../../common/constants/Analytics.es.js";
3
3
  import { fromUnixUTCToDayOfWeekAndDate as H } from "../../../core/utils/DateUtil.es.js";
4
4
  import U from "../../../common/components/Loader.es.js";
5
- import { useTransactionsUiStore as k } from "../../context/hooks.es.js";
6
- import W from "./transactionlist/TransactionRow.es.js";
7
- import j from "../../../common/components/SubheaderRow.es.js";
8
- import w from "./transactionlist/ZeroState.es.js";
5
+ import k from "../../../common/components/ZeroState.es.js";
6
+ import { useTransactionsUiStore as W } from "../../context/hooks.es.js";
7
+ import j from "./transactionlist/TransactionRow.es.js";
8
+ import w from "../../../common/components/SubheaderRow.es.js";
9
9
  import { hasInsetBorder as B, shouldShowDate as T } from "../../utils/Transactions.es.js";
10
10
  import i from "react";
11
11
  import { observer as G } from "mobx-react-lite";
@@ -17,7 +17,7 @@ import { useVirtualizer as K } from "@tanstack/react-virtual";
17
17
  var _ = 65, v = 32, M = ({ bgcolor: x, filter: s, height: E = "calc(100dvh - 36px)", loader: I = /* @__PURE__ */ o(U, {
18
18
  label: "Loading",
19
19
  size: 40
20
- }), onClick: f, showInsights: d = !1, showLoader: l = !1, transaction: p, width: g = "100%", zeroState: A = /* @__PURE__ */ o(w, {}) }) => {
20
+ }), onClick: f, showInsights: d = !1, showLoader: l = !1, transaction: p, width: g = "100%", zeroState: A = /* @__PURE__ */ o(k, {}) }) => {
21
21
  const { isLoading: c, sortedTransactions: m } = N(), e = i.useMemo(() => {
22
22
  const t = s ? m.filter(s) : m;
23
23
  return p ?? t;
@@ -25,7 +25,7 @@ var _ = 65, v = 32, M = ({ bgcolor: x, filter: s, height: E = "calc(100dvh - 36p
25
25
  m,
26
26
  s,
27
27
  p
28
- ]), { clearExpandedSplits: C, setShowInsights: R, toggleSplit: b } = k(), { onEvent: D } = z(), L = (t) => {
28
+ ]), { clearExpandedSplits: C, setShowInsights: R, toggleSplit: b } = W(), { onEvent: D } = z(), L = (t) => {
29
29
  const r = e.find((a) => a.guid === t);
30
30
  if (r?.has_been_split) {
31
31
  b(r.guid);
@@ -71,11 +71,11 @@ var _ = 65, v = 32, M = ({ bgcolor: x, filter: s, height: E = "calc(100dvh - 36p
71
71
  bgcolor: "background.paper"
72
72
  },
73
73
  children: [
74
- a && /* @__PURE__ */ o(j, {
74
+ a && /* @__PURE__ */ o(w, {
75
75
  bgcolor: x,
76
76
  children: H(r.date)
77
77
  }),
78
- /* @__PURE__ */ o(W, {
78
+ /* @__PURE__ */ o(j, {
79
79
  component: "div",
80
80
  ...f && { onClick: L },
81
81
  transaction: r
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionList.es.js","names":[],"sources":["../../../../src/transactions/components/shared/TransactionList.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\nimport { useVirtualizer } from '@tanstack/react-virtual'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport List from '@mui/material/List'\n\nimport { ANALYTICS_EVENTS, Loader, useEvent } from '../../../common'\nimport { type Transaction } from '../../../core'\n\nimport { useTransactionsUiStore } from '../../context/hooks'\nimport { useTransactionStore } from '../../../common'\n\nimport SubheaderRow from '../../../common/components/SubheaderRow'\nimport TransactionRow from './transactionlist/TransactionRow'\nimport ZeroState from './transactionlist/ZeroState'\n\nimport { hasInsetBorder, shouldShowDate } from '../../utils/Transactions'\nimport { fromUnixUTCToDayOfWeekAndDate } from '../../../core/utils/DateUtil'\n\nconst ROW_HEIGHT = 65\nconst DATE_ROW_HEIGHT = 32\n\nexport interface TransactionListProps {\n bgcolor?: string\n filter?: (t: Transaction) => boolean\n height?: number | string\n loader?: React.JSX.Element\n onClick?: (guid: string) => void\n showInsights?: boolean\n showLoader?: boolean\n transaction?: Transaction[]\n width?: number | string\n zeroState?: React.JSX.Element\n}\n\nconst TransactionList: React.FC<TransactionListProps> = ({\n bgcolor,\n filter,\n height = 'calc(100dvh - 36px)',\n loader = <Loader label=\"Loading\" size={40} />,\n onClick,\n showInsights = false,\n showLoader = false,\n transaction,\n width = '100%',\n zeroState = <ZeroState />,\n}) => {\n const { isLoading, sortedTransactions: allTransactions } = useTransactionStore()\n const transactions = React.useMemo(() => {\n const updatedTransactions = filter ? allTransactions.filter(filter) : allTransactions\n return transaction ?? updatedTransactions\n }, [allTransactions, filter, transaction])\n\n const { clearExpandedSplits, setShowInsights, toggleSplit } = useTransactionsUiStore()\n const { onEvent } = useEvent()\n\n const handleClick = (guid: string) => {\n const transaction = transactions.find((t) => t.guid === guid)\n\n if (transaction?.has_been_split) {\n toggleSplit(transaction.guid)\n return\n }\n\n onEvent(ANALYTICS_EVENTS.ACCOUNT_DETAILS_CLICK_TRANSACTION, {\n account_guid: transaction?.account_guid,\n transaction_guid: guid,\n })\n onClick?.(guid)\n }\n\n const parentRef = React.useRef<HTMLDivElement>(null)\n const rowVirtualizer = useVirtualizer({\n count: transactions.length,\n getScrollElement: () => parentRef.current,\n estimateSize: (i) => ROW_HEIGHT + (shouldShowDate(i, transactions) ? DATE_ROW_HEIGHT : 0),\n overscan: 5,\n })\n\n React.useEffect(() => rowVirtualizer.measure(), [transactions])\n React.useEffect(() => setShowInsights(showInsights), [showInsights])\n\n React.useEffect(() => {\n return () => clearExpandedSplits()\n }, [])\n\n return (\n <List component=\"div\" role=\"list\" sx={{ width: width }}>\n <Box height={height} overflow=\"auto\" ref={parentRef} role=\"presentation\" width={width}>\n <Box\n height={\n // set the height to auto when there are no transactions so the zero state isn't set to 0\n rowVirtualizer.getVirtualItems().length === 0 ? 'auto' : rowVirtualizer.getTotalSize()\n }\n position=\"relative\"\n role=\"presentation\"\n width=\"100%\"\n >\n {(isLoading || showLoader) && loader}\n {!isLoading && !showLoader && rowVirtualizer.getVirtualItems().length === 0 && zeroState}\n {!isLoading &&\n !showLoader &&\n rowVirtualizer.getVirtualItems().length > 0 &&\n rowVirtualizer.getVirtualItems().map((row) => {\n const transaction = transactions[row.index]\n const showDate = shouldShowDate(row.index, transactions)\n const isInset = hasInsetBorder(row.index, transactions)\n const rowHeight = ROW_HEIGHT + (showDate ? DATE_ROW_HEIGHT : 0)\n\n return (\n <Box\n key={transaction.guid}\n role=\"listitem\"\n sx={{\n height: rowHeight,\n position: 'absolute',\n transform: `translateY(${row.start}px)`,\n width: '100%',\n bgcolor: 'background.paper',\n }}\n >\n {showDate && (\n <SubheaderRow bgcolor={bgcolor}>\n {fromUnixUTCToDayOfWeekAndDate(transaction.date)}\n </SubheaderRow>\n )}\n <TransactionRow\n component=\"div\"\n {...(onClick && { onClick: handleClick })}\n transaction={transaction}\n />\n <Divider sx={{ ml: isInset ? 68 : 0 }} />\n </Box>\n )\n })}\n </Box>\n </Box>\n </List>\n )\n}\n\nexport default observer(TransactionList)\n"],"mappings":"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"}
1
+ {"version":3,"file":"TransactionList.es.js","names":[],"sources":["../../../../src/transactions/components/shared/TransactionList.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\nimport { useVirtualizer } from '@tanstack/react-virtual'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport List from '@mui/material/List'\n\nimport { ANALYTICS_EVENTS, Loader, useEvent, ZeroState } from '../../../common'\nimport { type Transaction } from '../../../core'\n\nimport { useTransactionsUiStore } from '../../context/hooks'\nimport { useTransactionStore } from '../../../common'\n\nimport SubheaderRow from '../../../common/components/SubheaderRow'\nimport TransactionRow from './transactionlist/TransactionRow'\n\nimport { hasInsetBorder, shouldShowDate } from '../../utils/Transactions'\nimport { fromUnixUTCToDayOfWeekAndDate } from '../../../core/utils/DateUtil'\n\nconst ROW_HEIGHT = 65\nconst DATE_ROW_HEIGHT = 32\n\nexport interface TransactionListProps {\n bgcolor?: string\n filter?: (t: Transaction) => boolean\n height?: number | string\n loader?: React.JSX.Element\n onClick?: (guid: string) => void\n showInsights?: boolean\n showLoader?: boolean\n transaction?: Transaction[]\n width?: number | string\n zeroState?: React.JSX.Element\n}\n\nconst TransactionList: React.FC<TransactionListProps> = ({\n bgcolor,\n filter,\n height = 'calc(100dvh - 36px)',\n loader = <Loader label=\"Loading\" size={40} />,\n onClick,\n showInsights = false,\n showLoader = false,\n transaction,\n width = '100%',\n zeroState = <ZeroState />,\n}) => {\n const { isLoading, sortedTransactions: allTransactions } = useTransactionStore()\n const transactions = React.useMemo(() => {\n const updatedTransactions = filter ? allTransactions.filter(filter) : allTransactions\n return transaction ?? updatedTransactions\n }, [allTransactions, filter, transaction])\n\n const { clearExpandedSplits, setShowInsights, toggleSplit } = useTransactionsUiStore()\n const { onEvent } = useEvent()\n\n const handleClick = (guid: string) => {\n const transaction = transactions.find((t) => t.guid === guid)\n\n if (transaction?.has_been_split) {\n toggleSplit(transaction.guid)\n return\n }\n\n onEvent(ANALYTICS_EVENTS.ACCOUNT_DETAILS_CLICK_TRANSACTION, {\n account_guid: transaction?.account_guid,\n transaction_guid: guid,\n })\n onClick?.(guid)\n }\n\n const parentRef = React.useRef<HTMLDivElement>(null)\n const rowVirtualizer = useVirtualizer({\n count: transactions.length,\n getScrollElement: () => parentRef.current,\n estimateSize: (i) => ROW_HEIGHT + (shouldShowDate(i, transactions) ? DATE_ROW_HEIGHT : 0),\n overscan: 5,\n })\n\n React.useEffect(() => rowVirtualizer.measure(), [transactions])\n React.useEffect(() => setShowInsights(showInsights), [showInsights])\n\n React.useEffect(() => {\n return () => clearExpandedSplits()\n }, [])\n\n return (\n <List component=\"div\" role=\"list\" sx={{ width: width }}>\n <Box height={height} overflow=\"auto\" ref={parentRef} role=\"presentation\" width={width}>\n <Box\n height={\n // set the height to auto when there are no transactions so the zero state isn't set to 0\n rowVirtualizer.getVirtualItems().length === 0 ? 'auto' : rowVirtualizer.getTotalSize()\n }\n position=\"relative\"\n role=\"presentation\"\n width=\"100%\"\n >\n {(isLoading || showLoader) && loader}\n {!isLoading && !showLoader && rowVirtualizer.getVirtualItems().length === 0 && zeroState}\n {!isLoading &&\n !showLoader &&\n rowVirtualizer.getVirtualItems().length > 0 &&\n rowVirtualizer.getVirtualItems().map((row) => {\n const transaction = transactions[row.index]\n const showDate = shouldShowDate(row.index, transactions)\n const isInset = hasInsetBorder(row.index, transactions)\n const rowHeight = ROW_HEIGHT + (showDate ? DATE_ROW_HEIGHT : 0)\n\n return (\n <Box\n key={transaction.guid}\n role=\"listitem\"\n sx={{\n height: rowHeight,\n position: 'absolute',\n transform: `translateY(${row.start}px)`,\n width: '100%',\n bgcolor: 'background.paper',\n }}\n >\n {showDate && (\n <SubheaderRow bgcolor={bgcolor}>\n {fromUnixUTCToDayOfWeekAndDate(transaction.date)}\n </SubheaderRow>\n )}\n <TransactionRow\n component=\"div\"\n {...(onClick && { onClick: handleClick })}\n transaction={transaction}\n />\n <Divider sx={{ ml: isInset ? 68 : 0 }} />\n </Box>\n )\n })}\n </Box>\n </Box>\n </List>\n )\n}\n\nexport default observer(TransactionList)\n"],"mappings":";;;;;;;;;;;;;;;;AAoBA,IAAM,IAAa,IACb,IAAkB,IAelB,IAAA,CAAmD,EACvD,SAAA,GACA,QAAA,GACA,QAAA,IAAS,uBACT,QAAA,IAAS,gBAAA,EAAC,GAAD;AAAA,EAAQ,OAAM;AAAA,EAAU,MAAM;AAAK,CAAA,GAC5C,SAAA,GACA,cAAA,IAAe,IACf,YAAA,IAAa,IACb,aAAA,GACA,OAAA,IAAQ,QACR,WAAA,IAAY,gBAAA,EAAC,GAAD,CAAY,CAAA,EAAA,MACpB;AACJ,QAAM,EAAE,WAAA,GAAW,oBAAoB,EAAA,IAAoB,EAAoB,GACzE,IAAe,EAAM,QAAA,MAAc;AACvC,UAAM,IAAsB,IAAS,EAAgB,OAAO,CAAM,IAAI;AACtE,WAAO,KAAe;AAAA,EACxB,GAAG;AAAA,IAAC;AAAA,IAAiB;AAAA,IAAQ;AAAA,EAAW,CAAC,GAEnC,EAAE,qBAAA,GAAqB,iBAAA,GAAiB,aAAA,EAAA,IAAgB,EAAuB,GAC/E,EAAE,SAAA,EAAA,IAAY,EAAS,GAEvB,IAAA,CAAe,MAAiB;AACpC,UAAM,IAAc,EAAa,KAAA,CAAM,MAAM,EAAE,SAAS,CAAI;AAE5D,QAAI,GAAa,gBAAgB;AAC/B,MAAA,EAAY,EAAY,IAAI;AAC5B;AAAA,IACF;AAEA,IAAA,EAAQ,EAAiB,mCAAmC;AAAA,MAC1D,cAAc,GAAa;AAAA,MAC3B,kBAAkB;AAAA,IACpB,CAAC,GACD,IAAU,CAAI;AAAA,EAChB,GAEM,IAAY,EAAM,OAAuB,IAAI,GAC7C,IAAiB,EAAe;AAAA,IACpC,OAAO,EAAa;AAAA,IACpB,kBAAA,MAAwB,EAAU;AAAA,IAClC,cAAA,CAAe,MAAM,KAAc,EAAe,GAAG,CAAY,IAAI,IAAkB;AAAA,IACvF,UAAU;AAAA,EACZ,CAAC;AAED,SAAA,EAAM,UAAA,MAAgB,EAAe,QAAQ,GAAG,CAAC,CAAY,CAAC,GAC9D,EAAM,UAAA,MAAgB,EAAgB,CAAY,GAAG,CAAC,CAAY,CAAC,GAEnE,EAAM,UAAA,MACJ,MAAa,EAAoB,GAChC,CAAC,CAAC,GAGH,gBAAA,EAAC,GAAD;AAAA,IAAM,WAAU;AAAA,IAAM,MAAK;AAAA,IAAO,IAAI,EAAS,OAAA,EAAM;AAAA,IACnD,UAAA,gBAAA,EAAC,GAAD;AAAA,MAAa,QAAA;AAAA,MAAQ,UAAS;AAAA,MAAO,KAAK;AAAA,MAAW,MAAK;AAAA,MAAsB,OAAA;AAAA,MAC9E,UAAA,gBAAA,EAAC,GAAD;AAAA,QACE,QAEE,EAAe,gBAAgB,EAAE,WAAW,IAAI,SAAS,EAAe,aAAa;AAAA,QAEvF,UAAS;AAAA,QACT,MAAK;AAAA,QACL,OAAM;AAAA,QAPR,UAAA;AAAA,WASI,KAAa,MAAe;AAAA,UAC7B,CAAC,KAAa,CAAC,KAAc,EAAe,gBAAgB,EAAE,WAAW,KAAK;AAAA,UAC9E,CAAC,KACA,CAAC,KACD,EAAe,gBAAgB,EAAE,SAAS,KAC1C,EAAe,gBAAgB,EAAE,IAAA,CAAK,MAAQ;AAC5C,kBAAM,IAAc,EAAa,EAAI,KAAA,GAC/B,IAAW,EAAe,EAAI,OAAO,CAAY,GACjD,IAAU,EAAe,EAAI,OAAO,CAAY;AAGtD,mBACE,gBAAA,EAAC,GAAD;AAAA,cAEE,MAAK;AAAA,cACL,IAAI;AAAA,gBACF,QAPY,KAAc,IAAW,IAAkB;AAAA,gBAQvD,UAAU;AAAA,gBACV,WAAW,cAAc,EAAI,KAAA;AAAA,gBAC7B,OAAO;AAAA,gBACP,SAAS;AAAA,cACX;AAAA,cATF,UAAA;AAAA,gBAWG,KACC,gBAAA,EAAC,GAAD;AAAA,kBAAuB,SAAA;AAAA,kBACpB,UAAA,EAA8B,EAAY,IAAI;AAAA,gBACnC,CAAA;AAAA,gBAEhB,gBAAA,EAAC,GAAD;AAAA,kBACE,WAAU;AAAA,kBACV,GAAK,KAAW,EAAE,SAAS,EAAY;AAAA,kBAC1B,aAAA;AAAA,gBACd,CAAA;AAAA,gBACD,gBAAA,EAAC,GAAD,EAAS,IAAI,EAAE,IAAI,IAAU,KAAK,EAAE,EAAI,CAAA;AAAA,cACrC;AAAA,YArBE,GAAA,EAAY,IAqBd;AAAA,UAET,CAAC;AAAA,QACA;AAAA;IACF,CAAA;AAAA,EACD,CAAA;AAEV,GAEA,KAAe,EAAS,CAAe"}
@@ -1,42 +1,46 @@
1
- import { CategoryGuidToName as m } from "../../../core/constants/Category.es.js";
2
- import { useEvent as g } from "../../../common/context/hooks.es.js";
1
+ import { CategoryGuidToName as g } from "../../../core/constants/Category.es.js";
2
+ import { useEvent as f } from "../../../common/context/hooks.es.js";
3
3
  import { ANALYTICS_EVENTS as b } from "../../../common/constants/Analytics.es.js";
4
- import { TRENDS_ANALYTICS_METADATA as f } from "../../constants/TrendsWidget.es.js";
5
- import { AccessibleSortIcon as p } from "./AccessibleSortIcon.es.js";
6
- import { jsx as T } from "react/jsx-runtime";
4
+ import p from "../../../common/components/ZeroState.es.js";
5
+ import { TRENDS_ANALYTICS_METADATA as T } from "../../constants/TrendsWidget.es.js";
6
+ import { AccessibleSortIcon as y } from "./AccessibleSortIcon.es.js";
7
+ import { jsx as d } from "react/jsx-runtime";
7
8
  import { useTheme as _ } from "@mui/material/styles";
8
- import { DataGridPro as y } from "@mui/x-data-grid-pro";
9
- var t = (e) => e.id !== "total" && !e.isParent, D = ({ columns: e, onRowClick: i, rows: d, totalRow: a }) => {
10
- const l = _(), { onEvent: u } = g(), n = l.palette.mode === "light", c = !!i, s = (r) => {
11
- t(r) && (i?.(r.category_guid), u(b.TRENDS_CLICK_LIST_ITEM, {
12
- ...f,
13
- listItem: m[r.category_guid] ?? r.category,
14
- destination: r.top_level_category_guid === r.category_guid ? "drill_down" : "drawer"
9
+ import { DataGridPro as v } from "@mui/x-data-grid-pro";
10
+ var S = () => /* @__PURE__ */ d(p, {}), t = (r) => r.id !== "total" && !r.isParent, M = ({ columns: r, onRowClick: i, rows: a, totalRow: n }) => {
11
+ const u = _(), { onEvent: c } = f(), s = u.palette.mode === "light", m = !!i, l = (e) => {
12
+ t(e) && (i?.(e.category_guid), c(b.TRENDS_CLICK_LIST_ITEM, {
13
+ ...T,
14
+ listItem: g[e.category_guid] ?? e.category,
15
+ destination: e.top_level_category_guid === e.category_guid ? "drill_down" : "drawer"
15
16
  }));
16
17
  };
17
- return /* @__PURE__ */ T(y, {
18
+ return /* @__PURE__ */ d(v, {
18
19
  autoHeight: !0,
19
- columns: e,
20
+ columns: r,
20
21
  disableColumnFilter: !0,
21
22
  disableColumnMenu: !0,
22
- getRowClassName: (r) => t(r.row) ? "" : "trends-row-static",
23
+ getRowClassName: (e) => t(e.row) ? "" : "trends-row-static",
23
24
  hideFooter: !0,
24
25
  initialState: { sorting: { sortModel: [{
25
26
  field: "category",
26
27
  sort: "asc"
27
28
  }] } },
28
- onCellKeyDown: (r, o) => {
29
- o.key !== "Enter" && o.key !== " " || t(r.row) && (o.preventDefault(), s(r.row));
29
+ onCellKeyDown: (e, o) => {
30
+ o.key !== "Enter" && o.key !== " " || t(e.row) && (o.preventDefault(), l(e.row));
30
31
  },
31
- onRowClick: (r) => s(r.row),
32
- pinnedRows: { bottom: a ? [a] : [] },
32
+ onRowClick: (e) => l(e.row),
33
+ pinnedRows: { bottom: n && a.length > 0 ? [n] : [] },
33
34
  rowHeight: 64,
34
- rows: d,
35
+ rows: a,
35
36
  slotProps: { baseIconButton: {
36
37
  color: "secondary",
37
38
  sx: { ml: 8 }
38
39
  } },
39
- slots: { columnHeaderSortIcon: p },
40
+ slots: {
41
+ columnHeaderSortIcon: y,
42
+ noRowsOverlay: S
43
+ },
40
44
  sortingOrder: ["asc", "desc"],
41
45
  sx: {
42
46
  borderColor: "divider",
@@ -44,17 +48,17 @@ var t = (e) => e.id !== "total" && !e.isParent, D = ({ columns: e, onRowClick: i
44
48
  borderStyle: "solid",
45
49
  borderRadius: 2,
46
50
  "& .MuiDataGrid-columnHeaders": {
47
- bgcolor: n ? "neutral.50" : "neutral.800",
51
+ bgcolor: s ? "neutral.50" : "neutral.800",
48
52
  borderBottom: "none"
49
53
  },
50
- "& .trends-table-header": { bgcolor: n ? "neutral.50" : "neutral.800" },
51
- "& .MuiDataGrid-row": { cursor: c ? "pointer" : "default" },
54
+ "& .trends-table-header": { bgcolor: s ? "neutral.50" : "neutral.800" },
55
+ "& .MuiDataGrid-row": { cursor: m ? "pointer" : "default" },
52
56
  "& .trends-row-static": { cursor: "default" }
53
57
  }
54
58
  });
55
59
  };
56
60
  export {
57
- D as TrendsTable
61
+ M as TrendsTable
58
62
  };
59
63
 
60
64
  //# sourceMappingURL=TrendsTable.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TrendsTable.es.js","names":[],"sources":["../../../../src/trends/components/trendstable/TrendsTable.tsx"],"sourcesContent":["import { ANALYTICS_EVENTS, useEvent } from '../../../common'\nimport { CategoryGuidToName } from '../../../core/constants'\nimport { TRENDS_ANALYTICS_METADATA } from '../../constants/TrendsWidget'\nimport { DataGridPro, GridColDef } from '@mui/x-data-grid-pro'\nimport { useTheme } from '@mui/material/styles'\nimport { TrendsTableRow } from '../../utils/TrendsTable'\nimport { AccessibleSortIcon } from './AccessibleSortIcon'\n\ninterface TrendsTableProps {\n columns: GridColDef[]\n onRowClick?: (category: string) => void\n rows: TrendsTableRow[]\n totalRow?: TrendsTableRow\n}\n\n// The pinned total row and the synthetic \"General [Parent]\" row (isParent: true,\n// only present in a drilled-in table) are summaries, not navigation destinations.\nconst isRowNavigable = (row: TrendsTableRow) => row.id !== 'total' && !row.isParent\n\nexport const TrendsTable = ({ columns, onRowClick, rows, totalRow }: TrendsTableProps) => {\n const theme = useTheme()\n const { onEvent } = useEvent()\n const isLightMode = theme.palette.mode === 'light'\n const isRowInteractive = Boolean(onRowClick)\n\n // Shared by pointer and keyboard activation; non-navigable rows are dropped so\n // neither path acts on them.\n const activateRow = (row: TrendsTableRow) => {\n if (!isRowNavigable(row)) return\n onRowClick?.(row.category_guid)\n onEvent(ANALYTICS_EVENTS.TRENDS_CLICK_LIST_ITEM, {\n ...TRENDS_ANALYTICS_METADATA,\n // Fall back to the row's display name for user-created categories, which\n // are absent from the static default-category map.\n listItem: CategoryGuidToName[row.category_guid] ?? row.category,\n // A top-level row (guid is its own top level) drills down; a sub-category\n // row opens the drawer.\n destination: row.top_level_category_guid === row.category_guid ? 'drill_down' : 'drawer',\n })\n }\n\n return (\n <DataGridPro\n // autoHeight sizes the grid to its content instead of measuring a flex\n // parent. The parent is an overflow:auto Stack with no fixed height, so the\n // default virtualized layout makes x-data-grid's useGridDimensions loop on\n // its own ResizeObserver measurement (a feedback loop that spikes to React's\n // \"Maximum update depth exceeded\" under a starved CI worker in jsdom). Content\n // sizing removes the measurement feedback and is correct for this unbounded,\n // page-scrolling table.\n autoHeight={true}\n columns={columns}\n disableColumnFilter={true}\n disableColumnMenu={true}\n getRowClassName={(params) => (isRowNavigable(params.row) ? '' : 'trends-row-static')}\n hideFooter={true}\n initialState={{ sorting: { sortModel: [{ field: 'category', sort: 'asc' }] } }}\n onCellKeyDown={(params, event) => {\n // Rows are reachable only by grid cell navigation, so Enter/Space on a\n // cell is the keyboard equivalent of clicking the row. Guard before\n // preventDefault so a non-navigable row keeps the grid's native key\n // handling instead of being swallowed with no action. Space would\n // otherwise scroll the grid.\n if (event.key !== 'Enter' && event.key !== ' ') return\n if (!isRowNavigable(params.row)) return\n event.preventDefault()\n activateRow(params.row)\n }}\n onRowClick={(r) => activateRow(r.row)}\n pinnedRows={{\n bottom: totalRow ? [totalRow] : [],\n }}\n rowHeight={64}\n rows={rows}\n slotProps={{ baseIconButton: { color: 'secondary', sx: { ml: 8 } } }}\n slots={{ columnHeaderSortIcon: AccessibleSortIcon }}\n sortingOrder={['asc', 'desc']}\n sx={{\n borderColor: 'divider',\n borderWidth: 1,\n borderStyle: 'solid',\n borderRadius: 2,\n '& .MuiDataGrid-columnHeaders': {\n bgcolor: isLightMode ? 'neutral.50' : 'neutral.800',\n borderBottom: 'none',\n },\n '& .trends-table-header': {\n bgcolor: isLightMode ? 'neutral.50' : 'neutral.800',\n },\n '& .MuiDataGrid-row': { cursor: isRowInteractive ? 'pointer' : 'default' },\n // getRowClassName stamps trends-row-static on every non-navigable row,\n // including the pinned total row.\n '& .trends-row-static': { cursor: 'default' },\n }}\n />\n )\n}\n"],"mappings":";;;;;;;;AAiBA,IAAM,IAAA,CAAkB,MAAwB,EAAI,OAAO,WAAW,CAAC,EAAI,UAE9D,IAAA,CAAe,EAAE,SAAA,GAAS,YAAA,GAAY,MAAA,GAAM,UAAA,EAAA,MAAiC;AACxF,QAAM,IAAQ,EAAS,GACjB,EAAE,SAAA,EAAA,IAAY,EAAS,GACvB,IAAc,EAAM,QAAQ,SAAS,SACrC,IAAmB,EAAQ,GAI3B,IAAA,CAAe,MAAwB;AAC3C,IAAK,EAAe,CAAG,MACvB,IAAa,EAAI,aAAa,GAC9B,EAAQ,EAAiB,wBAAwB;AAAA,MAC/C,GAAG;AAAA,MAGH,UAAU,EAAmB,EAAI,aAAA,KAAkB,EAAI;AAAA,MAGvD,aAAa,EAAI,4BAA4B,EAAI,gBAAgB,eAAe;AAAA,IAClF,CAAC;AAAA,EACH;AAEA,SACE,gBAAA,EAAC,GAAD;AAAA,IAQE,YAAY;AAAA,IACH,SAAA;AAAA,IACT,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,IACnB,iBAAA,CAAkB,MAAY,EAAe,EAAO,GAAG,IAAI,KAAK;AAAA,IAChE,YAAY;AAAA,IACZ,cAAc,EAAE,SAAS,EAAE,WAAW,CAAC;AAAA,MAAE,OAAO;AAAA,MAAY,MAAM;AAAA,IAAM,CAAC,EAAE,EAAE;AAAA,IAC7E,eAAA,CAAgB,GAAQ,MAAU;AAMhC,MAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,OACtC,EAAe,EAAO,GAAG,MAC9B,EAAM,eAAe,GACrB,EAAY,EAAO,GAAG;AAAA,IACxB;AAAA,IACA,YAAA,CAAa,MAAM,EAAY,EAAE,GAAG;AAAA,IACpC,YAAY,EACV,QAAQ,IAAW,CAAC,CAAQ,IAAI,CAAC,EACnC;AAAA,IACA,WAAW;AAAA,IACL,MAAA;AAAA,IACN,WAAW,EAAE,gBAAgB;AAAA,MAAE,OAAO;AAAA,MAAa,IAAI,EAAE,IAAI,EAAE;AAAA,IAAE,EAAE;AAAA,IACnE,OAAO,EAAE,sBAAsB,EAAmB;AAAA,IAClD,cAAc,CAAC,OAAO,MAAM;AAAA,IAC5B,IAAI;AAAA,MACF,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,gCAAgC;AAAA,QAC9B,SAAS,IAAc,eAAe;AAAA,QACtC,cAAc;AAAA,MAChB;AAAA,MACA,0BAA0B,EACxB,SAAS,IAAc,eAAe,cACxC;AAAA,MACA,sBAAsB,EAAE,QAAQ,IAAmB,YAAY,UAAU;AAAA,MAGzE,wBAAwB,EAAE,QAAQ,UAAU;AAAA,IAC9C;AAAA,EACD,CAAA;AAEL"}
1
+ {"version":3,"file":"TrendsTable.es.js","names":[],"sources":["../../../../src/trends/components/trendstable/TrendsTable.tsx"],"sourcesContent":["import { ANALYTICS_EVENTS, useEvent, ZeroState } from '../../../common'\nimport { CategoryGuidToName } from '../../../core/constants'\nimport { TRENDS_ANALYTICS_METADATA } from '../../constants/TrendsWidget'\nimport { DataGridPro, GridColDef } from '@mui/x-data-grid-pro'\nimport { useTheme } from '@mui/material/styles'\nimport { TrendsTableRow } from '../../utils/TrendsTable'\nimport { AccessibleSortIcon } from './AccessibleSortIcon'\n\n// The grid's default no-rows overlay is a bare \"No rows\". Render the same shared\n// zero state the app's other empty lists use instead. Wrapped because the\n// slot's prop type doesn't match ZeroState's; positioning is handled by the\n// grid's own overlay wrapper.\nconst TrendsTableNoRowsOverlay = () => <ZeroState />\n\ninterface TrendsTableProps {\n columns: GridColDef[]\n onRowClick?: (category: string) => void\n rows: TrendsTableRow[]\n totalRow?: TrendsTableRow\n}\n\n// The pinned total row and the synthetic \"General [Parent]\" row (isParent: true,\n// only present in a drilled-in table) are summaries, not navigation destinations.\nconst isRowNavigable = (row: TrendsTableRow) => row.id !== 'total' && !row.isParent\n\nexport const TrendsTable = ({ columns, onRowClick, rows, totalRow }: TrendsTableProps) => {\n const theme = useTheme()\n const { onEvent } = useEvent()\n const isLightMode = theme.palette.mode === 'light'\n const isRowInteractive = Boolean(onRowClick)\n\n // Shared by pointer and keyboard activation; non-navigable rows are dropped so\n // neither path acts on them.\n const activateRow = (row: TrendsTableRow) => {\n if (!isRowNavigable(row)) return\n onRowClick?.(row.category_guid)\n onEvent(ANALYTICS_EVENTS.TRENDS_CLICK_LIST_ITEM, {\n ...TRENDS_ANALYTICS_METADATA,\n // Fall back to the row's display name for user-created categories, which\n // are absent from the static default-category map.\n listItem: CategoryGuidToName[row.category_guid] ?? row.category,\n // A top-level row (guid is its own top level) drills down; a sub-category\n // row opens the drawer.\n destination: row.top_level_category_guid === row.category_guid ? 'drill_down' : 'drawer',\n })\n }\n\n return (\n <DataGridPro\n // autoHeight sizes the grid to its content instead of measuring a flex\n // parent. The parent is an overflow:auto Stack with no fixed height, so the\n // default virtualized layout makes x-data-grid's useGridDimensions loop on\n // its own ResizeObserver measurement (a feedback loop that spikes to React's\n // \"Maximum update depth exceeded\" under a starved CI worker in jsdom). Content\n // sizing removes the measurement feedback and is correct for this unbounded,\n // page-scrolling table.\n autoHeight={true}\n columns={columns}\n disableColumnFilter={true}\n disableColumnMenu={true}\n getRowClassName={(params) => (isRowNavigable(params.row) ? '' : 'trends-row-static')}\n hideFooter={true}\n initialState={{ sorting: { sortModel: [{ field: 'category', sort: 'asc' }] } }}\n onCellKeyDown={(params, event) => {\n // Rows are reachable only by grid cell navigation, so Enter/Space on a\n // cell is the keyboard equivalent of clicking the row. Guard before\n // preventDefault so a non-navigable row keeps the grid's native key\n // handling instead of being swallowed with no action. Space would\n // otherwise scroll the grid.\n if (event.key !== 'Enter' && event.key !== ' ') return\n if (!isRowNavigable(params.row)) return\n event.preventDefault()\n activateRow(params.row)\n }}\n onRowClick={(r) => activateRow(r.row)}\n pinnedRows={{\n // A pinned \"Total $0.00\" is meaningless with no rows above it, and while it\n // is present the grid suppresses the no-rows overlay entirely. Drop it so the\n // empty table shows the zero state instead.\n bottom: totalRow && rows.length > 0 ? [totalRow] : [],\n }}\n rowHeight={64}\n rows={rows}\n slotProps={{ baseIconButton: { color: 'secondary', sx: { ml: 8 } } }}\n slots={{\n columnHeaderSortIcon: AccessibleSortIcon,\n noRowsOverlay: TrendsTableNoRowsOverlay,\n }}\n sortingOrder={['asc', 'desc']}\n sx={{\n borderColor: 'divider',\n borderWidth: 1,\n borderStyle: 'solid',\n borderRadius: 2,\n '& .MuiDataGrid-columnHeaders': {\n bgcolor: isLightMode ? 'neutral.50' : 'neutral.800',\n borderBottom: 'none',\n },\n '& .trends-table-header': {\n bgcolor: isLightMode ? 'neutral.50' : 'neutral.800',\n },\n '& .MuiDataGrid-row': { cursor: isRowInteractive ? 'pointer' : 'default' },\n // getRowClassName stamps trends-row-static on every non-navigable row,\n // including the pinned total row.\n '& .trends-row-static': { cursor: 'default' },\n }}\n />\n )\n}\n"],"mappings":";;;;;;;;;AAYA,IAAM,IAAA,MAAiC,gBAAA,EAAC,GAAD,CAAY,CAAA,GAW7C,IAAA,CAAkB,MAAwB,EAAI,OAAO,WAAW,CAAC,EAAI,UAE9D,IAAA,CAAe,EAAE,SAAA,GAAS,YAAA,GAAY,MAAA,GAAM,UAAA,EAAA,MAAiC;AACxF,QAAM,IAAQ,EAAS,GACjB,EAAE,SAAA,EAAA,IAAY,EAAS,GACvB,IAAc,EAAM,QAAQ,SAAS,SACrC,IAAmB,EAAQ,GAI3B,IAAA,CAAe,MAAwB;AAC3C,IAAK,EAAe,CAAG,MACvB,IAAa,EAAI,aAAa,GAC9B,EAAQ,EAAiB,wBAAwB;AAAA,MAC/C,GAAG;AAAA,MAGH,UAAU,EAAmB,EAAI,aAAA,KAAkB,EAAI;AAAA,MAGvD,aAAa,EAAI,4BAA4B,EAAI,gBAAgB,eAAe;AAAA,IAClF,CAAC;AAAA,EACH;AAEA,SACE,gBAAA,EAAC,GAAD;AAAA,IAQE,YAAY;AAAA,IACH,SAAA;AAAA,IACT,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,IACnB,iBAAA,CAAkB,MAAY,EAAe,EAAO,GAAG,IAAI,KAAK;AAAA,IAChE,YAAY;AAAA,IACZ,cAAc,EAAE,SAAS,EAAE,WAAW,CAAC;AAAA,MAAE,OAAO;AAAA,MAAY,MAAM;AAAA,IAAM,CAAC,EAAE,EAAE;AAAA,IAC7E,eAAA,CAAgB,GAAQ,MAAU;AAMhC,MAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,OACtC,EAAe,EAAO,GAAG,MAC9B,EAAM,eAAe,GACrB,EAAY,EAAO,GAAG;AAAA,IACxB;AAAA,IACA,YAAA,CAAa,MAAM,EAAY,EAAE,GAAG;AAAA,IACpC,YAAY,EAIV,QAAQ,KAAY,EAAK,SAAS,IAAI,CAAC,CAAQ,IAAI,CAAC,EACtD;AAAA,IACA,WAAW;AAAA,IACL,MAAA;AAAA,IACN,WAAW,EAAE,gBAAgB;AAAA,MAAE,OAAO;AAAA,MAAa,IAAI,EAAE,IAAI,EAAE;AAAA,IAAE,EAAE;AAAA,IACnE,OAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,eAAe;AAAA,IACjB;AAAA,IACA,cAAc,CAAC,OAAO,MAAM;AAAA,IAC5B,IAAI;AAAA,MACF,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,gCAAgC;AAAA,QAC9B,SAAS,IAAc,eAAe;AAAA,QACtC,cAAc;AAAA,MAChB;AAAA,MACA,0BAA0B,EACxB,SAAS,IAAc,eAAe,cACxC;AAAA,MACA,sBAAsB,EAAE,QAAQ,IAAmB,YAAY,UAAU;AAAA,MAGzE,wBAAwB,EAAE,QAAQ,UAAU;AAAA,IAC9C;AAAA,EACD,CAAA;AAEL"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.4.65",
3
+ "version": "9.4.67",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- {"version":3,"file":"ZeroState.es.js","names":[],"sources":["../../../../../src/transactions/components/shared/transactionlist/ZeroState.tsx"],"sourcesContent":["import React from 'react'\nimport { observer } from 'mobx-react-lite'\n\nimport { Receipt as ReceiptOutlinedIcon } from '@mxenabled/mx-icons'\n\nimport Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport { useGlobalCopyStore } from '../../../../common'\n\ninterface ZeroStateProps {\n showIcon?: boolean\n showSubtitle?: boolean\n}\n\nconst ZeroState: React.FC<ZeroStateProps> = ({ showIcon = true, showSubtitle = true }) => {\n const { transactions: copy } = useGlobalCopyStore()\n\n return (\n <Stack alignItems=\"center\" gap={12} height=\"auto\" mb={24} mt={24}>\n {showIcon && <ReceiptOutlinedIcon color=\"action\" sx={{ fontSize: 32 }} />}\n <Text bold={true} color=\"text.secondary\" variant=\"body2\">\n {copy.zero_state_no_transactions}\n </Text>\n {showSubtitle && (\n <Text color=\"text.secondary\" variant=\"caption\">\n {copy.zero_state_there_are_no_transactions}\n </Text>\n )}\n </Stack>\n )\n}\n\nexport default observer(ZeroState)\n"],"mappings":";;;;;;;AAgBA,IAAM,IAAA,CAAuC,EAAE,UAAA,IAAW,IAAM,cAAA,IAAe,GAAA,MAAW;AACxF,QAAM,EAAE,cAAc,EAAA,IAAS,EAAmB;AAElD,SACE,gBAAA,EAAC,GAAD;AAAA,IAAO,YAAW;AAAA,IAAS,KAAK;AAAA,IAAI,QAAO;AAAA,IAAO,IAAI;AAAA,IAAI,IAAI;AAAA,IAA9D,UAAA;AAAA,MACG,KAAY,gBAAA,EAAC,GAAD;AAAA,QAAqB,OAAM;AAAA,QAAS,IAAI,EAAE,UAAU,GAAG;AAAA,MAAI,CAAA;AAAA,MACxE,gBAAA,EAAC,GAAD;AAAA,QAAM,MAAM;AAAA,QAAM,OAAM;AAAA,QAAiB,SAAQ;AAAA,QAC9C,UAAA,EAAK;AAAA,MACF,CAAA;AAAA,MACL,KACC,gBAAA,EAAC,GAAD;AAAA,QAAM,OAAM;AAAA,QAAiB,SAAQ;AAAA,QAClC,UAAA,EAAK;AAAA,MACF,CAAA;AAAA,IAEH;AAAA;AAEX,GAEA,IAAe,EAAS,CAAS"}