@mx-cartographer/experiences 9.4.22 → 9.4.23

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 (40) hide show
  1. package/CHANGELOG.md +12 -2
  2. package/dist/core/stores/InsightsV2Store.d.ts +23 -4
  3. package/dist/core/stores/InsightsV2Store.es.js +16 -7
  4. package/dist/core/stores/InsightsV2Store.es.js.map +1 -1
  5. package/dist/core/types/Insights.d.ts +2 -0
  6. package/dist/core/types/localization/InsightsFeedCopy.d.ts +1 -0
  7. package/dist/insights-v2/actionBlocks/ActionBlockLayer.es.js +15 -14
  8. package/dist/insights-v2/actionBlocks/ActionBlockLayer.es.js.map +1 -1
  9. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/transactionDetailsActions.d.ts +1 -2
  10. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/transactionDetailsActions.es.js +8 -14
  11. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/transactionDetailsActions.es.js.map +1 -1
  12. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.es.js +9 -8
  13. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.es.js.map +1 -1
  14. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/util.d.ts +3 -0
  15. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/util.es.js +8 -0
  16. package/dist/insights-v2/actionBlocks/TransactionDetailsBlock/util.es.js.map +1 -0
  17. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.d.ts +2 -1
  18. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.es.js +37 -34
  19. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.es.js.map +1 -1
  20. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js +89 -73
  21. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionHistoryBlock.es.js.map +1 -1
  22. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/layout.d.ts +1 -1
  23. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/layout.es.js.map +1 -1
  24. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/utils.d.ts +1 -1
  25. package/dist/insights-v2/actionBlocks/TransactionHistoryBlock/utils.es.js.map +1 -1
  26. package/dist/insights-v2/actionBlocks/util.d.ts +13 -0
  27. package/dist/insights-v2/actionBlocks/util.es.js +7 -0
  28. package/dist/insights-v2/actionBlocks/util.es.js.map +1 -0
  29. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js +19 -15
  30. package/dist/insights-v2/blocks/ChartBlocks/BarchartBlock/BarchartBlock.es.js.map +1 -1
  31. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js +15 -13
  32. package/dist/insights-v2/blocks/ChartBlocks/DoubleBarChartBlock/DoubleBarChartBlock.es.js.map +1 -1
  33. package/dist/insights-v2/blocks/ChartBlocks/StepChartBlock/StepChartBlock.d.ts +1 -1
  34. package/dist/insights-v2/blocks/ChartBlocks/StepChartBlock/StepChartBlock.es.js.map +1 -1
  35. package/dist/insights-v2/mappings/actionBlocksKey.d.ts +6 -0
  36. package/dist/insights-v2/mappings/actionBlocksKey.es.js +11 -0
  37. package/dist/insights-v2/mappings/actionBlocksKey.es.js.map +1 -0
  38. package/dist/insights-v2/mappings/blocks.es.js +47 -46
  39. package/dist/insights-v2/mappings/blocks.es.js.map +1 -1
  40. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [9.4.23] - 09-16-2026
2
+
3
+ - **ADDED** - Nested-drawer support for the insights-v2 `TransactionHistoryBlock`: clicking a transaction row in the history drawer opens a second, stacked `TransactionDetailsBlock` drawer scoped to that transaction, via `InsightsV2Store.setActionContext({ transaction_guid })` and `useActionContext<DrilldownPayload>()`. `TransactionDrillDown`'s row click is forwarded through a new `onEachRowClick` prop (WEC-1699)
4
+ - **ADDED** - `InsightsV2/ActionBlock/NestedDrawers` Storybook story demonstrating the full history → details drilldown through the real action-block registry (WEC-1699)
5
+ - **ADDED** - `transaction_details_title` copy key (`insights_feed.general`) for the nested `TransactionDetailsBlock` drawer's title (WEC-1699)
6
+ - **ADDED** - Shared CTA-resolution helpers (`getDynamicCtaBasedOnTriggers`, `getCtaForChartBarClick` in `insights-v2/actionBlocks/util.ts`) resolving which CTA (primary/secondary) drives a drawer based on its trigger, with a fallback to the primary CTA whenever resolution comes up empty; `actionBlocksKey` constants extracted for the action-block registry keys in `mappings/blocks.ts` (WEC-1699)
7
+ - **CHANGED** - `TransactionDetailsBlock`'s bottom actions are now resolved from the triggering CTA's `variant` via `getBottomActionsByVariant` instead of `instance_slot_data.bottom_actions`: the `fee_detected` variant gets `DEFAULT_BOTTOM_ACTIONS` (Split/Hide/Merchant-Logo), everything else gets `[BottomActions.MerchantBudget, ...DEFAULT_BOTTOM_ACTIONS]` — so the nested `TransactionDetailsBlock` drawer shows "Add Merchant Budget" by default when the transaction has a `merchant_guid`. Clicking it opens the existing `MerchantBudgetDetailsDrawer` as a third, further-stacked drawer; no changes were made to that budgets code itself. `DEFAULT_BOTTOM_ACTIONS` itself (`transactions/constants/Actions.ts`) is unchanged — every other `TransactionDetails` caller still omits `MerchantBudget` by default unless it opts in via an explicit `bottomActions` prop (WEC-1699)
8
+ - **CHANGED** - `BarchartBlock`/`DoubleBarChartBlock`'s chart-bar drilldown context now carries an explicit target `block` (`DrilldownPayload.block`), used by the new CTA-resolution helpers to pick the correct CTA for a chart-bar click (WEC-1699)
9
+ - **FIXED** - `InsightsV2Store.setActionContext` now merges new keys into the current drawer session's context bag instead of destructively replacing it, so an outer drawer's context (e.g. `chartBarIndex`) survives while a nested drawer layers its own key (e.g. `transaction_guid`) on top (WEC-1699)
10
+
1
11
  ## [9.4.22] - 09-12-2026
2
12
 
3
13
  - **FIXED** - The category-change confirmation dialog (and all `common` `Dialog` modals) read their title twice on screen readers: the title was both the dialog's accessible name and a separate visible heading node. The dialog now labels itself via `aria-labelledby` pointing at the heading, and passes `ariaHidden` so the heading is removed from the a11y tree, so the title is announced once
@@ -12,7 +22,7 @@
12
22
 
13
23
  - **ADDED** - DataDog RUM for Pulse and MDB
14
24
 
15
- ## [9.4.19] - 09-15-2026
25
+ ## [9.4.19] - 09-14-2026
16
26
 
17
27
  - **ADDED** - insights-v2 `ObsolesceBanner` component: presentational banner displaying beat obsolescence states (refresh_available, refreshing, updated, not_refreshable, hidden) with smooth Collapse animation, proper ARIA labels, and state-appropriate icons (Sync/CheckCircle/Cancel) and actions (Update/Dismiss buttons). Exported from insights-v2 with full TypeScript types (`ObsolesceBannerProps`, `ObsolesceBannerState`, `ObsolesceBannerCopy`). Component accepts state + callbacks + copy as props; host owns data logic (WEC-1766)
18
28
  - **CHANGED** - `ObsolesceBanner` reuses existing `insights_feed.general` copy keys (`dismiss`, `insight_no_longer_applicable`, `insight_updated`, `new_information_available`, `update`, `updating`) rather than introducing a dedicated copy section — matches the copy already consumed by the legacy `ObsoleteManager` and defined in mrs_content, avoiding duplicate keys and translations. `GeneralInsightsFeedCopy` extended with these keys; `BaseLayout` passes `copy.insights_feed.general` straight through (WEC-1766)
@@ -20,7 +30,7 @@
20
30
  - **ADDED** - Comprehensive test coverage: 20 `ObsolesceBanner` tests (all 5 states, button interactions, copy variations, state transitions, callback isolation) plus `BaseLayout` obsolete tests (banner render, dimming overlay, click blocking, callbacks) (WEC-1766)
21
31
  - **ADDED** - Storybook stories for `ObsolesceBanner`: 5 static state stories plus 1 interactive state-machine story with debug panel and automatic transitions (WEC-1766)
22
32
 
23
- ## [9.4.18] - 09-11-2026
33
+ ## [9.4.18] - 09-14-2026
24
34
 
25
35
  - **CHANGED** - insights-v2 feedback UI cleanup: removed verbose comments and section dividers from `BaseLayout`, `FeedbackDialog`, `FeedbackBar`, `HiddenConfirmationCard`, `DismissInsightDialog`, `InsightOptionsMenu`, and `useBeatFeedbackFlow`; code is now self-documenting with brief one-line descriptions only where complexity warrants explanation. Minimal comment philosophy applied throughout (WEC-1766)
26
36
  - **CHANGED** - insights-v2 dismiss flow simplified: replaced controlled `dismissState` prop with direct `beat.is_dismissed` observation paired with local `hasClosedConfirmation` state in `useBeatFeedbackFlow`; `cardState` now derived via `useMemo` from these two sources. Eliminates need for parent-managed dismiss state while maintaining clean separation: Pulse owns persistence (`is_dismissed` property), experiences owns transient UI state (confirmation visibility). Survives navigation and handles API failures gracefully (WEC-1766)
@@ -5,10 +5,18 @@ export interface ActionDrawerState {
5
5
  trigger: ActionDrawerTrigger;
6
6
  guid: string;
7
7
  /**
8
- * Block-specific drilldown data, opaque to the store. Each action block defines
9
- * and reads its own shape (via useActionContext<T>()), so adding a block never
10
- * widens this envelope. Chart drilldowns put `{ chartBarIndex, tabIndex }` here;
11
- * CTAs carry none.
8
+ * Block-specific drilldown data for the current drawer SESSION, opaque to the
9
+ * store. Each action block defines and reads its own shape (via
10
+ * useActionContext<T>()). Chart drilldowns put `{ chartBarIndex, tabIndex }`
11
+ * here; CTAs carry none.
12
+ *
13
+ * This is an accumulating bag, not a single owner's value: a nested drawer
14
+ * (e.g. TransactionDetailsBlock opened from a row inside TransactionHistory
15
+ * Block) adds its own key via `setActionContext` ON TOP of whatever the outer
16
+ * drawer already put here, so the outer block's own context survives while the
17
+ * nested block is open. It resets to a clean slate only when a NEW drawer
18
+ * session starts (`openActionDrawer`/`openCtaDrawer`, which fully replace the
19
+ * envelope) — not on every `setActionContext` call.
12
20
  */
13
21
  context: unknown;
14
22
  }
@@ -28,6 +36,17 @@ export declare class InsightsV2Store {
28
36
  globalStore: GlobalStore;
29
37
  actionDrawer: ActionDrawerState;
30
38
  constructor(globalStore: GlobalStore);
39
+ /**
40
+ * Merges keys into the current drawer session's context bag — it does NOT
41
+ * replace it. A nested drawer (e.g. a row click inside TransactionHistoryBlock
42
+ * opening TransactionDetailsBlock) calls this to layer its own key (e.g.
43
+ * `transaction_guid`) on top of whatever context the outer drawer already set
44
+ * (e.g. `chartBarIndex`), so the outer block keeps reading its own keys via
45
+ * useActionContext while the nested block is open. The bag only returns to a
46
+ * clean slate when a new drawer session starts via `openActionDrawer`/
47
+ * `openCtaDrawer`, which fully replace the envelope.
48
+ */
49
+ setActionContext: (context: Record<string, unknown>) => void;
31
50
  /**
32
51
  * Generic drawer opener — the only opener a new action block needs. Pass the
33
52
  * beat guid, the CTA/source that triggered it, and (optionally) a block-specific
@@ -4,24 +4,33 @@ var o = {
4
4
  trigger: "primaryCta",
5
5
  guid: "",
6
6
  context: void 0
7
- }, s = class {
7
+ }, n = class {
8
8
  globalStore;
9
9
  actionDrawer = o;
10
10
  constructor(r) {
11
11
  this.globalStore = r, a(this);
12
12
  }
13
- openActionDrawer = ({ guid: r, trigger: e, context: t }) => {
13
+ setActionContext = (r) => {
14
+ this.actionDrawer = {
15
+ ...this.actionDrawer,
16
+ context: {
17
+ ...this.actionDrawer.context,
18
+ ...r
19
+ }
20
+ };
21
+ };
22
+ openActionDrawer = ({ guid: r, trigger: t, context: e }) => {
14
23
  this.actionDrawer = {
15
24
  isDrawerOpen: !0,
16
- trigger: e,
25
+ trigger: t,
17
26
  guid: r,
18
- context: t
27
+ context: e
19
28
  };
20
29
  };
21
- openCtaDrawer = (r, e) => {
30
+ openCtaDrawer = (r, t) => {
22
31
  this.openActionDrawer({
23
32
  guid: r,
24
- trigger: e
33
+ trigger: t
25
34
  });
26
35
  };
27
36
  closeActionDrawer = () => {
@@ -34,7 +43,7 @@ var o = {
34
43
  };
35
44
  export {
36
45
  o as CLOSED_ACTION_DRAWER,
37
- s as InsightsV2Store
46
+ n as InsightsV2Store
38
47
  };
39
48
 
40
49
  //# sourceMappingURL=InsightsV2Store.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InsightsV2Store.es.js","names":[],"sources":["../../../src/core/stores/InsightsV2Store.ts"],"sourcesContent":["import { makeAutoObservable } from 'mobx'\n\nimport type { GlobalStore } from './GlobalStore'\n\nexport type ActionDrawerTrigger = 'primaryCta' | 'secondaryCta' | 'chartBar'\n\nexport interface ActionDrawerState {\n isDrawerOpen: boolean\n trigger: ActionDrawerTrigger\n guid: string\n /**\n * Block-specific drilldown data, opaque to the store. Each action block defines\n * and reads its own shape (via useActionContext<T>()), so adding a block never\n * widens this envelope. Chart drilldowns put `{ chartBarIndex, tabIndex }` here;\n * CTAs carry none.\n */\n context: unknown\n}\n\nexport const CLOSED_ACTION_DRAWER: ActionDrawerState = {\n isDrawerOpen: false,\n trigger: 'primaryCta',\n guid: '',\n context: undefined,\n}\n\ninterface OpenActionDrawerArgs {\n guid: string\n trigger: ActionDrawerTrigger\n context?: unknown\n}\n\n/**\n * UI state shared across the insights-v2 widget tree. Owns the action drawer so\n * cards, charts, and action blocks coordinate through the store instead of prop\n * drilling. The drawer state is a fixed envelope (isDrawerOpen/guid/trigger) plus\n * an opaque `context` bag, so per-block drilldown data never leaks into this shape.\n */\nexport class InsightsV2Store {\n globalStore: GlobalStore\n\n actionDrawer: ActionDrawerState = CLOSED_ACTION_DRAWER\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n\n makeAutoObservable(this)\n }\n\n /**\n * Generic drawer opener — the only opener a new action block needs. Pass the\n * beat guid, the CTA/source that triggered it, and (optionally) a block-specific\n * context object the block reads back via useActionContext.\n */\n openActionDrawer = ({ guid, trigger, context }: OpenActionDrawerArgs) => {\n this.actionDrawer = { isDrawerOpen: true, trigger, guid, context }\n }\n\n /** Convenience opener for CTA drawers (no drilldown context). */\n openCtaDrawer = (guid: string, trigger: 'primaryCta' | 'secondaryCta') => {\n this.openActionDrawer({ guid, trigger })\n }\n\n closeActionDrawer = () => {\n // Preserve `trigger` + `context` so the drawer keeps its variant-specific\n // title/content through the slide-out animation (ActionBlockLayer stays\n // mounted while closing). Only flip isDrawerOpen off and clear the beat guid.\n this.actionDrawer = { ...this.actionDrawer, isDrawerOpen: false, guid: '' }\n }\n}\n"],"mappings":";AAmBA,IAAa,IAA0C;AAAA,EACrD,cAAc;AAAA,EACd,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX,GAca,IAAb,MAA6B;AAAA,EAC3B;AAAA,EAEA,eAAkC;AAAA,EAElC,YAAY,GAA0B;AACpC,SAAK,cAAc,GAEnB,EAAmB,IAAI;AAAA,EACzB;AAAA,EAOA,mBAAA,CAAoB,EAAE,MAAA,GAAM,SAAA,GAAS,SAAA,EAAA,MAAoC;AACvE,SAAK,eAAe;AAAA,MAAE,cAAc;AAAA,MAAM,SAAA;AAAA,MAAS,MAAA;AAAA,MAAM,SAAA;AAAA,IAAQ;AAAA,EACnE;AAAA,EAGA,gBAAA,CAAiB,GAAc,MAA2C;AACxE,SAAK,iBAAiB;AAAA,MAAE,MAAA;AAAA,MAAM,SAAA;AAAA,IAAQ,CAAC;AAAA,EACzC;AAAA,EAEA,oBAAA,MAA0B;AAIxB,SAAK,eAAe;AAAA,MAAE,GAAG,KAAK;AAAA,MAAc,cAAc;AAAA,MAAO,MAAM;AAAA,IAAG;AAAA,EAC5E;AACF"}
1
+ {"version":3,"file":"InsightsV2Store.es.js","names":[],"sources":["../../../src/core/stores/InsightsV2Store.ts"],"sourcesContent":["import { makeAutoObservable } from 'mobx'\n\nimport type { GlobalStore } from './GlobalStore'\n\nexport type ActionDrawerTrigger = 'primaryCta' | 'secondaryCta' | 'chartBar'\n\nexport interface ActionDrawerState {\n isDrawerOpen: boolean\n trigger: ActionDrawerTrigger\n guid: string\n /**\n * Block-specific drilldown data for the current drawer SESSION, opaque to the\n * store. Each action block defines and reads its own shape (via\n * useActionContext<T>()). Chart drilldowns put `{ chartBarIndex, tabIndex }`\n * here; CTAs carry none.\n *\n * This is an accumulating bag, not a single owner's value: a nested drawer\n * (e.g. TransactionDetailsBlock opened from a row inside TransactionHistory\n * Block) adds its own key via `setActionContext` ON TOP of whatever the outer\n * drawer already put here, so the outer block's own context survives while the\n * nested block is open. It resets to a clean slate only when a NEW drawer\n * session starts (`openActionDrawer`/`openCtaDrawer`, which fully replace the\n * envelope) — not on every `setActionContext` call.\n */\n context: unknown\n}\n\nexport const CLOSED_ACTION_DRAWER: ActionDrawerState = {\n isDrawerOpen: false,\n trigger: 'primaryCta',\n guid: '',\n context: undefined,\n}\n\ninterface OpenActionDrawerArgs {\n guid: string\n trigger: ActionDrawerTrigger\n context?: unknown\n}\n\n/**\n * UI state shared across the insights-v2 widget tree. Owns the action drawer so\n * cards, charts, and action blocks coordinate through the store instead of prop\n * drilling. The drawer state is a fixed envelope (isDrawerOpen/guid/trigger) plus\n * an opaque `context` bag, so per-block drilldown data never leaks into this shape.\n */\nexport class InsightsV2Store {\n globalStore: GlobalStore\n\n actionDrawer: ActionDrawerState = CLOSED_ACTION_DRAWER\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n\n makeAutoObservable(this)\n }\n\n /**\n * Merges keys into the current drawer session's context bag — it does NOT\n * replace it. A nested drawer (e.g. a row click inside TransactionHistoryBlock\n * opening TransactionDetailsBlock) calls this to layer its own key (e.g.\n * `transaction_guid`) on top of whatever context the outer drawer already set\n * (e.g. `chartBarIndex`), so the outer block keeps reading its own keys via\n * useActionContext while the nested block is open. The bag only returns to a\n * clean slate when a new drawer session starts via `openActionDrawer`/\n * `openCtaDrawer`, which fully replace the envelope.\n */\n setActionContext = (context: Record<string, unknown>) => {\n this.actionDrawer = {\n ...this.actionDrawer,\n context: { ...(this.actionDrawer.context as Record<string, unknown> | undefined), ...context },\n }\n }\n\n /**\n * Generic drawer opener — the only opener a new action block needs. Pass the\n * beat guid, the CTA/source that triggered it, and (optionally) a block-specific\n * context object the block reads back via useActionContext.\n */\n openActionDrawer = ({ guid, trigger, context }: OpenActionDrawerArgs) => {\n this.actionDrawer = { isDrawerOpen: true, trigger, guid, context }\n }\n\n /** Convenience opener for CTA drawers (no drilldown context). */\n openCtaDrawer = (guid: string, trigger: 'primaryCta' | 'secondaryCta') => {\n this.openActionDrawer({ guid, trigger })\n }\n\n closeActionDrawer = () => {\n // Preserve `trigger` + `context` so the drawer keeps its variant-specific\n // title/content through the slide-out animation (ActionBlockLayer stays\n // mounted while closing). Only flip isDrawerOpen off and clear the beat guid.\n this.actionDrawer = { ...this.actionDrawer, isDrawerOpen: false, guid: '' }\n }\n}\n"],"mappings":";AA2BA,IAAa,IAA0C;AAAA,EACrD,cAAc;AAAA,EACd,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX,GAca,IAAb,MAA6B;AAAA,EAC3B;AAAA,EAEA,eAAkC;AAAA,EAElC,YAAY,GAA0B;AACpC,SAAK,cAAc,GAEnB,EAAmB,IAAI;AAAA,EACzB;AAAA,EAYA,mBAAA,CAAoB,MAAqC;AACvD,SAAK,eAAe;AAAA,MAClB,GAAG,KAAK;AAAA,MACR,SAAS;AAAA,QAAE,GAAI,KAAK,aAAa;AAAA,QAAiD,GAAG;AAAA,MAAQ;AAAA,IAC/F;AAAA,EACF;AAAA,EAOA,mBAAA,CAAoB,EAAE,MAAA,GAAM,SAAA,GAAS,SAAA,EAAA,MAAoC;AACvE,SAAK,eAAe;AAAA,MAAE,cAAc;AAAA,MAAM,SAAA;AAAA,MAAS,MAAA;AAAA,MAAM,SAAA;AAAA,IAAQ;AAAA,EACnE;AAAA,EAGA,gBAAA,CAAiB,GAAc,MAA2C;AACxE,SAAK,iBAAiB;AAAA,MAAE,MAAA;AAAA,MAAM,SAAA;AAAA,IAAQ,CAAC;AAAA,EACzC;AAAA,EAEA,oBAAA,MAA0B;AAIxB,SAAK,eAAe;AAAA,MAAE,GAAG,KAAK;AAAA,MAAc,cAAc;AAAA,MAAO,MAAM;AAAA,IAAG;AAAA,EAC5E;AACF"}
@@ -12,6 +12,8 @@ export interface ThemedSVGImageProps {
12
12
  export interface DrilldownPayload {
13
13
  chartBarIndex: number;
14
14
  tabIndex?: number;
15
+ transaction_guid?: string;
16
+ block?: string;
15
17
  }
16
18
  export interface InsightsPayload {
17
19
  widget_type: 'full' | 'mini' | 'micro';
@@ -14,6 +14,7 @@ interface GeneralInsightsFeedCopy {
14
14
  tip_section_message: string;
15
15
  tip_section_title: string;
16
16
  transaction_history_title: string;
17
+ transaction_details_title: string;
17
18
  trend: string;
18
19
  update: string;
19
20
  updating: string;
@@ -1,35 +1,36 @@
1
- import { useGlobalCopyStore as y, useGlobalUiStore as k, useInsightsV2Store as g } from "../../common/context/hooks.es.js";
1
+ import { useGlobalCopyStore as y, useGlobalUiStore as g, useInsightsV2Store as k } from "../../common/context/hooks.es.js";
2
2
  import C from "../../common/components/drawer/Drawer.es.js";
3
3
  import h from "../../common/components/Loader.es.js";
4
- import { actionBlocks as B, hasDrawerBlock as _ } from "../mappings/blocks.es.js";
5
- import { observer as b } from "mobx-react-lite";
6
- import w from "@mui/material/Stack";
4
+ import { getDynamicCtaBasedOnTriggers as B } from "./util.es.js";
5
+ import { actionBlocks as _, hasDrawerBlock as b } from "../mappings/blocks.es.js";
6
+ import { observer as w } from "mobx-react-lite";
7
+ import D from "@mui/material/Stack";
7
8
  import { Text as v } from "@mxenabled/mxui";
8
9
  import { jsx as e } from "react/jsx-runtime";
9
- var D = ({ actionBlock: l, ...o }) => {
10
- const { Component: n, usePrepare: t } = l;
10
+ var L = ({ actionBlock: s, ...o }) => {
11
+ const { Component: n, usePrepare: t } = s;
11
12
  return t(o), /* @__PURE__ */ e(n, { ...o });
12
- }, j = b(function({ beat: o }) {
13
- const n = y(), t = n.common, { isCopyLoaded: m } = k(), { actionDrawer: c, closeActionDrawer: p } = g(), s = c.isDrawerOpen && c.guid === o.guid;
14
- if (!m) return s ? /* @__PURE__ */ e(h, {}) : null;
13
+ }, R = w(function({ beat: o }) {
14
+ const n = y(), t = n.common, { isCopyLoaded: m } = g(), { actionDrawer: a, closeActionDrawer: p } = k(), l = a.isDrawerOpen && a.guid === o.guid;
15
+ if (!m) return l ? /* @__PURE__ */ e(h, {}) : null;
15
16
  if (!o.insights_payload) return null;
16
- const { primary_cta: u, secondary_cta: d } = o.insights_payload, r = c.trigger === "secondaryCta" ? d : u, a = _(r?.block), i = a ? B[r?.block] : void 0, f = i ? i.title?.(r?.variant, n) ?? r?.label ?? "" : a ? t.error_heading : r?.label ?? "";
17
+ const { primary_cta: u, secondary_cta: d } = o.insights_payload, r = B(a, u, d), c = b(r?.block), i = c ? _[r?.block] : void 0, f = i ? i.title?.(r?.variant, n) ?? r?.label ?? "" : c ? t.error_heading : r?.label ?? "";
17
18
  return /* @__PURE__ */ e(C, {
18
19
  ariaLabelClose: t.close_aria,
19
- isOpen: s,
20
+ isOpen: l,
20
21
  onClose: p,
21
22
  title: f,
22
- children: i ? /* @__PURE__ */ e(D, {
23
+ children: i ? /* @__PURE__ */ e(L, {
23
24
  actionBlock: i,
24
25
  beat: o
25
- }, r?.block) : a ? /* @__PURE__ */ e(w, {
26
+ }, r?.block) : c ? /* @__PURE__ */ e(D, {
26
27
  sx: { p: 24 },
27
28
  children: /* @__PURE__ */ e(v, { children: t.error_message })
28
29
  }) : null
29
30
  });
30
31
  });
31
32
  export {
32
- j as ActionBlockLayer
33
+ R as ActionBlockLayer
33
34
  };
34
35
 
35
36
  //# sourceMappingURL=ActionBlockLayer.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActionBlockLayer.es.js","names":[],"sources":["../../../src/insights-v2/actionBlocks/ActionBlockLayer.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\nimport { observer } from 'mobx-react-lite'\n\nimport {\n Drawer,\n Loader,\n useGlobalCopyStore,\n useGlobalUiStore,\n useInsightsV2Store,\n} from '../../common'\nimport { type Beat } from '../../core'\nimport {\n actionBlocks,\n hasDrawerBlock,\n type ActionBlockEntry,\n type ActionBlockProps,\n} from '../mappings/blocks'\n\ninterface ActionBlockLayerProps {\n beat: Beat\n}\n\n/**\n * Renders a registered action block. Callers MUST key this per block name — a\n * block with `usePrepare` and one without run a different number of hooks, so\n * reusing the same fiber across a block switch violates the rules of hooks.\n */\nconst ActionBlockRunner = ({\n actionBlock,\n ...blockProps\n}: ActionBlockProps & { actionBlock: ActionBlockEntry }) => {\n const { Component, usePrepare } = actionBlock\n\n usePrepare(blockProps)\n\n return <Component {...blockProps} />\n}\n\n// `observer` is required: this reads `isCopyLoaded` off GlobalUiStore and the\n// action drawer off InsightsV2Store. Without it the component never re-renders\n// and stays stuck on <Loader /> forever.\nexport const ActionBlockLayer = observer(function ActionBlockLayer({\n beat,\n}: ActionBlockLayerProps) {\n const copy = useGlobalCopyStore()\n const commonCopy = copy.common\n const { isCopyLoaded } = useGlobalUiStore()\n const { actionDrawer, closeActionDrawer } = useInsightsV2Store()\n\n // Every card in the feed renders its own layer against the shared store, so\n // this card's drawer only opens when its beat is the one that triggered it.\n const isCurrentBeatOpen = actionDrawer.isDrawerOpen && actionDrawer.guid === beat.guid\n\n if (!isCopyLoaded) return isCurrentBeatOpen ? <Loader /> : null\n\n // Mirrors BaseLayout's guard — the layer is exported, so callers are not\n // guaranteed to have narrowed this already.\n if (!beat.insights_payload) return null\n\n const { primary_cta, secondary_cta } = beat.insights_payload\n\n const currentCta = actionDrawer.trigger === 'secondaryCta' ? secondary_cta : primary_cta\n\n // A CTA without a real block never opens a drawer (BaseLayout won't trigger it);\n // a real-but-unknown block shows the error (\"oops\") content.\n const blockValid = hasDrawerBlock(currentCta?.block)\n const actionBlock = blockValid\n ? actionBlocks[currentCta?.block as keyof typeof actionBlocks]\n : undefined\n\n const drawerTitle = actionBlock\n ? (actionBlock.title?.(currentCta?.variant, copy) ?? currentCta?.label ?? '')\n : blockValid\n ? commonCopy.error_heading\n : (currentCta?.label ?? '')\n\n return (\n <Drawer\n ariaLabelClose={commonCopy.close_aria}\n isOpen={isCurrentBeatOpen}\n onClose={closeActionDrawer}\n title={drawerTitle}\n >\n {actionBlock ? (\n <ActionBlockRunner actionBlock={actionBlock} beat={beat} key={currentCta?.block} />\n ) : blockValid ? (\n <Stack sx={{ p: 24 }}>\n <Text>{commonCopy.error_message}</Text>\n </Stack>\n ) : null}\n </Drawer>\n )\n})\n"],"mappings":";;;;;;;;AA6BA,IAAM,IAAA,CAAqB,EACzB,aAAA,GACA,GAAG,EAAA,MACuD;AAC1D,QAAM,EAAE,WAAA,GAAW,YAAA,EAAA,IAAe;AAElC,SAAA,EAAW,CAAU,GAEd,gBAAA,EAAC,GAAD,EAAW,GAAI,EAAa,CAAA;AACrC,GAKa,IAAmB,EAAS,SAA0B,EACjE,MAAA,EAAA,GACwB;AACxB,QAAM,IAAO,EAAmB,GAC1B,IAAa,EAAK,QAClB,EAAE,cAAA,EAAA,IAAiB,EAAiB,GACpC,EAAE,cAAA,GAAc,mBAAA,EAAA,IAAsB,EAAmB,GAIzD,IAAoB,EAAa,gBAAgB,EAAa,SAAS,EAAK;AAElF,MAAI,CAAC,EAAc,QAAO,IAAoB,gBAAA,EAAC,GAAD,CAAS,CAAA,IAAI;AAI3D,MAAI,CAAC,EAAK,iBAAkB,QAAO;AAEnC,QAAM,EAAE,aAAA,GAAa,eAAA,EAAA,IAAkB,EAAK,kBAEtC,IAAa,EAAa,YAAY,iBAAiB,IAAgB,GAIvE,IAAa,EAAe,GAAY,KAAK,GAC7C,IAAc,IAChB,EAAa,GAAY,KAAA,IACzB,QAEE,IAAc,IACf,EAAY,QAAQ,GAAY,SAAS,CAAI,KAAK,GAAY,SAAS,KACxE,IACE,EAAW,gBACV,GAAY,SAAS;AAE5B,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,gBAAgB,EAAW;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IAEN,UAAA,IACC,gBAAA,EAAC,GAAD;AAAA,MAAgC,aAAA;AAAA,MAAmB,MAAA;AAAA,IAA+B,GAApB,GAAY,KAAQ,IAChF,IACF,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,GAAG,GAAG;AAAA,MACjB,UAAA,gBAAA,EAAC,GAAD,EAAA,UAAO,EAAW,cAAoB,CAAA;AAAA,IACjC,CAAA,IACL;AAAA,EACE,CAAA;AAEZ,CAAC"}
1
+ {"version":3,"file":"ActionBlockLayer.es.js","names":[],"sources":["../../../src/insights-v2/actionBlocks/ActionBlockLayer.tsx"],"sourcesContent":["import Stack from '@mui/material/Stack'\n\nimport { Text } from '@mxenabled/mxui'\nimport { observer } from 'mobx-react-lite'\n\nimport {\n Drawer,\n Loader,\n useGlobalCopyStore,\n useGlobalUiStore,\n useInsightsV2Store,\n} from '../../common'\nimport { type Beat } from '../../core'\nimport {\n actionBlocks,\n hasDrawerBlock,\n type ActionBlockEntry,\n type ActionBlockProps,\n} from '../mappings/blocks'\nimport { getDynamicCtaBasedOnTriggers } from './util'\n\ninterface ActionBlockLayerProps {\n beat: Beat\n}\n\n/**\n * Renders a registered action block. Callers MUST key this per block name — a\n * block with `usePrepare` and one without run a different number of hooks, so\n * reusing the same fiber across a block switch violates the rules of hooks.\n */\nconst ActionBlockRunner = ({\n actionBlock,\n ...blockProps\n}: ActionBlockProps & { actionBlock: ActionBlockEntry }) => {\n const { Component, usePrepare } = actionBlock\n\n usePrepare(blockProps)\n\n return <Component {...blockProps} />\n}\n\n// `observer` is required: this reads `isCopyLoaded` off GlobalUiStore and the\n// action drawer off InsightsV2Store. Without it the component never re-renders\n// and stays stuck on <Loader /> forever.\nexport const ActionBlockLayer = observer(function ActionBlockLayer({\n beat,\n}: ActionBlockLayerProps) {\n const copy = useGlobalCopyStore()\n const commonCopy = copy.common\n const { isCopyLoaded } = useGlobalUiStore()\n const { actionDrawer, closeActionDrawer } = useInsightsV2Store()\n\n // Every card in the feed renders its own layer against the shared store, so\n // this card's drawer only opens when its beat is the one that triggered it.\n const isCurrentBeatOpen = actionDrawer.isDrawerOpen && actionDrawer.guid === beat.guid\n\n if (!isCopyLoaded) return isCurrentBeatOpen ? <Loader /> : null\n\n // Mirrors BaseLayout's guard — the layer is exported, so callers are not\n // guaranteed to have narrowed this already.\n if (!beat.insights_payload) return null\n\n const { primary_cta, secondary_cta } = beat.insights_payload\n\n const currentCta = getDynamicCtaBasedOnTriggers(actionDrawer, primary_cta, secondary_cta)\n\n // A CTA without a real block never opens a drawer (BaseLayout won't trigger it);\n // a real-but-unknown block shows the error (\"oops\") content.\n const blockValid = hasDrawerBlock(currentCta?.block)\n const actionBlock = blockValid\n ? actionBlocks[currentCta?.block as keyof typeof actionBlocks]\n : undefined\n\n const drawerTitle = actionBlock\n ? (actionBlock.title?.(currentCta?.variant, copy) ?? currentCta?.label ?? '')\n : blockValid\n ? commonCopy.error_heading\n : (currentCta?.label ?? '')\n\n return (\n <Drawer\n ariaLabelClose={commonCopy.close_aria}\n isOpen={isCurrentBeatOpen}\n onClose={closeActionDrawer}\n title={drawerTitle}\n >\n {actionBlock ? (\n <ActionBlockRunner actionBlock={actionBlock} beat={beat} key={currentCta?.block}/>\n ) : blockValid ? (\n <Stack sx={{ p: 24 }}>\n <Text>{commonCopy.error_message}</Text>\n </Stack>\n ) : null}\n </Drawer>\n )\n})\n"],"mappings":";;;;;;;;;AA8BA,IAAM,IAAA,CAAqB,EACzB,aAAA,GACA,GAAG,EAAA,MACuD;AAC1D,QAAM,EAAE,WAAA,GAAW,YAAA,EAAA,IAAe;AAElC,SAAA,EAAW,CAAU,GAEd,gBAAA,EAAC,GAAD,EAAW,GAAI,EAAa,CAAA;AACrC,GAKa,IAAmB,EAAS,SAA0B,EACjE,MAAA,EAAA,GACwB;AACxB,QAAM,IAAO,EAAmB,GAC1B,IAAa,EAAK,QAClB,EAAE,cAAA,EAAA,IAAiB,EAAiB,GACpC,EAAE,cAAA,GAAc,mBAAA,EAAA,IAAsB,EAAmB,GAIzD,IAAoB,EAAa,gBAAgB,EAAa,SAAS,EAAK;AAElF,MAAI,CAAC,EAAc,QAAO,IAAoB,gBAAA,EAAC,GAAD,CAAS,CAAA,IAAI;AAI3D,MAAI,CAAC,EAAK,iBAAkB,QAAO;AAEnC,QAAM,EAAE,aAAA,GAAa,eAAA,EAAA,IAAkB,EAAK,kBAEtC,IAAa,EAA6B,GAAc,GAAa,CAAa,GAIlF,IAAa,EAAe,GAAY,KAAK,GAC7C,IAAc,IAChB,EAAa,GAAY,KAAA,IACzB,QAEE,IAAc,IACf,EAAY,QAAQ,GAAY,SAAS,CAAI,KAAK,GAAY,SAAS,KACxE,IACE,EAAW,gBACV,GAAY,SAAS;AAE5B,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,gBAAgB,EAAW;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IAEN,UAAA,IACC,gBAAA,EAAC,GAAD;AAAA,MAAgC,aAAA;AAAA,MAAmB,MAAA;AAAA,IAA8B,GAAnB,GAAY,KAAO,IAC/E,IACF,gBAAA,EAAC,GAAD;AAAA,MAAO,IAAI,EAAE,GAAG,GAAG;AAAA,MACjB,UAAA,gBAAA,EAAC,GAAD,EAAA,UAAO,EAAW,cAAoB,CAAA;AAAA,IACjC,CAAA,IACL;AAAA,EACE,CAAA;AAEZ,CAAC"}
@@ -1,3 +1,2 @@
1
- import { BottomActions, TopActions } from '../../../transactions/constants/Actions';
1
+ import { TopActions } from '../../../transactions/constants/Actions';
2
2
  export declare const resolveTopActions: (names?: string[]) => TopActions[];
3
- export declare const resolveBottomActions: (names?: string[]) => BottomActions[];
@@ -1,18 +1,12 @@
1
- import { BottomActions as t, DEFAULT_BOTTOM_ACTIONS as i, DEFAULT_TOP_ACTIONS as c, TopActions as r } from "../../../transactions/constants/Actions.es.js";
2
- var s = {
3
- Category: r.Category,
4
- Date: r.Date,
5
- Memo: r.Memo,
6
- Tags: r.Tags
7
- }, A = {
8
- MerchantBudget: t.MerchantBudget,
9
- SplitTransaction: t.SplitTransaction,
10
- HideTransaction: t.HideTransaction,
11
- MerchantLogo: t.MerchantLogo
12
- }, e = (o, T, n) => o ? o.map((a) => T[a]).filter((a) => a !== void 0) : n, O = (o) => e(o, s, c), _ = (o) => e(o, A, i);
1
+ import { DEFAULT_TOP_ACTIONS as T, TopActions as o } from "../../../transactions/constants/Actions.es.js";
2
+ var i = {
3
+ Category: o.Category,
4
+ Date: o.Date,
5
+ Memo: o.Memo,
6
+ Tags: o.Tags
7
+ }, v = (r, t, a) => r ? r.map((e) => t[e]).filter((e) => e !== void 0) : a, p = (r) => v(r, i, T);
13
8
  export {
14
- _ as resolveBottomActions,
15
- O as resolveTopActions
9
+ p as resolveTopActions
16
10
  };
17
11
 
18
12
  //# sourceMappingURL=transactionDetailsActions.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transactionDetailsActions.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionDetailsBlock/transactionDetailsActions.ts"],"sourcesContent":["import {\n BottomActions,\n DEFAULT_BOTTOM_ACTIONS,\n DEFAULT_TOP_ACTIONS,\n TopActions,\n} from '../../../transactions/constants/Actions'\n\n/**\n * The backend sends action names as strings on `instance_slot_data`; `TransactionDetails` takes the\n * numeric enums. Keep the lookup keyed by the enum's own member names so adding a member to\n * `Actions.ts` is picked up here without a second edit.\n *\n * Unknown names are dropped rather than throwing: a beat configured against a newer ditto config\n * than the bundle should render with the actions it *does* understand, not blow up the drawer.\n */\nconst TOP_ACTION_BY_NAME: Record<string, TopActions> = {\n Category: TopActions.Category,\n Date: TopActions.Date,\n Memo: TopActions.Memo,\n Tags: TopActions.Tags,\n}\n\nconst BOTTOM_ACTION_BY_NAME: Record<string, BottomActions> = {\n MerchantBudget: BottomActions.MerchantBudget,\n SplitTransaction: BottomActions.SplitTransaction,\n HideTransaction: BottomActions.HideTransaction,\n MerchantLogo: BottomActions.MerchantLogo,\n}\n\nconst resolve = <T>(names: string[] | undefined, lookup: Record<string, T>, fallback: T[]): T[] => {\n // `undefined` means \"not configured\" -> defaults. An explicit empty array means \"no actions\",\n // which is a legitimate per-beat choice (a read-only details view) and must not fall back.\n if (!names) return fallback\n\n return names.map((name) => lookup[name]).filter((action): action is T => action !== undefined)\n}\n\nexport const resolveTopActions = (names?: string[]): TopActions[] =>\n resolve(names, TOP_ACTION_BY_NAME, DEFAULT_TOP_ACTIONS)\n\nexport const resolveBottomActions = (names?: string[]): BottomActions[] =>\n resolve(names, BOTTOM_ACTION_BY_NAME, DEFAULT_BOTTOM_ACTIONS)\n"],"mappings":";AAeA,IAAM,IAAiD;AAAA,EACrD,UAAU,EAAW;AAAA,EACrB,MAAM,EAAW;AAAA,EACjB,MAAM,EAAW;AAAA,EACjB,MAAM,EAAW;AACnB,GAEM,IAAuD;AAAA,EAC3D,gBAAgB,EAAc;AAAA,EAC9B,kBAAkB,EAAc;AAAA,EAChC,iBAAiB,EAAc;AAAA,EAC/B,cAAc,EAAc;AAC9B,GAEM,IAAA,CAAc,GAA6B,GAA2B,MAGrE,IAEE,EAAM,IAAA,CAAK,MAAS,EAAO,CAAA,CAAK,EAAE,OAAA,CAAQ,MAAwB,MAAW,MAAS,IAF1E,GAKR,IAAA,CAAqB,MAChC,EAAQ,GAAO,GAAoB,CAAmB,GAE3C,IAAA,CAAwB,MACnC,EAAQ,GAAO,GAAuB,CAAsB"}
1
+ {"version":3,"file":"transactionDetailsActions.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionDetailsBlock/transactionDetailsActions.ts"],"sourcesContent":["import { DEFAULT_TOP_ACTIONS, TopActions } from '../../../transactions/constants/Actions'\n\n/**\n * The backend sends action names as strings on `instance_slot_data`; `TransactionDetails` takes the\n * numeric enums. Keep the lookup keyed by the enum's own member names so adding a member to\n * `Actions.ts` is picked up here without a second edit.\n *\n * Unknown names are dropped rather than throwing: a beat configured against a newer ditto config\n * than the bundle should render with the actions it *does* understand, not blow up the drawer.\n */\nconst TOP_ACTION_BY_NAME: Record<string, TopActions> = {\n Category: TopActions.Category,\n Date: TopActions.Date,\n Memo: TopActions.Memo,\n Tags: TopActions.Tags,\n}\n\nconst resolve = <T>(names: string[] | undefined, lookup: Record<string, T>, fallback: T[]): T[] => {\n // `undefined` means \"not configured\" -> defaults. An explicit empty array means \"no actions\",\n // which is a legitimate per-beat choice (a read-only details view) and must not fall back.\n if (!names) return fallback\n\n return names.map((name) => lookup[name]).filter((action): action is T => action !== undefined)\n}\n\nexport const resolveTopActions = (names?: string[]): TopActions[] =>\n resolve(names, TOP_ACTION_BY_NAME, DEFAULT_TOP_ACTIONS)\n"],"mappings":";AAUA,IAAM,IAAiD;AAAA,EACrD,UAAU,EAAW;AAAA,EACrB,MAAM,EAAW;AAAA,EACjB,MAAM,EAAW;AAAA,EACjB,MAAM,EAAW;AACnB,GAEM,IAAA,CAAc,GAA6B,GAA2B,MAGrE,IAEE,EAAM,IAAA,CAAK,MAAS,EAAO,CAAA,CAAK,EAAE,OAAA,CAAQ,MAAwB,MAAW,MAAS,IAF1E,GAKR,IAAA,CAAqB,MAChC,EAAQ,GAAO,GAAoB,CAAmB"}
@@ -1,16 +1,17 @@
1
- import { useTransactionStore as e } from "../../../common/context/hooks.es.js";
2
- import { resolveBottomActions as p, resolveTopActions as m } from "./transactionDetailsActions.es.js";
3
- var g = (o) => {
4
- const { detailedTransactions: a, isTransactionDataLoaded: i } = e(), s = o.insights_payload?.instance_slot_data ?? {}, t = s.transaction_guid ?? o.primary_transaction_guid ?? o.transaction_guids?.[0], r = t ? a.find((d) => d.guid === t) : void 0, n = o.primary_transaction, c = !t || n?.guid === t;
1
+ import { useActionContext as _, useInsightsV2Store as g, useTransactionStore as m } from "../../../common/context/hooks.es.js";
2
+ import { getBottomActionsByVariant as u } from "./util.es.js";
3
+ import { resolveTopActions as l } from "./transactionDetailsActions.es.js";
4
+ var A = (t) => {
5
+ const { detailedTransactions: a, isTransactionDataLoaded: i } = m(), { actionDrawer: r } = g(), { transaction_guid: c } = _() ?? {}, s = t.insights_payload?.instance_slot_data ?? {}, o = c ?? s.transaction_guid ?? t.primary_transaction_guid ?? t.transaction_guids?.[0], d = o ? a.find((p) => p.guid === o) : void 0, n = t.primary_transaction, e = !o || n?.guid === o;
5
6
  return {
6
- bottomActions: p(s.bottom_actions),
7
+ bottomActions: u(r, t.insights_payload?.primary_cta, t.insights_payload?.secondary_cta),
7
8
  isLoading: !i,
8
- topActions: m(s.top_actions),
9
- transaction: r ?? (c ? n : void 0)
9
+ topActions: l(s.top_actions),
10
+ transaction: d ?? (e ? n : void 0)
10
11
  };
11
12
  };
12
13
  export {
13
- g as useTransactionDetailsBlock
14
+ A as useTransactionDetailsBlock
14
15
  };
15
16
 
16
17
  //# sourceMappingURL=useTransactionDetailsBlock.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useTransactionDetailsBlock.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.ts"],"sourcesContent":["import { useTransactionStore } from '../../../common'\nimport type { Beat, Transaction } from '../../../core'\nimport type { TransactionDetailsBlockData } from '../../../core/types/InsightsInstanceSlotData'\nimport type { BottomActions, TopActions } from '../../../transactions/constants/Actions'\n\nimport { resolveBottomActions, resolveTopActions } from './transactionDetailsActions'\n\ninterface TransactionDetailsBlockState {\n bottomActions: BottomActions[]\n /** True while the store is still loading; the block shows a loader instead of an empty state. */\n isLoading: boolean\n topActions: TopActions[]\n /** `undefined` once loading finishes means the transaction could not be resolved. */\n transaction?: Transaction\n}\n\n/**\n * Resolves which transaction this drawer is about, and which inline actions it offers.\n *\n * Resolution order is deliberate:\n * 1. `instance_slot_data.transaction_guid` — the beat explicitly naming its subject.\n * 2. `beat.primary_transaction_guid` — the standard beat-level pointer.\n * 3. `beat.transaction_guids[0]` — last resort for beats that only carry the list.\n *\n * The guid is then looked up in `transactionStore.detailedTransactions` rather than used directly,\n * because `TransactionDetails` needs the *detailed* shape (account + category + taggings joined in)\n * and edits must write through to the same store object the rest of the app renders. `buildDetailed\n * Transactions` inside the store is this repo's equivalent of pulse's `buildTransactionDetails`.\n *\n * `beat.primary_transaction` is the fallback of last resort: it is a payload snapshot, not a store\n * object, so inline edits against it would not propagate. Preferring it over a store hit would make\n * editing silently no-op, which is why it is only used when the store genuinely has nothing — and\n * only when it is a snapshot of the *same* transaction the guid resolved to (or when no guid\n * resolved at all). A snapshot of some other transaction is not an answer to this question.\n */\nexport const useTransactionDetailsBlock = (beat: Beat): TransactionDetailsBlockState => {\n const { detailedTransactions, isTransactionDataLoaded } = useTransactionStore()\n\n const slotData = (beat.insights_payload?.instance_slot_data ?? {}) as TransactionDetailsBlockData\n\n const guid =\n slotData.transaction_guid ?? beat.primary_transaction_guid ?? beat.transaction_guids?.[0]\n\n const fromStore = guid\n ? detailedTransactions.find((transaction) => transaction.guid === guid)\n : undefined\n\n // The snapshot is only a valid answer for the guid we actually resolved. When a beat names its\n // subject via instance_slot_data (or transaction_guids[0]) and that guid misses in the store,\n // falling back unconditionally would render a *different* transaction's details — and inline\n // edits would then be made against the wrong subject. Match on guid, or accept the snapshot only\n // when no guid resolved at all.\n const snapshot = beat.primary_transaction\n const snapshotMatches = !guid || snapshot?.guid === guid\n\n return {\n bottomActions: resolveBottomActions(slotData.bottom_actions),\n isLoading: !isTransactionDataLoaded,\n topActions: resolveTopActions(slotData.top_actions),\n transaction: fromStore ?? (snapshotMatches ? snapshot : undefined),\n }\n}\n"],"mappings":";;AAmCA,IAAa,IAAA,CAA8B,MAA6C;AACtF,QAAM,EAAE,sBAAA,GAAsB,yBAAA,EAAA,IAA4B,EAAoB,GAExE,IAAY,EAAK,kBAAkB,sBAAsB,CAAC,GAE1D,IACJ,EAAS,oBAAoB,EAAK,4BAA4B,EAAK,oBAAoB,CAAA,GAEnF,IAAY,IACd,EAAqB,KAAA,CAAM,MAAgB,EAAY,SAAS,CAAI,IACpE,QAOE,IAAW,EAAK,qBAChB,IAAkB,CAAC,KAAQ,GAAU,SAAS;AAEpD,SAAO;AAAA,IACL,eAAe,EAAqB,EAAS,cAAc;AAAA,IAC3D,WAAW,CAAC;AAAA,IACZ,YAAY,EAAkB,EAAS,WAAW;AAAA,IAClD,aAAa,MAAc,IAAkB,IAAW;AAAA,EAC1D;AACF"}
1
+ {"version":3,"file":"useTransactionDetailsBlock.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionDetailsBlock/useTransactionDetailsBlock.ts"],"sourcesContent":["import { useActionContext, useInsightsV2Store, useTransactionStore } from '../../../common'\nimport type { Beat, Transaction, DrilldownPayload } from '../../../core'\nimport type { TransactionDetailsBlockData } from '../../../core/types/InsightsInstanceSlotData'\nimport type { BottomActions, TopActions } from '../../../transactions/constants/Actions'\nimport { getBottomActionsByVariant } from './util'\nimport { resolveTopActions } from './transactionDetailsActions'\n\ninterface TransactionDetailsBlockState {\n bottomActions: BottomActions[]\n /** True while the store is still loading; the block shows a loader instead of an empty state. */\n isLoading: boolean\n topActions: TopActions[]\n /** `undefined` once loading finishes means the transaction could not be resolved. */\n transaction?: Transaction\n}\n\n/**\n * Resolves which transaction this drawer is about, and which inline actions it offers.\n *\n * Resolution order is deliberate:\n * 1. `instance_slot_data.transaction_guid` — the beat explicitly naming its subject.\n * 2. `beat.primary_transaction_guid` — the standard beat-level pointer.\n * 3. `beat.transaction_guids[0]` — last resort for beats that only carry the list.\n *\n * The guid is then looked up in `transactionStore.detailedTransactions` rather than used directly,\n * because `TransactionDetails` needs the *detailed* shape (account + category + taggings joined in)\n * and edits must write through to the same store object the rest of the app renders. `buildDetailed\n * Transactions` inside the store is this repo's equivalent of pulse's `buildTransactionDetails`.\n *\n * `beat.primary_transaction` is the fallback of last resort: it is a payload snapshot, not a store\n * object, so inline edits against it would not propagate. Preferring it over a store hit would make\n * editing silently no-op, which is why it is only used when the store genuinely has nothing — and\n * only when it is a snapshot of the *same* transaction the guid resolved to (or when no guid\n * resolved at all). A snapshot of some other transaction is not an answer to this question.\n */\nexport const useTransactionDetailsBlock = (beat: Beat): TransactionDetailsBlockState => {\n const { detailedTransactions, isTransactionDataLoaded } = useTransactionStore()\n\n const {actionDrawer} = useInsightsV2Store()\n\n const { transaction_guid } = useActionContext<DrilldownPayload>() ?? {}\n const slotData = (beat.insights_payload?.instance_slot_data ?? {}) as TransactionDetailsBlockData\n\n const guid = transaction_guid ??\n slotData.transaction_guid ?? beat.primary_transaction_guid ?? beat.transaction_guids?.[0]\n\n const fromStore = guid\n ? detailedTransactions.find((transaction) => transaction.guid === guid)\n : undefined\n\n // The snapshot is only a valid answer for the guid we actually resolved. When a beat names its\n // subject via instance_slot_data (or transaction_guids[0]) and that guid misses in the store,\n // falling back unconditionally would render a *different* transaction's details — and inline\n // edits would then be made against the wrong subject. Match on guid, or accept the snapshot only\n // when no guid resolved at all.\n const snapshot = beat.primary_transaction\n const snapshotMatches = !guid || snapshot?.guid === guid\n\n const bottomActions = getBottomActionsByVariant(actionDrawer, beat.insights_payload?.primary_cta, beat.insights_payload?.secondary_cta)\n return {\n bottomActions,\n isLoading: !isTransactionDataLoaded,\n topActions: resolveTopActions(slotData.top_actions),\n transaction: fromStore ?? (snapshotMatches ? snapshot : undefined),\n }\n}\n"],"mappings":";;;AAmCA,IAAa,IAAA,CAA8B,MAA6C;AACtF,QAAM,EAAE,sBAAA,GAAsB,yBAAA,EAAA,IAA4B,EAAoB,GAExE,EAAC,cAAA,EAAA,IAAgB,EAAmB,GAEpC,EAAE,kBAAA,EAAA,IAAqB,EAAmC,KAAK,CAAC,GAChE,IAAY,EAAK,kBAAkB,sBAAsB,CAAC,GAE1D,IAAO,KACX,EAAS,oBAAoB,EAAK,4BAA4B,EAAK,oBAAoB,CAAA,GAEnF,IAAY,IACd,EAAqB,KAAA,CAAM,MAAgB,EAAY,SAAS,CAAI,IACpE,QAOE,IAAW,EAAK,qBAChB,IAAkB,CAAC,KAAQ,GAAU,SAAS;AAGpD,SAAO;AAAA,IACL,eAFoB,EAA0B,GAAc,EAAK,kBAAkB,aAAa,EAAK,kBAAkB,aAEvH;AAAA,IACA,WAAW,CAAC;AAAA,IACZ,YAAY,EAAkB,EAAS,WAAW;AAAA,IAClD,aAAa,MAAc,IAAkB,IAAW;AAAA,EAC1D;AACF"}
@@ -0,0 +1,3 @@
1
+ import { ActionDrawerState, PrimaryCTA, SecondaryCTA } from '../../../core';
2
+ import { BottomActions } from '../../../transactions/constants/Actions';
3
+ export declare const getBottomActionsByVariant: (actionDrawer: ActionDrawerState, primary_cta: PrimaryCTA | undefined, secondary_cta: SecondaryCTA | undefined) => BottomActions[];
@@ -0,0 +1,8 @@
1
+ import { BottomActions as o, DEFAULT_BOTTOM_ACTIONS as t } from "../../../transactions/constants/Actions.es.js";
2
+ import { getDynamicCtaBasedOnTriggers as i } from "../util.es.js";
3
+ var m = (e, r, a) => i(e, r, a)?.variant === "fee_detected" ? t : [o.MerchantBudget, ...t];
4
+ export {
5
+ m as getBottomActionsByVariant
6
+ };
7
+
8
+ //# sourceMappingURL=util.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionDetailsBlock/util.ts"],"sourcesContent":["import type { ActionDrawerState, PrimaryCTA, SecondaryCTA } from '../../../core'\nimport { BottomActions, DEFAULT_BOTTOM_ACTIONS } from '../../../transactions/constants/Actions'\nimport { getDynamicCtaBasedOnTriggers } from '../util'\n\nexport const getBottomActionsByVariant = (\n actionDrawer: ActionDrawerState,\n primary_cta: PrimaryCTA | undefined,\n secondary_cta: SecondaryCTA | undefined,\n): BottomActions[] => {\n const cta = getDynamicCtaBasedOnTriggers(actionDrawer, primary_cta, secondary_cta)\n\n switch (cta?.variant) {\n case 'fee_detected':\n return DEFAULT_BOTTOM_ACTIONS\n default:\n return [BottomActions.MerchantBudget, ...DEFAULT_BOTTOM_ACTIONS]\n }\n}\n"],"mappings":";;AAIA,IAAa,IAAA,CACX,GACA,GACA,MAEY,EAA6B,GAAc,GAAa,CAE5D,GAAK,YACN,iBACI,IAEA,CAAC,EAAc,gBAAgB,GAAG,CAAsB"}
@@ -13,10 +13,11 @@ interface TransactionDrillDownProps {
13
13
  selectedIndex: number;
14
14
  top: React.ReactNode;
15
15
  onSelectionChange?: (selectedIndex: number) => void;
16
+ onEachRowClick?: (guid: string) => void;
16
17
  transactionFilter?: (selectedIndex: number) => (transaction: Transaction) => boolean;
17
18
  baseTransactions?: Transaction[];
18
19
  }
19
- export declare const TransactionDrillDown: (({ ariaLabel, heading, subHeadingText, icon, tabs, selectedIndex, top, onSelectionChange, transactionFilter, baseTransactions, }: TransactionDrillDownProps) => import("react/jsx-runtime").JSX.Element) & {
20
+ export declare const TransactionDrillDown: (({ ariaLabel, heading, subHeadingText, icon, tabs, selectedIndex, top, onSelectionChange, transactionFilter, onEachRowClick, baseTransactions, }: TransactionDrillDownProps) => import("react/jsx-runtime").JSX.Element) & {
20
21
  displayName: string;
21
22
  };
22
23
  export default TransactionDrillDown;
@@ -1,34 +1,34 @@
1
1
  import { useGlobalCopyStore as W, useGlobalUiStore as $, useTransactionStore as j } from "../../../common/context/hooks.es.js";
2
- import { exportTransactionsToCSV as k } from "../../../core/utils/TransactionUtils.es.js";
3
- import G from "../../../common/components/Loader.es.js";
4
- import P from "../../../transactions/components/shared/TransactionList.es.js";
2
+ import { exportTransactionsToCSV as G } from "../../../core/utils/TransactionUtils.es.js";
3
+ import P from "../../../common/components/Loader.es.js";
4
+ import A from "../../../transactions/components/shared/TransactionList.es.js";
5
5
  import "react";
6
- import { observer as A } from "mobx-react-lite";
6
+ import { observer as E } from "mobx-react-lite";
7
7
  import c from "@mui/material/Stack";
8
- import { H3 as E, Text as d } from "@mxenabled/mxui";
9
- import N from "@mui/material/Button";
10
- import { Icon as R } from "@mxenabled/mx-icons";
11
- import { jsx as r, jsxs as o } from "react/jsx-runtime";
8
+ import { H3 as N, Text as d } from "@mxenabled/mxui";
9
+ import R from "@mui/material/Button";
10
+ import { Icon as U } from "@mxenabled/mx-icons";
11
+ import { jsx as o, jsxs as r } from "react/jsx-runtime";
12
12
  import p from "@mui/material/Box";
13
- import U from "@mui/material/Tab";
14
- import V from "@mui/material/Tabs";
15
- var u = "transaction-drill-down-panel", v = (m) => `transaction-details-tab-${m}`, ar = A(function({ ariaLabel: T, heading: i, subHeadingText: n, icon: y, tabs: b, selectedIndex: e, top: C, onSelectionChange: g, transactionFilter: f, baseTransactions: _ }) {
16
- const { transactions: l } = W(), { isCopyLoaded: w } = $(), { sortedTransactionsWithSplits: D, tags: S, detailedTransactions: L } = j();
17
- if (!w) return /* @__PURE__ */ r(G, {});
18
- const s = !!b?.length, B = T ?? l.transactions_title, I = (t, a) => {
13
+ import V from "@mui/material/Tab";
14
+ import q from "@mui/material/Tabs";
15
+ var u = "transaction-drill-down-panel", v = (m) => `transaction-details-tab-${m}`, io = E(function({ ariaLabel: T, heading: i, subHeadingText: n, icon: y, tabs: b, selectedIndex: e, top: C, onSelectionChange: g, transactionFilter: f, onEachRowClick: _, baseTransactions: w }) {
16
+ const { transactions: l } = W(), { isCopyLoaded: D } = $(), { sortedTransactionsWithSplits: S, tags: L, detailedTransactions: B } = j();
17
+ if (!D) return /* @__PURE__ */ o(P, {});
18
+ const s = !!b?.length, I = T ?? l.transactions_title, k = (t, a) => {
19
19
  g?.(a);
20
- }, h = f ? (_ ?? L).filter(f(e)) : void 0, x = h ?? D;
21
- return /* @__PURE__ */ o(p, {
20
+ }, h = f ? (w ?? B).filter(f(e)) : void 0, x = h ?? S;
21
+ return /* @__PURE__ */ r(p, {
22
22
  sx: {
23
23
  bgcolor: "background.paper",
24
24
  width: "100%"
25
25
  },
26
- children: [s && /* @__PURE__ */ r(V, {
27
- "aria-label": B,
28
- onChange: I,
26
+ children: [s && /* @__PURE__ */ o(q, {
27
+ "aria-label": I,
28
+ onChange: k,
29
29
  value: e,
30
30
  variant: "fullWidth",
31
- children: b.map((t, a) => /* @__PURE__ */ r(U, {
31
+ children: b.map((t, a) => /* @__PURE__ */ o(V, {
32
32
  "aria-controls": u,
33
33
  "aria-label": t.ariaLabel,
34
34
  id: v(a),
@@ -38,35 +38,35 @@ var u = "transaction-drill-down-panel", v = (m) => `transaction-details-tab-${m}
38
38
  px: 0
39
39
  }
40
40
  }, `${t.label}-${a}`))
41
- }), /* @__PURE__ */ o(p, {
41
+ }), /* @__PURE__ */ r(p, {
42
42
  "aria-labelledby": s ? v(e) : void 0,
43
43
  id: u,
44
44
  role: s ? "tabpanel" : void 0,
45
45
  children: [
46
- (i || n) && /* @__PURE__ */ o(c, {
46
+ (i || n) && /* @__PURE__ */ r(c, {
47
47
  sx: {
48
48
  gap: 4,
49
49
  pt: 16,
50
50
  px: 24
51
51
  },
52
- children: [i && /* @__PURE__ */ r(E, { children: i }), n && /* @__PURE__ */ o(c, {
52
+ children: [i && /* @__PURE__ */ o(N, { children: i }), n && /* @__PURE__ */ r(c, {
53
53
  sx: {
54
54
  alignItems: "center",
55
55
  flexDirection: "row",
56
56
  gap: 8
57
57
  },
58
- children: [y, /* @__PURE__ */ r(d, {
58
+ children: [y, /* @__PURE__ */ o(d, {
59
59
  textTransform: "uppercase",
60
60
  variant: "body2",
61
61
  children: n
62
62
  })]
63
63
  })]
64
64
  }),
65
- /* @__PURE__ */ r(p, {
65
+ /* @__PURE__ */ o(p, {
66
66
  sx: { pt: 16 },
67
67
  children: C
68
68
  }),
69
- /* @__PURE__ */ o(c, {
69
+ /* @__PURE__ */ r(c, {
70
70
  sx: {
71
71
  alignItems: "center",
72
72
  borderBottomColor: "divider",
@@ -78,31 +78,34 @@ var u = "transaction-drill-down-panel", v = (m) => `transaction-details-tab-${m}
78
78
  pt: 16,
79
79
  px: 24
80
80
  },
81
- children: [/* @__PURE__ */ r(d, {
81
+ children: [/* @__PURE__ */ o(d, {
82
82
  bold: !0,
83
83
  variant: "body1",
84
84
  children: l.transactions_title
85
- }), x.length > 0 && /* @__PURE__ */ r(N, {
85
+ }), x.length > 0 && /* @__PURE__ */ o(R, {
86
86
  onClick: () => {
87
- k(x, S);
87
+ G(x, L);
88
88
  },
89
- startIcon: /* @__PURE__ */ r(R, { name: "ios_share" }),
89
+ startIcon: /* @__PURE__ */ o(U, { name: "ios_share" }),
90
90
  sx: { height: 28 },
91
- children: /* @__PURE__ */ r(d, {
91
+ children: /* @__PURE__ */ o(d, {
92
92
  bold: !0,
93
93
  variant: "body2",
94
94
  children: l.export_csv_btn
95
95
  })
96
96
  })]
97
97
  }),
98
- /* @__PURE__ */ r(P, { transaction: h })
98
+ /* @__PURE__ */ o(A, {
99
+ transaction: h,
100
+ onClick: _
101
+ })
99
102
  ]
100
103
  })]
101
104
  });
102
105
  });
103
106
  export {
104
- ar as TransactionDrillDown,
105
- ar as default
107
+ io as TransactionDrillDown,
108
+ io as default
106
109
  };
107
110
 
108
111
  //# sourceMappingURL=TransactionDrillDown.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionDrillDown.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.tsx"],"sourcesContent":["import React from 'react'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Stack from '@mui/material/Stack'\nimport Tab from '@mui/material/Tab'\nimport Tabs from '@mui/material/Tabs'\nimport { observer } from 'mobx-react-lite'\n\nimport { Icon } from '@mxenabled/mx-icons'\nimport { H3, Text } from '@mxenabled/mxui'\n\nimport { Loader, useGlobalCopyStore, useGlobalUiStore, useTransactionStore } from '../../../common'\nimport type { Transaction } from '../../../core'\nimport { exportTransactionsToCSV } from '../../../core/utils/TransactionUtils'\nimport { TransactionList } from '../../../transactions'\n\ninterface TabItem {\n label: string\n ariaLabel?: string\n}\n\nconst PANEL_ID = 'transaction-drill-down-panel'\nconst tabId = (index: number) => `transaction-details-tab-${index}`\n\ninterface TransactionDrillDownProps {\n ariaLabel?: string\n heading?: string\n subHeadingText?: string\n icon?: React.ReactNode\n tabs?: TabItem[]\n selectedIndex: number\n top: React.ReactNode\n onSelectionChange?: (selectedIndex: number) => void\n transactionFilter?: (selectedIndex: number) => (transaction: Transaction) => boolean\n baseTransactions?: Transaction[]\n}\n\nexport const TransactionDrillDown = observer(function TransactionDrillDown({\n ariaLabel,\n heading,\n subHeadingText,\n icon,\n tabs,\n selectedIndex,\n top,\n onSelectionChange,\n transactionFilter,\n baseTransactions,\n}: TransactionDrillDownProps) {\n const { transactions: transactionsCopy } = useGlobalCopyStore()\n const { isCopyLoaded } = useGlobalUiStore()\n const { sortedTransactionsWithSplits, tags, detailedTransactions } = useTransactionStore()\n\n if (!isCopyLoaded) return <Loader />\n\n const hasTabs = !!tabs?.length\n const tablistLabel = ariaLabel ?? transactionsCopy.transactions_title\n\n const handlePrimaryChange = (_event: React.SyntheticEvent, newValue: number) => {\n onSelectionChange?.(newValue)\n }\n\n const filteredTransactions = transactionFilter\n ? (baseTransactions ?? detailedTransactions).filter(transactionFilter(selectedIndex))\n : undefined\n\n const exportTransactions = filteredTransactions ?? sortedTransactionsWithSplits\n\n return (\n <Box sx={{ bgcolor: 'background.paper', width: '100%' }}>\n {hasTabs && (\n <Tabs\n aria-label={tablistLabel}\n onChange={handlePrimaryChange}\n value={selectedIndex}\n variant=\"fullWidth\"\n >\n {tabs!.map((tab, index) => (\n <Tab\n aria-controls={PANEL_ID}\n aria-label={tab.ariaLabel}\n id={tabId(index)}\n key={`${tab.label}-${index}`}\n label={tab.label}\n sx={{ minWidth: 'auto', px: 0 }}\n />\n ))}\n </Tabs>\n )}\n\n <Box\n aria-labelledby={hasTabs ? tabId(selectedIndex) : undefined}\n id={PANEL_ID}\n role={hasTabs ? 'tabpanel' : undefined}\n >\n {(heading || subHeadingText) && (\n <Stack sx={{ gap: 4, pt: 16, px: 24 }}>\n {heading && <H3>{heading}</H3>}\n {subHeadingText && (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n {icon}\n <Text textTransform=\"uppercase\" variant=\"body2\">\n {subHeadingText}\n </Text>\n </Stack>\n )}\n </Stack>\n )}\n\n <Box sx={{ pt: 16 }}>{top}</Box>\n\n <Stack\n sx={{\n alignItems: 'center',\n borderBottomColor: 'divider',\n borderBottomStyle: 'solid',\n borderBottomWidth: 1,\n flexDirection: 'row',\n justifyContent: 'space-between',\n pb: 4,\n pt: 16,\n px: 24,\n }}\n >\n <Text bold={true} variant=\"body1\">\n {transactionsCopy.transactions_title}\n </Text>\n {exportTransactions.length > 0 && (\n <Button\n onClick={() => {\n exportTransactionsToCSV(exportTransactions, tags)\n }}\n startIcon={<Icon name=\"ios_share\" />}\n sx={{ height: 28 }}\n >\n <Text bold={true} variant=\"body2\">\n {transactionsCopy.export_csv_btn}\n </Text>\n </Button>\n )}\n </Stack>\n\n <TransactionList transaction={filteredTransactions} />\n </Box>\n </Box>\n )\n})\n\nexport default TransactionDrillDown\n"],"mappings":"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"}
1
+ {"version":3,"file":"TransactionDrillDown.es.js","names":[],"sources":["../../../../src/insights-v2/actionBlocks/TransactionHistoryBlock/TransactionDrillDown.tsx"],"sourcesContent":["import React from 'react'\n\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Stack from '@mui/material/Stack'\nimport Tab from '@mui/material/Tab'\nimport Tabs from '@mui/material/Tabs'\nimport { observer } from 'mobx-react-lite'\n\nimport { Icon } from '@mxenabled/mx-icons'\nimport { H3, Text } from '@mxenabled/mxui'\n\nimport { Loader, useGlobalCopyStore, useGlobalUiStore, useTransactionStore } from '../../../common'\nimport type { Transaction } from '../../../core'\nimport { exportTransactionsToCSV } from '../../../core/utils/TransactionUtils'\nimport { TransactionList } from '../../../transactions'\n\ninterface TabItem {\n label: string\n ariaLabel?: string\n}\n\nconst PANEL_ID = 'transaction-drill-down-panel'\nconst tabId = (index: number) => `transaction-details-tab-${index}`\n\ninterface TransactionDrillDownProps {\n ariaLabel?: string\n heading?: string\n subHeadingText?: string\n icon?: React.ReactNode\n tabs?: TabItem[]\n selectedIndex: number\n top: React.ReactNode\n onSelectionChange?: (selectedIndex: number) => void\n onEachRowClick?: (guid: string) => void\n transactionFilter?: (selectedIndex: number) => (transaction: Transaction) => boolean\n baseTransactions?: Transaction[]\n}\n\nexport const TransactionDrillDown = observer(function TransactionDrillDown({\n ariaLabel,\n heading,\n subHeadingText,\n icon,\n tabs,\n selectedIndex,\n top,\n onSelectionChange,\n transactionFilter,\n onEachRowClick,\n baseTransactions,\n}: TransactionDrillDownProps) {\n const { transactions: transactionsCopy } = useGlobalCopyStore()\n const { isCopyLoaded } = useGlobalUiStore()\n const { sortedTransactionsWithSplits, tags, detailedTransactions } = useTransactionStore()\n\n if (!isCopyLoaded) return <Loader />\n\n const hasTabs = !!tabs?.length\n const tablistLabel = ariaLabel ?? transactionsCopy.transactions_title\n\n const handlePrimaryChange = (_event: React.SyntheticEvent, newValue: number) => {\n onSelectionChange?.(newValue)\n }\n\n const filteredTransactions = transactionFilter\n ? (baseTransactions ?? detailedTransactions).filter(transactionFilter(selectedIndex))\n : undefined\n\n const exportTransactions = filteredTransactions ?? sortedTransactionsWithSplits\n\n return (\n <Box sx={{ bgcolor: 'background.paper', width: '100%' }}>\n {hasTabs && (\n <Tabs\n aria-label={tablistLabel}\n onChange={handlePrimaryChange}\n value={selectedIndex}\n variant=\"fullWidth\"\n >\n {tabs!.map((tab, index) => (\n <Tab\n aria-controls={PANEL_ID}\n aria-label={tab.ariaLabel}\n id={tabId(index)}\n key={`${tab.label}-${index}`}\n label={tab.label}\n sx={{ minWidth: 'auto', px: 0 }}\n />\n ))}\n </Tabs>\n )}\n\n <Box\n aria-labelledby={hasTabs ? tabId(selectedIndex) : undefined}\n id={PANEL_ID}\n role={hasTabs ? 'tabpanel' : undefined}\n >\n {(heading || subHeadingText) && (\n <Stack sx={{ gap: 4, pt: 16, px: 24 }}>\n {heading && <H3>{heading}</H3>}\n {subHeadingText && (\n <Stack sx={{ alignItems: 'center', flexDirection: 'row', gap: 8 }}>\n {icon}\n <Text textTransform=\"uppercase\" variant=\"body2\">\n {subHeadingText}\n </Text>\n </Stack>\n )}\n </Stack>\n )}\n\n <Box sx={{ pt: 16 }}>{top}</Box>\n\n <Stack\n sx={{\n alignItems: 'center',\n borderBottomColor: 'divider',\n borderBottomStyle: 'solid',\n borderBottomWidth: 1,\n flexDirection: 'row',\n justifyContent: 'space-between',\n pb: 4,\n pt: 16,\n px: 24,\n }}\n >\n <Text bold={true} variant=\"body1\">\n {transactionsCopy.transactions_title}\n </Text>\n {exportTransactions.length > 0 && (\n <Button\n onClick={() => {\n exportTransactionsToCSV(exportTransactions, tags)\n }}\n startIcon={<Icon name=\"ios_share\" />}\n sx={{ height: 28 }}\n >\n <Text bold={true} variant=\"body2\">\n {transactionsCopy.export_csv_btn}\n </Text>\n </Button>\n )}\n </Stack>\n\n <TransactionList transaction={filteredTransactions} onClick={onEachRowClick} />\n </Box>\n </Box>\n )\n})\n\nexport default TransactionDrillDown\n"],"mappings":"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"}