@mx-cartographer/experiences 9.7.93 → 9.7.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [9.7.95] - 11-03-2026
2
+
3
+ - **FIXED** - 20px Transaction Details category icon (MEW2-3427)
4
+
5
+ ## [9.7.94] - 11-03-2026
6
+
7
+ - **ADDED** - Weekend Spending Summary beat on Insights 2.0 (MEW2-3422): the `transaction_block` `spending_summary` variant (header, rows and footer with the header text in `primary.main`, via a `headerColor` on the layout config and `TransactionListCard`) whose "View Transactions" CTA opens the Transaction List drawer as a plain list. Fixture, story, contract test and block doc
8
+
1
9
  ## [9.7.93] - 11-03-2026
2
10
 
3
11
  - **ADDED** - Charge Dispute Refund beat on Insights 2.0 (MEW2-3423): the `with_header` transaction card whose "View Transaction" CTA opens the Transaction Details drawer for the refund. Fixture, story, contract test and the Transaction Details block doc
@@ -1,25 +1,25 @@
1
- import { useCategoryStore as j, useGlobalCopyStore as q, useGlobalStore as D } from "../../../../common/context/hooks.es.js";
1
+ import { useCategoryStore as q, useGlobalCopyStore as D, useGlobalStore as H } from "../../../../common/context/hooks.es.js";
2
2
  import { slot as s } from "../../../../core/types/Insights.es.js";
3
3
  import { formatCurrency as v } from "../../../../core/utils/NumberFormatting.es.js";
4
4
  import { getCategoryColor as C } from "../../../../core/utils/CategoryUtil.es.js";
5
- import { useBeatActions as H } from "../../../beatActions.es.js";
6
- import { USER_RESPONSE as P, repeatingTransactionOf as V } from "../../../ctaActions/subscriptionAnswer.es.js";
7
- import { logoFromRef as U } from "../../../components/shared/EntityLogo.es.js";
8
- import W from "../../../components/LogoFromGuid.es.js";
9
- import { statusIconName as Y, statusIconPalette as I } from "../../../components/statusIcon.es.js";
10
- import { resolveVariantConfig as J } from "../../resolveVariantConfig.es.js";
11
- import K from "../../../components/TransactionListCard.es.js";
12
- import Q from "../../../components/StatusMessageCard.es.js";
13
- import { subscriptionFrequency as X } from "../../../components/SubscriptionStatus/subscriptionFrequency.es.js";
14
- import { getLayoutConfig as oo, transactionBlockVariant as to } from "./layout.es.js";
15
- import { observer as ro } from "mobx-react-lite";
16
- import { CategoryIcon as eo, InstitutionLogo as io, MerchantLogo as no } from "@mxenabled/mxui";
5
+ import { useBeatActions as P } from "../../../beatActions.es.js";
6
+ import { USER_RESPONSE as V, repeatingTransactionOf as U } from "../../../ctaActions/subscriptionAnswer.es.js";
7
+ import { logoFromRef as W } from "../../../components/shared/EntityLogo.es.js";
8
+ import Y from "../../../components/LogoFromGuid.es.js";
9
+ import { statusIconName as J, statusIconPalette as I } from "../../../components/statusIcon.es.js";
10
+ import { resolveVariantConfig as K } from "../../resolveVariantConfig.es.js";
11
+ import Q from "../../../components/TransactionListCard.es.js";
12
+ import X from "../../../components/StatusMessageCard.es.js";
13
+ import { subscriptionFrequency as oo } from "../../../components/SubscriptionStatus/subscriptionFrequency.es.js";
14
+ import { getLayoutConfig as to, transactionBlockVariant as ro } from "./layout.es.js";
15
+ import { observer as eo } from "mobx-react-lite";
16
+ import { CategoryIcon as io, InstitutionLogo as no, MerchantLogo as ao } from "@mxenabled/mxui";
17
17
  import { Icon as T } from "@mxenabled/mx-icons";
18
18
  import { jsx as t } from "react/jsx-runtime";
19
- import { alpha as S, useTheme as ao } from "@mui/material/styles";
19
+ import { alpha as S, useTheme as so } from "@mui/material/styles";
20
20
  import d from "@mui/material/Box";
21
- var u = 32, so = Math.round(u * 0.625), co = 24, G = 32, uo = 20, lo = ({ icon: a }) => {
22
- const i = Y(a?.guid);
21
+ var u = 32, co = Math.round(u * 0.625), uo = 24, G = 32, lo = 20, mo = ({ icon: a }) => {
22
+ const i = J(a?.guid);
23
23
  return i ? /* @__PURE__ */ t(d, {
24
24
  "aria-hidden": !0,
25
25
  "data-icon": i,
@@ -36,12 +36,12 @@ var u = 32, so = Math.round(u * 0.625), co = 24, G = 32, uo = 20, lo = ({ icon:
36
36
  children: /* @__PURE__ */ t(T, {
37
37
  fill: !0,
38
38
  name: i,
39
- size: uo,
39
+ size: lo,
40
40
  sx: { color: `${I(a?.color)}.contrastText` }
41
41
  })
42
42
  }) : null;
43
- }, mo = (a, i, c, l) => {
44
- const o = U(a.logo, a.primary_text);
43
+ }, go = (a, i, c, l) => {
44
+ const o = W(a.logo, a.primary_text);
45
45
  if (o) {
46
46
  if (o.logo_name) {
47
47
  const e = !!o.logo_fill, r = o.logo_color ?? c.palette.chart.chart2 ?? c.palette.primary.main;
@@ -59,18 +59,18 @@ var u = 32, so = Math.round(u * 0.625), co = 24, G = 32, uo = 20, lo = ({ icon:
59
59
  },
60
60
  children: /* @__PURE__ */ t(T, {
61
61
  name: o.logo_name,
62
- size: so,
62
+ size: co,
63
63
  sx: { color: e ? r : o.logo_color }
64
64
  })
65
65
  });
66
66
  }
67
- if (o.merchant_guid) return /* @__PURE__ */ t(no, {
67
+ if (o.merchant_guid) return /* @__PURE__ */ t(ao, {
68
68
  alt: o.merchant_name ?? "",
69
69
  categoryGuid: o.category_guid ? i(o.category_guid) : "",
70
70
  merchantGuid: o.merchant_guid,
71
71
  size: u
72
72
  });
73
- if (o.institution_guid) return /* @__PURE__ */ t(io, {
73
+ if (o.institution_guid) return /* @__PURE__ */ t(no, {
74
74
  alt: o.institution_name ?? "",
75
75
  institutionGuid: o.institution_guid,
76
76
  size: u
@@ -84,7 +84,7 @@ var u = 32, so = Math.round(u * 0.625), co = 24, G = 32, uo = 20, lo = ({ icon:
84
84
  return /* @__PURE__ */ t(d, {
85
85
  "data-testid": `category-icon-${e}`,
86
86
  sx: { display: "flex" },
87
- children: /* @__PURE__ */ t(eo, {
87
+ children: /* @__PURE__ */ t(io, {
88
88
  categoryGuid: e,
89
89
  size: u,
90
90
  sx: r
@@ -92,20 +92,20 @@ var u = 32, so = Math.round(u * 0.625), co = 24, G = 32, uo = 20, lo = ({ icon:
92
92
  });
93
93
  }
94
94
  }
95
- }, Ao = ro(({ payload: a }) => {
96
- const i = ao(), { getTopLevelCategoryGuid: c } = j(), l = D(), { recurring: o } = q(), { beat: e } = H(), { data: r, variant: E } = a.instance_slot, { answeredBackground: p, background: m, cardVariant: B, elevated: L, followsSubscription: g, raised: k, showFooter: O, showFrequency: y, showHeader: R, statusMessage: A, sx: w, tintedCategoryLogo: z } = J(oo(i), E, to.NoHeader, "TransactionBlock"), _ = (y || g) && e ? V({
95
+ }, wo = eo(({ payload: a }) => {
96
+ const i = so(), { getTopLevelCategoryGuid: c } = q(), l = H(), { recurring: o } = D(), { beat: e } = P(), { data: r, variant: E } = a.instance_slot, { answeredBackground: p, background: m, cardVariant: B, elevated: L, followsSubscription: g, headerColor: k, raised: O, showFooter: R, showFrequency: y, showHeader: A, statusMessage: w, sx: z, tintedCategoryLogo: F } = K(to(i), E, ro.NoHeader, "TransactionBlock"), _ = (y || g) && e ? U({
97
97
  beat: e,
98
98
  stores: l
99
- }) : void 0, h = !!g && _?.user_response === P.CONFIRMED;
100
- if (A) {
99
+ }) : void 0, h = !!g && _?.user_response === V.CONFIRMED;
100
+ if (w) {
101
101
  const n = s(r, "message");
102
- return typeof n != "string" || !n.trim() ? (console.warn("[TransactionBlock] status_message has no message — rendering nothing."), null) : /* @__PURE__ */ t(Q, {
102
+ return typeof n != "string" || !n.trim() ? (console.warn("[TransactionBlock] status_message has no message — rendering nothing."), null) : /* @__PURE__ */ t(X, {
103
103
  icon: /* @__PURE__ */ t(d, {
104
104
  "aria-hidden": "true",
105
105
  sx: { display: "flex" },
106
- children: /* @__PURE__ */ t(W, {
106
+ children: /* @__PURE__ */ t(Y, {
107
107
  logo: s(r, "icon"),
108
- size: co
108
+ size: uo
109
109
  })
110
110
  }),
111
111
  message: n,
@@ -117,30 +117,31 @@ var u = 32, so = Math.round(u * 0.625), co = 24, G = 32, uo = 20, lo = ({ icon:
117
117
  }
118
118
  const f = s(r, "series"), x = s(r, "header_text");
119
119
  if (!Array.isArray(f) || !f.length) return null;
120
- const F = R && typeof x == "string" ? x : void 0, b = s(r, "footer_text"), N = s(r, "footer_amount"), M = O && typeof b == "string" ? {
120
+ const N = A && typeof x == "string" ? x : void 0, b = s(r, "footer_text"), M = s(r, "footer_amount"), Z = R && typeof b == "string" ? {
121
121
  label: b,
122
- amount: v(N, "0,0.00")
123
- } : void 0, Z = y ? X(o, _) : void 0, $ = g ? /* @__PURE__ */ t(lo, { icon: s(r, h ? "reviewed_icon" : "icon") }) : void 0;
124
- return /* @__PURE__ */ t(K, {
122
+ amount: v(M, "0,0.00")
123
+ } : void 0, $ = y ? oo(o, _) : void 0, j = g ? /* @__PURE__ */ t(mo, { icon: s(r, h ? "reviewed_icon" : "icon") }) : void 0;
124
+ return /* @__PURE__ */ t(Q, {
125
125
  background: h && p ? p : m,
126
- badge: $,
126
+ badge: j,
127
127
  elevated: L,
128
- footer: M,
129
- header: F,
130
- raised: k,
131
- sx: w,
128
+ footer: Z,
129
+ header: N,
130
+ headerColor: k,
131
+ raised: O,
132
+ sx: z,
132
133
  variant: B,
133
134
  rows: f.map((n) => ({
134
135
  amount: typeof n.amount == "number" ? v(n.amount, "0,0.00") : "",
135
- amountCaption: Z,
136
- leading: mo(n, c, i, z ?? !1),
136
+ amountCaption: $,
137
+ leading: go(n, c, i, F ?? !1),
137
138
  subtitle: n.secondary_text ?? "",
138
139
  title: n.primary_text ?? ""
139
140
  }))
140
141
  });
141
142
  });
142
143
  export {
143
- Ao as TransactionBlock
144
+ wo as TransactionBlock
144
145
  };
145
146
 
146
147
  //# sourceMappingURL=TransactionBlock.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport { alpha, useTheme } from '@mui/material/styles'\nimport type { Theme } from '@mui/material/styles'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\n\nimport { useCategoryStore, useGlobalCopyStore, useGlobalStore } from '../../../../common'\nimport { slot } from '../../../../core'\nimport type { InsightsPayload, InstanceSlotRow, LogoRef } from '../../../../core'\nimport { getCategoryColor } from '../../../../core/utils/CategoryUtil'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport { useBeatActions } from '../../../beatActions'\nimport LogoFromGuid from '../../../components/LogoFromGuid'\nimport StatusMessageCard from '../../../components/StatusMessageCard'\nimport TransactionListCard from '../../../components/TransactionListCard'\nimport { logoFromRef } from '../../../components/shared/EntityLogo'\nimport { statusIconName, statusIconPalette } from '../../../components/statusIcon'\nimport { subscriptionFrequency } from '../../../components/SubscriptionStatus/subscriptionFrequency'\nimport { repeatingTransactionOf, USER_RESPONSE } from '../../../ctaActions/subscriptionAnswer'\n\nimport { resolveVariantConfig } from '../../resolveVariantConfig'\nimport { getLayoutConfig, transactionBlockVariant } from './layout'\n\ninterface TransactionBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\nconst ROW_LOGO_SIZE = 32\n// Same glyph-to-tile ratio mxui's `CategoryIcon` uses, so a status icon sits like the other logos.\nconst ROW_ICON_SIZE = Math.round(ROW_LOGO_SIZE * 0.625)\nconst STATUS_ICON_SIZE = 24\n// Status badge: palette disc, contrastText glyph.\nconst BADGE_SIZE = 32\nconst BADGE_GLYPH_SIZE = 20\n\n/** Status disc from `data.icon` / `data.reviewed_icon`. */\nconst SubscriptionBadge = ({ icon }: { icon?: LogoRef }) => {\n const name = statusIconName(icon?.guid)\n\n if (!name) return null\n\n return (\n <Box\n aria-hidden={true}\n data-icon={name}\n data-testid=\"subscription-badge\"\n sx={{\n alignItems: 'center',\n bgcolor: `${statusIconPalette(icon?.color)}.main`,\n borderRadius: '50%',\n display: 'flex',\n height: BADGE_SIZE,\n justifyContent: 'center',\n width: BADGE_SIZE,\n }}\n >\n <Icon\n fill={true}\n name={name}\n size={BADGE_GLYPH_SIZE}\n sx={{ color: `${statusIconPalette(icon?.color)}.contrastText` }}\n />\n </Box>\n )\n}\n\n/**\n * Renders the row's leading logo from its `LogoRef`: a status icon, or an entity guid whose prefix\n * names the entity. An unrecognized prefix renders no logo rather than guessing.\n *\n * `resolveTopLevelCategory`: mxui's `CategoryIcon` only knows the top-level category guids and\n * silently falls back to the Uncategorized icon for a sub-category. The details drawer avoids\n * this by passing `transaction.top_level_category_guid`; the row only has the raw guid, so it is\n * walked up to its parent here (identity until categories load). That resolution applies both to a\n * `CAT-` row logo and to a merchant's `fallback_guid`. The tinted/bordered tile is opt-in per variant\n * (`tintedCategoryLogo`) and only styles the `CAT-` row branch; a merchant's `fallback_guid` is drawn\n * by `MerchantLogo`'s own untinted `CategoryIcon` fallback when the merchant image fails to load.\n */\nconst renderRowLogo = (\n row: InstanceSlotRow,\n resolveTopLevelCategory: (guid: string) => string,\n theme: Theme,\n tintedCategoryLogo: boolean,\n) => {\n const logo = logoFromRef(row.logo, row.primary_text)\n\n if (!logo) return undefined\n\n if (logo.logo_name) {\n // A `{ icon, color }` status logo (e.g. an overdraft warning) renders as a bare coloured glyph.\n // An ICO- fill logo (the Weekly New Merchants \"Others\" row - `logo_fill` is set for ICO- refs\n // only, in EntityLogo) renders as an accent tile: per the MX accent-icon pattern the background is\n // the tile colour at 15% opacity and the glyph is the full tile colour (Figma). The tile colour is\n // the logo's own colour when it carries one, else chart-2 - so tile and glyph always match.\n const accentTile = !!logo.logo_fill\n const tileColor = logo.logo_color ?? theme.palette.chart.chart2 ?? theme.palette.primary.main\n return (\n <Box\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: ROW_LOGO_SIZE,\n justifyContent: 'center',\n width: ROW_LOGO_SIZE,\n ...(accentTile && {\n bgcolor: alpha(tileColor, 0.15),\n borderRadius: '8px',\n }),\n }}\n >\n <Icon\n name={logo.logo_name}\n size={ROW_ICON_SIZE}\n sx={{ color: accentTile ? tileColor : logo.logo_color }}\n />\n </Box>\n )\n }\n\n if (logo.merchant_guid) {\n return (\n <MerchantLogo\n alt={logo.merchant_name ?? ''}\n categoryGuid={logo.category_guid ? resolveTopLevelCategory(logo.category_guid) : ''}\n merchantGuid={logo.merchant_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.institution_guid) {\n return (\n <InstitutionLogo\n alt={logo.institution_name ?? ''}\n institutionGuid={logo.institution_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.category_guid) {\n const topLevelGuid = resolveTopLevelCategory(logo.category_guid)\n // When the variant opts in (`tintedCategoryLogo`), the tile is the Budget-style accent: the\n // category colour at 15% opacity, a 1px category-colour border, and a `text.primary` glyph\n // (Figma - Replenish Savings' multi-account Transfer row). Otherwise mxui's default tile, so other\n // beats' category logos are unchanged.\n const tintSx = tintedCategoryLogo\n ? {\n bgcolor: alpha(getCategoryColor(topLevelGuid, theme), 0.15),\n border: `1px solid ${getCategoryColor(topLevelGuid, theme)}`,\n color: 'text.primary',\n }\n : undefined\n return (\n <Box data-testid={`category-icon-${topLevelGuid}`} sx={{ display: 'flex' }}>\n <CategoryIcon categoryGuid={topLevelGuid} size={ROW_LOGO_SIZE} sx={tintSx} />\n </Box>\n )\n }\n\n return undefined\n}\n\n/**\n * The `transaction_block`: rows the backend already localized, carried inline on\n * `instance_slot.data.series` (`logo`, `primary_text`, `secondary_text`, `amount`). Only the\n * amount is formatted here, because the contract sends it as a number. `instance_slot.variant`\n * picks the header and slot treatment from `./layout.ts`.\n *\n * This is the full/mini shape. The reduced widgets (micro, embedded) resolve to the row logo\n * alone, carried flat on `data.logo` with no `series`, and are drawn by `CompactInsightCard`.\n *\n * `status_message` draws no rows: `data.message` beside the `data.icon` logo, as a\n * `StatusMessageCard` banner (Uncategorized Transactions V2 `complete`).\n *\n * A header, when the variant shows one, comes from `instance_slot.data.header_text` (the\n * transaction date, or \"{count} transactions\"). It deliberately does *not* come from the first\n * row: on a `with_merchant` card a row's `secondary_text` is the category, so reading it here\n * rendered the category twice and dropped the date entirely.\n *\n * A footer/summary row (Replenish Savings' \"Remaining Balance\", Weekly New Merchants' \"Total\")\n * renders when the variant's `showFooter` config is set (`with_header_footer`, `with_footer`), from\n * `data.footer_text` with `data.footer_amount` beside it, formatted like the row amounts (the\n * contract sends it as a number).\n */\nexport const TransactionBlock = observer(({ payload }: TransactionBlockProps) => {\n const theme = useTheme()\n const { getTopLevelCategoryGuid } = useCategoryStore()\n const stores = useGlobalStore()\n const { recurring: recurringCopy } = useGlobalCopyStore()\n const { beat } = useBeatActions()\n const { data, variant } = payload.instance_slot\n // The plain row is the safe default: it adds nothing a wrong variant could misstate.\n const {\n answeredBackground,\n background,\n cardVariant,\n elevated,\n followsSubscription,\n raised,\n showFooter,\n showFrequency,\n showHeader,\n statusMessage,\n sx,\n tintedCategoryLogo,\n } = resolveVariantConfig(\n getLayoutConfig(theme),\n variant,\n transactionBlockVariant.NoHeader,\n 'TransactionBlock',\n )\n\n // The live repeating transaction (read-only), for the frequency and the badge / answered wash.\n const repeating =\n (showFrequency || followsSubscription) && beat\n ? repeatingTransactionOf({ beat, stores })\n : undefined\n const subscribed = !!followsSubscription && repeating?.user_response === USER_RESPONSE.CONFIRMED\n\n if (statusMessage) {\n const message = slot<string>(data, 'message')\n if (typeof message !== 'string' || !message.trim()) {\n console.warn('[TransactionBlock] status_message has no message — rendering nothing.')\n return null\n }\n\n // The icon only decorates the message, so it is hidden from the status announcement.\n return (\n <StatusMessageCard\n icon={\n <Box aria-hidden=\"true\" sx={{ display: 'flex' }}>\n <LogoFromGuid logo={slot<LogoRef>(data, 'icon')} size={STATUS_ICON_SIZE} />\n </Box>\n }\n message={message}\n // The 20% wash layers over paper, as Figma's slot does.\n sx={background ? { backgroundImage: background, bgcolor: 'background.paper' } : undefined}\n />\n )\n }\n\n const series = slot<InstanceSlotRow[]>(data, 'series')\n const headerText = slot<string>(data, 'header_text')\n\n if (!Array.isArray(series) || !series.length) return null\n\n const header = showHeader && typeof headerText === 'string' ? headerText : undefined\n\n const footerText = slot<string>(data, 'footer_text')\n const footerAmount = slot<number>(data, 'footer_amount')\n const footer =\n showFooter && typeof footerText === 'string'\n ? {\n label: footerText,\n amount: formatCurrency(footerAmount, '0,0.00'),\n }\n : undefined\n\n // Live, as pulse: the repeating transaction the CTA's `prepare` loads.\n const frequency = showFrequency ? subscriptionFrequency(recurringCopy, repeating) : undefined\n const badge = followsSubscription ? (\n <SubscriptionBadge icon={slot<LogoRef>(data, subscribed ? 'reviewed_icon' : 'icon')} />\n ) : undefined\n\n return (\n <TransactionListCard\n background={subscribed && answeredBackground ? answeredBackground : background}\n badge={badge}\n elevated={elevated}\n footer={footer}\n header={header}\n raised={raised}\n sx={sx}\n variant={cardVariant}\n rows={series.map((row) => ({\n amount: typeof row.amount === 'number' ? formatCurrency(row.amount, '0,0.00') : '',\n amountCaption: frequency,\n leading: renderRowLogo(row, getTopLevelCategoryGuid, theme, tintedCategoryLogo ?? false),\n subtitle: row.secondary_text ?? '',\n title: row.primary_text ?? '',\n }))}\n />\n )\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"TransactionBlock.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/TransactionBlock/TransactionBlock.tsx"],"sourcesContent":["import { observer } from 'mobx-react-lite'\n\nimport Box from '@mui/material/Box'\nimport { alpha, useTheme } from '@mui/material/styles'\nimport type { Theme } from '@mui/material/styles'\n\nimport { CategoryIcon, InstitutionLogo, MerchantLogo } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\n\nimport { useCategoryStore, useGlobalCopyStore, useGlobalStore } from '../../../../common'\nimport { slot } from '../../../../core'\nimport type { InsightsPayload, InstanceSlotRow, LogoRef } from '../../../../core'\nimport { getCategoryColor } from '../../../../core/utils/CategoryUtil'\nimport { formatCurrency } from '../../../../core/utils/NumberFormatting'\n\nimport { useBeatActions } from '../../../beatActions'\nimport LogoFromGuid from '../../../components/LogoFromGuid'\nimport StatusMessageCard from '../../../components/StatusMessageCard'\nimport TransactionListCard from '../../../components/TransactionListCard'\nimport { logoFromRef } from '../../../components/shared/EntityLogo'\nimport { statusIconName, statusIconPalette } from '../../../components/statusIcon'\nimport { subscriptionFrequency } from '../../../components/SubscriptionStatus/subscriptionFrequency'\nimport { repeatingTransactionOf, USER_RESPONSE } from '../../../ctaActions/subscriptionAnswer'\n\nimport { resolveVariantConfig } from '../../resolveVariantConfig'\nimport { getLayoutConfig, transactionBlockVariant } from './layout'\n\ninterface TransactionBlockProps {\n payload: InsightsPayload\n beatGuid?: string\n}\n\nconst ROW_LOGO_SIZE = 32\n// Same glyph-to-tile ratio mxui's `CategoryIcon` uses, so a status icon sits like the other logos.\nconst ROW_ICON_SIZE = Math.round(ROW_LOGO_SIZE * 0.625)\nconst STATUS_ICON_SIZE = 24\n// Status badge: palette disc, contrastText glyph.\nconst BADGE_SIZE = 32\nconst BADGE_GLYPH_SIZE = 20\n\n/** Status disc from `data.icon` / `data.reviewed_icon`. */\nconst SubscriptionBadge = ({ icon }: { icon?: LogoRef }) => {\n const name = statusIconName(icon?.guid)\n\n if (!name) return null\n\n return (\n <Box\n aria-hidden={true}\n data-icon={name}\n data-testid=\"subscription-badge\"\n sx={{\n alignItems: 'center',\n bgcolor: `${statusIconPalette(icon?.color)}.main`,\n borderRadius: '50%',\n display: 'flex',\n height: BADGE_SIZE,\n justifyContent: 'center',\n width: BADGE_SIZE,\n }}\n >\n <Icon\n fill={true}\n name={name}\n size={BADGE_GLYPH_SIZE}\n sx={{ color: `${statusIconPalette(icon?.color)}.contrastText` }}\n />\n </Box>\n )\n}\n\n/**\n * Renders the row's leading logo from its `LogoRef`: a status icon, or an entity guid whose prefix\n * names the entity. An unrecognized prefix renders no logo rather than guessing.\n *\n * `resolveTopLevelCategory`: mxui's `CategoryIcon` only knows the top-level category guids and\n * silently falls back to the Uncategorized icon for a sub-category. The details drawer avoids\n * this by passing `transaction.top_level_category_guid`; the row only has the raw guid, so it is\n * walked up to its parent here (identity until categories load). That resolution applies both to a\n * `CAT-` row logo and to a merchant's `fallback_guid`. The tinted/bordered tile is opt-in per variant\n * (`tintedCategoryLogo`) and only styles the `CAT-` row branch; a merchant's `fallback_guid` is drawn\n * by `MerchantLogo`'s own untinted `CategoryIcon` fallback when the merchant image fails to load.\n */\nconst renderRowLogo = (\n row: InstanceSlotRow,\n resolveTopLevelCategory: (guid: string) => string,\n theme: Theme,\n tintedCategoryLogo: boolean,\n) => {\n const logo = logoFromRef(row.logo, row.primary_text)\n\n if (!logo) return undefined\n\n if (logo.logo_name) {\n // A `{ icon, color }` status logo (e.g. an overdraft warning) renders as a bare coloured glyph.\n // An ICO- fill logo (the Weekly New Merchants \"Others\" row - `logo_fill` is set for ICO- refs\n // only, in EntityLogo) renders as an accent tile: per the MX accent-icon pattern the background is\n // the tile colour at 15% opacity and the glyph is the full tile colour (Figma). The tile colour is\n // the logo's own colour when it carries one, else chart-2 - so tile and glyph always match.\n const accentTile = !!logo.logo_fill\n const tileColor = logo.logo_color ?? theme.palette.chart.chart2 ?? theme.palette.primary.main\n return (\n <Box\n sx={{\n alignItems: 'center',\n display: 'flex',\n height: ROW_LOGO_SIZE,\n justifyContent: 'center',\n width: ROW_LOGO_SIZE,\n ...(accentTile && {\n bgcolor: alpha(tileColor, 0.15),\n borderRadius: '8px',\n }),\n }}\n >\n <Icon\n name={logo.logo_name}\n size={ROW_ICON_SIZE}\n sx={{ color: accentTile ? tileColor : logo.logo_color }}\n />\n </Box>\n )\n }\n\n if (logo.merchant_guid) {\n return (\n <MerchantLogo\n alt={logo.merchant_name ?? ''}\n categoryGuid={logo.category_guid ? resolveTopLevelCategory(logo.category_guid) : ''}\n merchantGuid={logo.merchant_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.institution_guid) {\n return (\n <InstitutionLogo\n alt={logo.institution_name ?? ''}\n institutionGuid={logo.institution_guid}\n size={ROW_LOGO_SIZE}\n />\n )\n }\n\n if (logo.category_guid) {\n const topLevelGuid = resolveTopLevelCategory(logo.category_guid)\n // When the variant opts in (`tintedCategoryLogo`), the tile is the Budget-style accent: the\n // category colour at 15% opacity, a 1px category-colour border, and a `text.primary` glyph\n // (Figma - Replenish Savings' multi-account Transfer row). Otherwise mxui's default tile, so other\n // beats' category logos are unchanged.\n const tintSx = tintedCategoryLogo\n ? {\n bgcolor: alpha(getCategoryColor(topLevelGuid, theme), 0.15),\n border: `1px solid ${getCategoryColor(topLevelGuid, theme)}`,\n color: 'text.primary',\n }\n : undefined\n return (\n <Box data-testid={`category-icon-${topLevelGuid}`} sx={{ display: 'flex' }}>\n <CategoryIcon categoryGuid={topLevelGuid} size={ROW_LOGO_SIZE} sx={tintSx} />\n </Box>\n )\n }\n\n return undefined\n}\n\n/**\n * The `transaction_block`: rows the backend already localized, carried inline on\n * `instance_slot.data.series` (`logo`, `primary_text`, `secondary_text`, `amount`). Only the\n * amount is formatted here, because the contract sends it as a number. `instance_slot.variant`\n * picks the header and slot treatment from `./layout.ts`.\n *\n * This is the full/mini shape. The reduced widgets (micro, embedded) resolve to the row logo\n * alone, carried flat on `data.logo` with no `series`, and are drawn by `CompactInsightCard`.\n *\n * `status_message` draws no rows: `data.message` beside the `data.icon` logo, as a\n * `StatusMessageCard` banner (Uncategorized Transactions V2 `complete`).\n *\n * A header, when the variant shows one, comes from `instance_slot.data.header_text` (the\n * transaction date, or \"{count} transactions\"). It deliberately does *not* come from the first\n * row: on a `with_merchant` card a row's `secondary_text` is the category, so reading it here\n * rendered the category twice and dropped the date entirely.\n *\n * A footer/summary row (Replenish Savings' \"Remaining Balance\", Weekly New Merchants' \"Total\")\n * renders when the variant's `showFooter` config is set (`with_header_footer`, `with_footer`), from\n * `data.footer_text` with `data.footer_amount` beside it, formatted like the row amounts (the\n * contract sends it as a number).\n */\nexport const TransactionBlock = observer(({ payload }: TransactionBlockProps) => {\n const theme = useTheme()\n const { getTopLevelCategoryGuid } = useCategoryStore()\n const stores = useGlobalStore()\n const { recurring: recurringCopy } = useGlobalCopyStore()\n const { beat } = useBeatActions()\n const { data, variant } = payload.instance_slot\n // The plain row is the safe default: it adds nothing a wrong variant could misstate.\n const {\n answeredBackground,\n background,\n cardVariant,\n elevated,\n followsSubscription,\n headerColor,\n raised,\n showFooter,\n showFrequency,\n showHeader,\n statusMessage,\n sx,\n tintedCategoryLogo,\n } = resolveVariantConfig(\n getLayoutConfig(theme),\n variant,\n transactionBlockVariant.NoHeader,\n 'TransactionBlock',\n )\n\n // The live repeating transaction (read-only), for the frequency and the badge / answered wash.\n const repeating =\n (showFrequency || followsSubscription) && beat\n ? repeatingTransactionOf({ beat, stores })\n : undefined\n const subscribed = !!followsSubscription && repeating?.user_response === USER_RESPONSE.CONFIRMED\n\n if (statusMessage) {\n const message = slot<string>(data, 'message')\n if (typeof message !== 'string' || !message.trim()) {\n console.warn('[TransactionBlock] status_message has no message — rendering nothing.')\n return null\n }\n\n // The icon only decorates the message, so it is hidden from the status announcement.\n return (\n <StatusMessageCard\n icon={\n <Box aria-hidden=\"true\" sx={{ display: 'flex' }}>\n <LogoFromGuid logo={slot<LogoRef>(data, 'icon')} size={STATUS_ICON_SIZE} />\n </Box>\n }\n message={message}\n // The 20% wash layers over paper, as Figma's slot does.\n sx={background ? { backgroundImage: background, bgcolor: 'background.paper' } : undefined}\n />\n )\n }\n\n const series = slot<InstanceSlotRow[]>(data, 'series')\n const headerText = slot<string>(data, 'header_text')\n\n if (!Array.isArray(series) || !series.length) return null\n\n const header = showHeader && typeof headerText === 'string' ? headerText : undefined\n\n const footerText = slot<string>(data, 'footer_text')\n const footerAmount = slot<number>(data, 'footer_amount')\n const footer =\n showFooter && typeof footerText === 'string'\n ? {\n label: footerText,\n amount: formatCurrency(footerAmount, '0,0.00'),\n }\n : undefined\n\n // Live, as pulse: the repeating transaction the CTA's `prepare` loads.\n const frequency = showFrequency ? subscriptionFrequency(recurringCopy, repeating) : undefined\n const badge = followsSubscription ? (\n <SubscriptionBadge icon={slot<LogoRef>(data, subscribed ? 'reviewed_icon' : 'icon')} />\n ) : undefined\n\n return (\n <TransactionListCard\n background={subscribed && answeredBackground ? answeredBackground : background}\n badge={badge}\n elevated={elevated}\n footer={footer}\n header={header}\n headerColor={headerColor}\n raised={raised}\n sx={sx}\n variant={cardVariant}\n rows={series.map((row) => ({\n amount: typeof row.amount === 'number' ? formatCurrency(row.amount, '0,0.00') : '',\n amountCaption: frequency,\n leading: renderRowLogo(row, getTopLevelCategoryGuid, theme, tintedCategoryLogo ?? false),\n subtitle: row.secondary_text ?? '',\n title: row.primary_text ?? '',\n }))}\n />\n )\n})\n"],"mappings":"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"}
@@ -14,6 +14,8 @@ import { SxProps, Theme } from '@mui/material/styles';
14
14
  * Subscription Payment). Treatment names, not beat names, so any beat can reuse the wash.
15
15
  * - `StatusMessage` — no rows: an icon + message banner from `data.icon` / `data.message`
16
16
  * (Uncategorized Transactions V2 `complete`, "All Categorized!").
17
+ * - `SpendingSummary` — header, rows and footer, with the header text in `primary.main`
18
+ * (Weekend Spending Summary: the weekend above one row per category and "Total spent").
17
19
  */
18
20
  export declare const transactionBlockVariant: {
19
21
  readonly WithHeader: "with_header";
@@ -24,6 +26,7 @@ export declare const transactionBlockVariant: {
24
26
  readonly InfoWash: "info_wash";
25
27
  readonly WarningWash: "warning_wash";
26
28
  readonly StatusMessage: "status_message";
29
+ readonly SpendingSummary: "spending_summary";
27
30
  };
28
31
  export type TransactionBlockVariant = (typeof transactionBlockVariant)[keyof typeof transactionBlockVariant];
29
32
  export interface TransactionLayoutConfig {
@@ -33,6 +36,8 @@ export interface TransactionLayoutConfig {
33
36
  showFooter?: boolean;
34
37
  /** `TransactionListCard` style: grey utility header, or filled primary header. */
35
38
  cardVariant?: 'default' | 'primary';
39
+ /** Theme colour for the header text, over the card style's own. */
40
+ headerColor?: string;
36
41
  /** CSS background for the slot behind the card; the card renders borderless unless `raised`. */
37
42
  background?: string;
38
43
  /** Render `data.message` as a `StatusMessageCard` banner instead of the rows. */
@@ -1,4 +1,4 @@
1
- import { WARM_LIME_ACCENT_GRADIENT as a, WARNING_WASH_GRADIENT as t, getPrimaryWashGradient as o } from "../../../components/celebrationGradients.es.js";
1
+ import { WARM_LIME_ACCENT_GRADIENT as r, WARNING_WASH_GRADIENT as o, getPrimaryWashGradient as t } from "../../../components/celebrationGradients.es.js";
2
2
  var e = {
3
3
  WithHeader: "with_header",
4
4
  WithHeaderFooter: "with_header_footer",
@@ -7,8 +7,9 @@ var e = {
7
7
  UncategorizedTransaction: "uncategorized_transaction",
8
8
  InfoWash: "info_wash",
9
9
  WarningWash: "warning_wash",
10
- StatusMessage: "status_message"
11
- }, n = (r) => ({
10
+ StatusMessage: "status_message",
11
+ SpendingSummary: "spending_summary"
12
+ }, n = (a) => ({
12
13
  [e.WithHeader]: {
13
14
  showHeader: !0,
14
15
  tintedCategoryLogo: !0
@@ -28,23 +29,28 @@ var e = {
28
29
  },
29
30
  [e.InfoWash]: {
30
31
  showHeader: !1,
31
- background: o(r),
32
+ background: t(a),
32
33
  raised: !0,
33
34
  showFrequency: !0
34
35
  },
35
36
  [e.WarningWash]: {
36
37
  showHeader: !1,
37
- background: t,
38
+ background: o,
38
39
  showFrequency: !0,
39
40
  followsSubscription: !0,
40
- answeredBackground: a,
41
+ answeredBackground: r,
41
42
  elevated: !0,
42
43
  sx: { p: "28px 24px 24px 32px" }
43
44
  },
44
45
  [e.StatusMessage]: {
45
46
  showHeader: !1,
46
47
  statusMessage: !0,
47
- background: a
48
+ background: r
49
+ },
50
+ [e.SpendingSummary]: {
51
+ showHeader: !0,
52
+ showFooter: !0,
53
+ headerColor: "primary.main"
48
54
  }
49
55
  });
50
56
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/TransactionBlock/layout.ts"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles'\n\nimport {\n WARM_LIME_ACCENT_GRADIENT,\n WARNING_WASH_GRADIENT,\n getPrimaryWashGradient,\n} from '../../../components/celebrationGradients'\n\n/**\n * Transaction block variants, keyed by the backend `instance_slot.variant`. All render the same\n * pre-localized rows through `TransactionListCard`; only the header and the slot differ.\n *\n * - `WithHeader` — row under a date header (Fee Detected, Large Transaction).\n * - `WithHeaderFooter` — date header above the rows plus the footer/summary row from\n * `data.footer_text` / `data.footer_amount` (Replenish Savings' \"Remaining Balance\").\n * - `NoHeader` — the row alone (Large Transaction without a merchant).\n * - `UncategorizedTransaction` — filled primary header (\"{count} transactions\").\n * - `InfoWash` — raised row (border + shadow) on the blue slot wash, with the\n * subscription's live frequency under the amount (e.g. Subscription Detected).\n * - `WarningWash` — borderless row on the warning slot wash (e.g. Unexpected\n * Subscription Payment). Treatment names, not beat names, so any beat can reuse the wash.\n * - `StatusMessage` — no rows: an icon + message banner from `data.icon` / `data.message`\n * (Uncategorized Transactions V2 `complete`, \"All Categorized!\").\n */\nexport const transactionBlockVariant = {\n WithHeader: 'with_header',\n WithHeaderFooter: 'with_header_footer',\n NoHeader: 'no_header',\n // A multi-row list with no in-card header plus a \"Total\" summary row (Weekly New Merchants; the\n // date range is the card subtitle). The plain no-footer list reuses `NoHeader`.\n WithFooter: 'with_footer',\n UncategorizedTransaction: 'uncategorized_transaction',\n InfoWash: 'info_wash',\n WarningWash: 'warning_wash',\n StatusMessage: 'status_message',\n} as const\n\nexport type TransactionBlockVariant =\n (typeof transactionBlockVariant)[keyof typeof transactionBlockVariant]\n\nexport interface TransactionLayoutConfig {\n /** Show `instance_slot.data.header_text` above the rows. */\n showHeader: boolean\n /** Show the `data.footer_text` / `data.footer_amount` summary row beneath the rows. */\n showFooter?: boolean\n /** `TransactionListCard` style: grey utility header, or filled primary header. */\n cardVariant?: 'default' | 'primary'\n /** CSS background for the slot behind the card; the card renders borderless unless `raised`. */\n background?: string\n /** Render `data.message` as a `StatusMessageCard` banner instead of the rows. */\n statusMessage?: boolean\n /** Caption each amount with the beat's live repeating transaction frequency. */\n showFrequency?: boolean\n /** Status badge and answered wash from the live repeating transaction. */\n followsSubscription?: boolean\n /** Wash once subscribed. */\n answeredBackground?: string\n /** Row card at `elevation/1` (needs `background`). */\n elevated?: boolean\n /** Slot padding override (CSS shorthand). */\n sx?: SxProps\n /** Border and shadow on the row card. */\n raised?: boolean\n /**\n * Tint a `CAT-` row logo as the Budget-style accent tile (category colour at 15% opacity, a 1px\n * category-colour border, a `text.primary` glyph) instead of mxui's default. Opt-in per variant so\n * it stays scoped to the beats that want it (Replenish Savings' multi-account Transfer row), not\n * every `transaction_block` consumer.\n */\n tintedCategoryLogo?: boolean\n}\n\n/** Per-variant `TransactionListCard` props (mirrors DetailedAccountBlock's `getLayoutConfig`). */\nexport const getLayoutConfig = (\n theme: Theme,\n): Record<TransactionBlockVariant, TransactionLayoutConfig> => ({\n // `with_header` is Replenish Savings' multi-account card: its one summary row is a `CAT-` Transfer\n // logo, which we tint. (Other `with_header` beats, e.g. Large Transaction, use a merchant logo, so\n // the `CAT-` tint path never runs for them.)\n [transactionBlockVariant.WithHeader]: { showHeader: true, tintedCategoryLogo: true },\n [transactionBlockVariant.WithHeaderFooter]: { showHeader: true, showFooter: true },\n [transactionBlockVariant.NoHeader]: { showHeader: false },\n [transactionBlockVariant.WithFooter]: { showHeader: false, showFooter: true },\n [transactionBlockVariant.UncategorizedTransaction]: { showHeader: true, cardVariant: 'primary' },\n [transactionBlockVariant.InfoWash]: {\n showHeader: false,\n background: getPrimaryWashGradient(theme),\n raised: true,\n showFrequency: true,\n },\n [transactionBlockVariant.WarningWash]: {\n showHeader: false,\n background: WARNING_WASH_GRADIENT,\n showFrequency: true,\n followsSubscription: true,\n answeredBackground: WARM_LIME_ACCENT_GRADIENT,\n elevated: true,\n // Room for the badge.\n sx: { p: '28px 24px 24px 32px' },\n },\n // Figma 1941:207336: the banner sits on the warm-to-lime slot wash.\n [transactionBlockVariant.StatusMessage]: {\n showHeader: false,\n statusMessage: true,\n background: WARM_LIME_ACCENT_GRADIENT,\n },\n})\n"],"mappings":";AAwBA,IAAa,IAA0B;AAAA,EACrC,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,UAAU;AAAA,EAGV,YAAY;AAAA,EACZ,0BAA0B;AAAA,EAC1B,UAAU;AAAA,EACV,aAAa;AAAA,EACb,eAAe;AACjB,GAsCa,IAAA,CACX,OAC8D;AAAA,EAI7D,CAAA,EAAwB,UAAA,GAAa;AAAA,IAAE,YAAY;AAAA,IAAM,oBAAoB;AAAA,EAAK;AAAA,EAClF,CAAA,EAAwB,gBAAA,GAAmB;AAAA,IAAE,YAAY;AAAA,IAAM,YAAY;AAAA,EAAK;AAAA,EAChF,CAAA,EAAwB,QAAA,GAAW,EAAE,YAAY,GAAM;AAAA,EACvD,CAAA,EAAwB,UAAA,GAAa;AAAA,IAAE,YAAY;AAAA,IAAO,YAAY;AAAA,EAAK;AAAA,EAC3E,CAAA,EAAwB,wBAAA,GAA2B;AAAA,IAAE,YAAY;AAAA,IAAM,aAAa;AAAA,EAAU;AAAA,EAC9F,CAAA,EAAwB,QAAA,GAAW;AAAA,IAClC,YAAY;AAAA,IACZ,YAAY,EAAuB,CAAK;AAAA,IACxC,QAAQ;AAAA,IACR,eAAe;AAAA,EACjB;AAAA,EACC,CAAA,EAAwB,WAAA,GAAc;AAAA,IACrC,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,UAAU;AAAA,IAEV,IAAI,EAAE,GAAG,sBAAsB;AAAA,EACjC;AAAA,EAEC,CAAA,EAAwB,aAAA,GAAgB;AAAA,IACvC,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,YAAY;AAAA,EACd;AACF"}
1
+ {"version":3,"file":"layout.es.js","names":[],"sources":["../../../../../src/insights-v2/blocks/ComponentBlocks/TransactionBlock/layout.ts"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles'\n\nimport {\n WARM_LIME_ACCENT_GRADIENT,\n WARNING_WASH_GRADIENT,\n getPrimaryWashGradient,\n} from '../../../components/celebrationGradients'\n\n/**\n * Transaction block variants, keyed by the backend `instance_slot.variant`. All render the same\n * pre-localized rows through `TransactionListCard`; only the header and the slot differ.\n *\n * - `WithHeader` — row under a date header (Fee Detected, Large Transaction).\n * - `WithHeaderFooter` — date header above the rows plus the footer/summary row from\n * `data.footer_text` / `data.footer_amount` (Replenish Savings' \"Remaining Balance\").\n * - `NoHeader` — the row alone (Large Transaction without a merchant).\n * - `UncategorizedTransaction` — filled primary header (\"{count} transactions\").\n * - `InfoWash` — raised row (border + shadow) on the blue slot wash, with the\n * subscription's live frequency under the amount (e.g. Subscription Detected).\n * - `WarningWash` — borderless row on the warning slot wash (e.g. Unexpected\n * Subscription Payment). Treatment names, not beat names, so any beat can reuse the wash.\n * - `StatusMessage` — no rows: an icon + message banner from `data.icon` / `data.message`\n * (Uncategorized Transactions V2 `complete`, \"All Categorized!\").\n * - `SpendingSummary` — header, rows and footer, with the header text in `primary.main`\n * (Weekend Spending Summary: the weekend above one row per category and \"Total spent\").\n */\nexport const transactionBlockVariant = {\n WithHeader: 'with_header',\n WithHeaderFooter: 'with_header_footer',\n NoHeader: 'no_header',\n // A multi-row list with no in-card header plus a \"Total\" summary row (Weekly New Merchants; the\n // date range is the card subtitle). The plain no-footer list reuses `NoHeader`.\n WithFooter: 'with_footer',\n UncategorizedTransaction: 'uncategorized_transaction',\n InfoWash: 'info_wash',\n WarningWash: 'warning_wash',\n StatusMessage: 'status_message',\n SpendingSummary: 'spending_summary',\n} as const\n\nexport type TransactionBlockVariant =\n (typeof transactionBlockVariant)[keyof typeof transactionBlockVariant]\n\nexport interface TransactionLayoutConfig {\n /** Show `instance_slot.data.header_text` above the rows. */\n showHeader: boolean\n /** Show the `data.footer_text` / `data.footer_amount` summary row beneath the rows. */\n showFooter?: boolean\n /** `TransactionListCard` style: grey utility header, or filled primary header. */\n cardVariant?: 'default' | 'primary'\n /** Theme colour for the header text, over the card style's own. */\n headerColor?: string\n /** CSS background for the slot behind the card; the card renders borderless unless `raised`. */\n background?: string\n /** Render `data.message` as a `StatusMessageCard` banner instead of the rows. */\n statusMessage?: boolean\n /** Caption each amount with the beat's live repeating transaction frequency. */\n showFrequency?: boolean\n /** Status badge and answered wash from the live repeating transaction. */\n followsSubscription?: boolean\n /** Wash once subscribed. */\n answeredBackground?: string\n /** Row card at `elevation/1` (needs `background`). */\n elevated?: boolean\n /** Slot padding override (CSS shorthand). */\n sx?: SxProps\n /** Border and shadow on the row card. */\n raised?: boolean\n /**\n * Tint a `CAT-` row logo as the Budget-style accent tile (category colour at 15% opacity, a 1px\n * category-colour border, a `text.primary` glyph) instead of mxui's default. Opt-in per variant so\n * it stays scoped to the beats that want it (Replenish Savings' multi-account Transfer row), not\n * every `transaction_block` consumer.\n */\n tintedCategoryLogo?: boolean\n}\n\n/** Per-variant `TransactionListCard` props (mirrors DetailedAccountBlock's `getLayoutConfig`). */\nexport const getLayoutConfig = (\n theme: Theme,\n): Record<TransactionBlockVariant, TransactionLayoutConfig> => ({\n // `with_header` is Replenish Savings' multi-account card: its one summary row is a `CAT-` Transfer\n // logo, which we tint. (Other `with_header` beats, e.g. Large Transaction, use a merchant logo, so\n // the `CAT-` tint path never runs for them.)\n [transactionBlockVariant.WithHeader]: { showHeader: true, tintedCategoryLogo: true },\n [transactionBlockVariant.WithHeaderFooter]: { showHeader: true, showFooter: true },\n [transactionBlockVariant.NoHeader]: { showHeader: false },\n [transactionBlockVariant.WithFooter]: { showHeader: false, showFooter: true },\n [transactionBlockVariant.UncategorizedTransaction]: { showHeader: true, cardVariant: 'primary' },\n [transactionBlockVariant.InfoWash]: {\n showHeader: false,\n background: getPrimaryWashGradient(theme),\n raised: true,\n showFrequency: true,\n },\n [transactionBlockVariant.WarningWash]: {\n showHeader: false,\n background: WARNING_WASH_GRADIENT,\n showFrequency: true,\n followsSubscription: true,\n answeredBackground: WARM_LIME_ACCENT_GRADIENT,\n elevated: true,\n // Room for the badge.\n sx: { p: '28px 24px 24px 32px' },\n },\n // Figma 1941:207336: the banner sits on the warm-to-lime slot wash.\n [transactionBlockVariant.StatusMessage]: {\n showHeader: false,\n statusMessage: true,\n background: WARM_LIME_ACCENT_GRADIENT,\n },\n [transactionBlockVariant.SpendingSummary]: {\n showHeader: true,\n showFooter: true,\n headerColor: 'primary.main',\n },\n})\n"],"mappings":";AA0BA,IAAa,IAA0B;AAAA,EACrC,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,UAAU;AAAA,EAGV,YAAY;AAAA,EACZ,0BAA0B;AAAA,EAC1B,UAAU;AAAA,EACV,aAAa;AAAA,EACb,eAAe;AAAA,EACf,iBAAiB;AACnB,GAwCa,IAAA,CACX,OAC8D;AAAA,EAI7D,CAAA,EAAwB,UAAA,GAAa;AAAA,IAAE,YAAY;AAAA,IAAM,oBAAoB;AAAA,EAAK;AAAA,EAClF,CAAA,EAAwB,gBAAA,GAAmB;AAAA,IAAE,YAAY;AAAA,IAAM,YAAY;AAAA,EAAK;AAAA,EAChF,CAAA,EAAwB,QAAA,GAAW,EAAE,YAAY,GAAM;AAAA,EACvD,CAAA,EAAwB,UAAA,GAAa;AAAA,IAAE,YAAY;AAAA,IAAO,YAAY;AAAA,EAAK;AAAA,EAC3E,CAAA,EAAwB,wBAAA,GAA2B;AAAA,IAAE,YAAY;AAAA,IAAM,aAAa;AAAA,EAAU;AAAA,EAC9F,CAAA,EAAwB,QAAA,GAAW;AAAA,IAClC,YAAY;AAAA,IACZ,YAAY,EAAuB,CAAK;AAAA,IACxC,QAAQ;AAAA,IACR,eAAe;AAAA,EACjB;AAAA,EACC,CAAA,EAAwB,WAAA,GAAc;AAAA,IACrC,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,UAAU;AAAA,IAEV,IAAI,EAAE,GAAG,sBAAsB;AAAA,EACjC;AAAA,EAEC,CAAA,EAAwB,aAAA,GAAgB;AAAA,IACvC,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,YAAY;AAAA,EACd;AAAA,EACC,CAAA,EAAwB,eAAA,GAAkB;AAAA,IACzC,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA,EACf;AACF"}
@@ -10,6 +10,8 @@ type TransactionListCardVariant = 'default' | 'primary';
10
10
  interface TransactionListCardProps {
11
11
  /** Optional header label above the rows (e.g. "{Date}", "3 transactions"). */
12
12
  header?: ReactNode;
13
+ /** Theme colour for the header label, over the variant's own. */
14
+ headerColor?: string;
13
15
  /** One or more transaction rows. */
14
16
  rows: InsightTransactionRowProps[];
15
17
  /** Optional summary/total row rendered beneath a divider. */
@@ -47,5 +49,5 @@ interface TransactionListCardProps {
47
49
  *
48
50
  * Scope is the Content section only; Header/Description are out of scope.
49
51
  */
50
- declare const TransactionListCard: ({ background, badge, elevated, footer, header, raised, rows, variant, sx, }: TransactionListCardProps) => import("react/jsx-runtime").JSX.Element | null;
52
+ declare const TransactionListCard: ({ background, badge, elevated, footer, header, headerColor, raised, rows, variant, sx, }: TransactionListCardProps) => import("react/jsx-runtime").JSX.Element | null;
51
53
  export default TransactionListCard;
@@ -1,12 +1,12 @@
1
- import k from "./InsightTransactionRow.es.js";
2
- import { ELEVATION_SHADOW as I } from "./shared/elevation.es.js";
3
- import { Fragment as T } from "react";
4
- import i from "@mui/material/Stack";
1
+ import I from "./InsightTransactionRow.es.js";
2
+ import { ELEVATION_SHADOW as S } from "./shared/elevation.es.js";
3
+ import { Fragment as L } from "react";
4
+ import d from "@mui/material/Stack";
5
5
  import { Text as m } from "@mxenabled/mxui";
6
- import { Fragment as f, jsx as r, jsxs as a } from "react/jsx-runtime";
7
- import g from "@mui/material/Box";
6
+ import { Fragment as g, jsx as r, jsxs as a } from "react/jsx-runtime";
7
+ import B from "@mui/material/Box";
8
8
  import u from "@mui/material/Divider";
9
- var S = (n) => n === "primary" ? {
9
+ var j = (n) => n === "primary" ? {
10
10
  radius: "8px",
11
11
  borderColor: "primary.main",
12
12
  headerBg: "primary.main",
@@ -30,9 +30,9 @@ var S = (n) => n === "primary" ? {
30
30
  px: 16,
31
31
  py: 2
32
32
  }
33
- }, V = ({ background: n, badge: c, elevated: B = !1, footer: l, header: d, raised: y = !1, rows: x, variant: v = "default", sx: C }) => {
33
+ }, N = ({ background: n, badge: c, elevated: y = !1, footer: l, header: i, headerColor: C, raised: v = !1, rows: x, variant: b = "default", sx: w }) => {
34
34
  if (x.length === 0) return null;
35
- const e = S(v), o = !!n, t = o ? "8px" : e.radius, s = !!d && !o && e.headerInsideBorder, p = d ? /* @__PURE__ */ r(i, {
35
+ const e = j(b), o = !!n, t = o ? "8px" : e.radius, s = !!i && !o && e.headerInsideBorder, R = b === "default" ? C ?? e.headerColor : e.headerColor, h = i ? /* @__PURE__ */ r(d, {
36
36
  sx: {
37
37
  bgcolor: e.headerBg,
38
38
  justifyContent: "center",
@@ -40,11 +40,11 @@ var S = (n) => n === "primary" ? {
40
40
  },
41
41
  children: /* @__PURE__ */ r(m, {
42
42
  bold: e.headerBold,
43
- color: e.headerColor,
43
+ color: R,
44
44
  variant: "caption",
45
- children: d
45
+ children: i
46
46
  })
47
- }) : null, w = l ? /* @__PURE__ */ a(f, { children: [/* @__PURE__ */ r(u, {}), /* @__PURE__ */ a(i, {
47
+ }) : null, T = l ? /* @__PURE__ */ a(g, { children: [/* @__PURE__ */ r(u, {}), /* @__PURE__ */ a(d, {
48
48
  sx: {
49
49
  alignItems: "center",
50
50
  bgcolor: o ? "background.paper" : "background.default",
@@ -64,15 +64,15 @@ var S = (n) => n === "primary" ? {
64
64
  variant: "body2",
65
65
  children: l.amount
66
66
  })]
67
- })] }) : null, R = /* @__PURE__ */ r(i, {
67
+ })] }) : null, k = /* @__PURE__ */ r(d, {
68
68
  role: "list",
69
69
  sx: { width: "100%" },
70
- children: x.map((h, b) => /* @__PURE__ */ a(T, { children: [b > 0 && /* @__PURE__ */ r(u, { role: "presentation" }), /* @__PURE__ */ r(g, {
70
+ children: x.map((p, f) => /* @__PURE__ */ a(L, { children: [f > 0 && /* @__PURE__ */ r(u, { role: "presentation" }), /* @__PURE__ */ r(B, {
71
71
  role: "listitem",
72
- children: /* @__PURE__ */ r(k, { ...h })
73
- })] }, b))
72
+ children: /* @__PURE__ */ r(I, { ...p })
73
+ })] }, f))
74
74
  });
75
- return /* @__PURE__ */ a(i, {
75
+ return /* @__PURE__ */ a(d, {
76
76
  "data-testid": "transaction-list-card",
77
77
  sx: {
78
78
  ...o ? {
@@ -84,10 +84,10 @@ var S = (n) => n === "primary" ? {
84
84
  },
85
85
  ...o && c ? { position: "relative" } : {},
86
86
  width: "100%",
87
- ...C
87
+ ...w
88
88
  },
89
89
  children: [
90
- o && c && /* @__PURE__ */ r(g, {
90
+ o && c && /* @__PURE__ */ r(B, {
91
91
  sx: {
92
92
  left: 16,
93
93
  position: "absolute",
@@ -96,23 +96,23 @@ var S = (n) => n === "primary" ? {
96
96
  },
97
97
  children: c
98
98
  }),
99
- !s && p && /* @__PURE__ */ r(i, {
99
+ !s && h && /* @__PURE__ */ r(d, {
100
100
  sx: {
101
101
  borderTopLeftRadius: t,
102
102
  borderTopRightRadius: t,
103
103
  overflow: "hidden"
104
104
  },
105
- children: p
105
+ children: h
106
106
  }),
107
- /* @__PURE__ */ a(i, {
107
+ /* @__PURE__ */ a(d, {
108
108
  sx: {
109
109
  ...o ? {
110
110
  bgcolor: "background.paper",
111
- ...B && {
112
- backgroundImage: (h) => h.vars?.overlays?.[1] ?? "none",
113
- boxShadow: I[1]
114
- },
115
111
  ...y && {
112
+ backgroundImage: (p) => p.vars?.overlays?.[1] ?? "none",
113
+ boxShadow: S[1]
114
+ },
115
+ ...v && {
116
116
  border: "1px solid",
117
117
  borderColor: "divider",
118
118
  boxShadow: 1
@@ -123,22 +123,22 @@ var S = (n) => n === "primary" ? {
123
123
  },
124
124
  borderBottomLeftRadius: t,
125
125
  borderBottomRightRadius: t,
126
- borderTopLeftRadius: s || !d ? t : 0,
127
- borderTopRightRadius: s || !d ? t : 0,
126
+ borderTopLeftRadius: s || !i ? t : 0,
127
+ borderTopRightRadius: s || !i ? t : 0,
128
128
  overflow: "hidden",
129
129
  width: "100%"
130
130
  },
131
131
  children: [
132
- s && /* @__PURE__ */ a(f, { children: [p, /* @__PURE__ */ r(u, {})] }),
133
- R,
134
- w
132
+ s && /* @__PURE__ */ a(g, { children: [h, /* @__PURE__ */ r(u, {})] }),
133
+ k,
134
+ T
135
135
  ]
136
136
  })
137
137
  ]
138
138
  });
139
139
  };
140
140
  export {
141
- V as default
141
+ N as default
142
142
  };
143
143
 
144
144
  //# sourceMappingURL=TransactionListCard.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TransactionListCard.es.js","names":[],"sources":["../../../src/insights-v2/components/TransactionListCard.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps, Theme } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport InsightTransactionRow, { type InsightTransactionRowProps } from './InsightTransactionRow'\nimport { ELEVATION_SHADOW } from './shared/elevation'\n\nexport interface FooterRow {\n label: ReactNode\n amount: ReactNode\n amountColor?: string\n}\n\ntype TransactionListCardVariant = 'default' | 'primary'\n\ninterface TransactionListCardProps {\n /** Optional header label above the rows (e.g. \"{Date}\", \"3 transactions\"). */\n header?: ReactNode\n /** One or more transaction rows. */\n rows: InsightTransactionRowProps[]\n /** Optional summary/total row rendered beneath a divider. */\n footer?: FooterRow\n /**\n * Card style:\n * - `default` — grey utility header, hairline border, radius 4.\n * - `primary` — filled `primary.main` header with white text and a matching\n * border, radius 8 (Figma \"Multi\" variant).\n *\n * In both cases the header is borderless; the border wraps the content block\n * below it.\n */\n variant?: TransactionListCardVariant\n /**\n * Optional background applied to the Slot behind the card. Must be a valid CSS\n * background string (gradient or color in CSS format); MUI theme tokens are\n * not resolved here (this is the CSS `background` shorthand, not `bgcolor`), so\n * use a CSS color literal instead. When set, the inner card renders borderless\n * on a white surface inside the padded Slot (Figma HSA Deposit), unless `raised`.\n */\n background?: string\n /** Status disc over the card's corner (needs `background`). */\n badge?: ReactNode\n /** Card at elevation/1 on the wash; not with `raised` (its shadow wins). */\n elevated?: boolean\n /** Border and shadow on the inner card; only with `background` (Figma Transaction Row). */\n raised?: boolean\n sx?: SxProps\n}\n\nconst getVariantStyles = (variant: TransactionListCardVariant) => {\n switch (variant) {\n case 'primary':\n // Borderless filled header on top of the bordered rows block.\n return {\n radius: '8px',\n borderColor: 'primary.main',\n headerBg: 'primary.main',\n headerColor: 'primary.contrastText',\n headerBold: false,\n headerInsideBorder: false,\n headerSx: { minHeight: 24, px: 12, py: 4 } as const,\n }\n default:\n // A single border wraps the card; the grey header sits inside it.\n return {\n radius: '8px',\n borderColor: 'divider',\n headerBg: 'background.default',\n headerColor: 'text.primary',\n headerBold: true,\n headerInsideBorder: true,\n headerSx: { minHeight: 36, px: 16, py: 2 } as const,\n }\n }\n}\n\n/**\n * List card composing an optional header label, one or more\n * `InsightTransactionRow`s (divided), and an optional footer/total row.\n * `variant` supplies the Figma design defaults for the two card styles.\n *\n * Scope is the Content section only; Header/Description are out of scope.\n */\nconst TransactionListCard = ({\n background,\n badge,\n elevated = false,\n footer,\n header,\n raised = false,\n rows,\n variant = 'default',\n sx,\n}: TransactionListCardProps) => {\n // rows usually comes from mapped API data, so an empty array is reachable and\n // would render a broken border shell; render nothing instead.\n if (rows.length === 0) return null\n\n const styles = getVariantStyles(variant)\n const hasBackground = Boolean(background)\n const radius = hasBackground ? '8px' : styles.radius\n // The header sits inside the border only for the bordered `default` variant;\n // for `primary`/backgrounded cards it sits above a separately-bordered body.\n const headerInsideBorder = Boolean(header) && !hasBackground && styles.headerInsideBorder\n\n const headerBlock = header ? (\n <Stack sx={{ bgcolor: styles.headerBg, justifyContent: 'center', ...styles.headerSx }}>\n <Text bold={styles.headerBold} color={styles.headerColor} variant=\"caption\">\n {header}\n </Text>\n </Stack>\n ) : null\n\n const footerBlock = footer ? (\n <>\n <Divider />\n <Stack\n sx={{\n alignItems: 'center',\n bgcolor: hasBackground ? 'background.paper' : 'background.default',\n flexDirection: 'row',\n justifyContent: 'space-between',\n minHeight: 40,\n px: 16,\n py: 2,\n }}\n >\n <Text color=\"text.secondary\" variant=\"caption\">\n {footer.label}\n </Text>\n <Text bold={true} color={footer.amountColor ?? 'text.primary'} variant=\"body2\">\n {footer.amount}\n </Text>\n </Stack>\n </>\n ) : null\n\n const rowsBlock = (\n <Stack role=\"list\" sx={{ width: '100%' }}>\n {rows.map((row, index) => (\n // Static, caller-ordered list that may contain identical rows, so the\n // array index is the correct key (a content-based key would collide).\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={index}>\n {index > 0 && <Divider role=\"presentation\" />}\n <Box role=\"listitem\">\n <InsightTransactionRow {...row} />\n </Box>\n </Fragment>\n ))}\n </Stack>\n )\n\n return (\n <Stack\n data-testid=\"transaction-list-card\"\n sx={{\n ...(hasBackground ? { background, p: 16 } : { pt: 8, px: 16 }),\n ...(hasBackground && badge ? { position: 'relative' } : {}),\n width: '100%',\n ...sx,\n }}\n >\n {hasBackground &&\n badge && (\n // Centred on the card's top-left corner.\n <Box sx={{ left: 16, position: 'absolute', top: 12, zIndex: 1 }}>{badge}</Box>\n )}\n {/* Header above the border for `primary`/backgrounded cards; top-rounded. */}\n {!headerInsideBorder && headerBlock && (\n <Stack\n sx={{\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n overflow: 'hidden',\n }}\n >\n {headerBlock}\n </Stack>\n )}\n\n <Stack\n sx={{\n ...(hasBackground\n ? {\n bgcolor: 'background.paper',\n // elevation/1 shadow plus the dark-mode tint.\n ...(elevated && {\n backgroundImage: (theme: Theme) => theme.vars?.overlays?.[1] ?? 'none',\n boxShadow: ELEVATION_SHADOW[1],\n }),\n ...(raised && { border: '1px solid', borderColor: 'divider', boxShadow: 1 }),\n }\n : { border: '1px solid', borderColor: styles.borderColor }),\n borderBottomLeftRadius: radius,\n borderBottomRightRadius: radius,\n borderTopLeftRadius: headerInsideBorder || !header ? radius : 0,\n borderTopRightRadius: headerInsideBorder || !header ? radius : 0,\n overflow: 'hidden',\n width: '100%',\n }}\n >\n {/* Header inside the border for the `default` table variant. */}\n {headerInsideBorder && (\n <>\n {headerBlock}\n <Divider />\n </>\n )}\n {rowsBlock}\n {footerBlock}\n </Stack>\n </Stack>\n )\n}\n\nexport default TransactionListCard\n"],"mappings":"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"}
1
+ {"version":3,"file":"TransactionListCard.es.js","names":[],"sources":["../../../src/insights-v2/components/TransactionListCard.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react'\n\nimport Box from '@mui/material/Box'\nimport Divider from '@mui/material/Divider'\nimport Stack from '@mui/material/Stack'\nimport type { SxProps, Theme } from '@mui/material/styles'\n\nimport { Text } from '@mxenabled/mxui'\n\nimport InsightTransactionRow, { type InsightTransactionRowProps } from './InsightTransactionRow'\nimport { ELEVATION_SHADOW } from './shared/elevation'\n\nexport interface FooterRow {\n label: ReactNode\n amount: ReactNode\n amountColor?: string\n}\n\ntype TransactionListCardVariant = 'default' | 'primary'\n\ninterface TransactionListCardProps {\n /** Optional header label above the rows (e.g. \"{Date}\", \"3 transactions\"). */\n header?: ReactNode\n /** Theme colour for the header label, over the variant's own. */\n headerColor?: string\n /** One or more transaction rows. */\n rows: InsightTransactionRowProps[]\n /** Optional summary/total row rendered beneath a divider. */\n footer?: FooterRow\n /**\n * Card style:\n * - `default` — grey utility header, hairline border, radius 4.\n * - `primary` — filled `primary.main` header with white text and a matching\n * border, radius 8 (Figma \"Multi\" variant).\n *\n * In both cases the header is borderless; the border wraps the content block\n * below it.\n */\n variant?: TransactionListCardVariant\n /**\n * Optional background applied to the Slot behind the card. Must be a valid CSS\n * background string (gradient or color in CSS format); MUI theme tokens are\n * not resolved here (this is the CSS `background` shorthand, not `bgcolor`), so\n * use a CSS color literal instead. When set, the inner card renders borderless\n * on a white surface inside the padded Slot (Figma HSA Deposit), unless `raised`.\n */\n background?: string\n /** Status disc over the card's corner (needs `background`). */\n badge?: ReactNode\n /** Card at elevation/1 on the wash; not with `raised` (its shadow wins). */\n elevated?: boolean\n /** Border and shadow on the inner card; only with `background` (Figma Transaction Row). */\n raised?: boolean\n sx?: SxProps\n}\n\nconst getVariantStyles = (variant: TransactionListCardVariant) => {\n switch (variant) {\n case 'primary':\n // Borderless filled header on top of the bordered rows block.\n return {\n radius: '8px',\n borderColor: 'primary.main',\n headerBg: 'primary.main',\n headerColor: 'primary.contrastText',\n headerBold: false,\n headerInsideBorder: false,\n headerSx: { minHeight: 24, px: 12, py: 4 } as const,\n }\n default:\n // A single border wraps the card; the grey header sits inside it.\n return {\n radius: '8px',\n borderColor: 'divider',\n headerBg: 'background.default',\n headerColor: 'text.primary',\n headerBold: true,\n headerInsideBorder: true,\n headerSx: { minHeight: 36, px: 16, py: 2 } as const,\n }\n }\n}\n\n/**\n * List card composing an optional header label, one or more\n * `InsightTransactionRow`s (divided), and an optional footer/total row.\n * `variant` supplies the Figma design defaults for the two card styles.\n *\n * Scope is the Content section only; Header/Description are out of scope.\n */\nconst TransactionListCard = ({\n background,\n badge,\n elevated = false,\n footer,\n header,\n headerColor,\n raised = false,\n rows,\n variant = 'default',\n sx,\n}: TransactionListCardProps) => {\n // rows usually comes from mapped API data, so an empty array is reachable and\n // would render a broken border shell; render nothing instead.\n if (rows.length === 0) return null\n\n const styles = getVariantStyles(variant)\n const hasBackground = Boolean(background)\n const radius = hasBackground ? '8px' : styles.radius\n // The header sits inside the border only for the bordered `default` variant;\n // for `primary`/backgrounded cards it sits above a separately-bordered body.\n const headerInsideBorder = Boolean(header) && !hasBackground && styles.headerInsideBorder\n\n const headerTextColor =\n variant === 'default' ? (headerColor ?? styles.headerColor) : styles.headerColor\n\n const headerBlock = header ? (\n <Stack sx={{ bgcolor: styles.headerBg, justifyContent: 'center', ...styles.headerSx }}>\n <Text bold={styles.headerBold} color={headerTextColor} variant=\"caption\">\n {header}\n </Text>\n </Stack>\n ) : null\n\n const footerBlock = footer ? (\n <>\n <Divider />\n <Stack\n sx={{\n alignItems: 'center',\n bgcolor: hasBackground ? 'background.paper' : 'background.default',\n flexDirection: 'row',\n justifyContent: 'space-between',\n minHeight: 40,\n px: 16,\n py: 2,\n }}\n >\n <Text color=\"text.secondary\" variant=\"caption\">\n {footer.label}\n </Text>\n <Text bold={true} color={footer.amountColor ?? 'text.primary'} variant=\"body2\">\n {footer.amount}\n </Text>\n </Stack>\n </>\n ) : null\n\n const rowsBlock = (\n <Stack role=\"list\" sx={{ width: '100%' }}>\n {rows.map((row, index) => (\n // Static, caller-ordered list that may contain identical rows, so the\n // array index is the correct key (a content-based key would collide).\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={index}>\n {index > 0 && <Divider role=\"presentation\" />}\n <Box role=\"listitem\">\n <InsightTransactionRow {...row} />\n </Box>\n </Fragment>\n ))}\n </Stack>\n )\n\n return (\n <Stack\n data-testid=\"transaction-list-card\"\n sx={{\n ...(hasBackground ? { background, p: 16 } : { pt: 8, px: 16 }),\n ...(hasBackground && badge ? { position: 'relative' } : {}),\n width: '100%',\n ...sx,\n }}\n >\n {hasBackground &&\n badge && (\n // Centred on the card's top-left corner.\n <Box sx={{ left: 16, position: 'absolute', top: 12, zIndex: 1 }}>{badge}</Box>\n )}\n {/* Header above the border for `primary`/backgrounded cards; top-rounded. */}\n {!headerInsideBorder && headerBlock && (\n <Stack\n sx={{\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n overflow: 'hidden',\n }}\n >\n {headerBlock}\n </Stack>\n )}\n\n <Stack\n sx={{\n ...(hasBackground\n ? {\n bgcolor: 'background.paper',\n // elevation/1 shadow plus the dark-mode tint.\n ...(elevated && {\n backgroundImage: (theme: Theme) => theme.vars?.overlays?.[1] ?? 'none',\n boxShadow: ELEVATION_SHADOW[1],\n }),\n ...(raised && { border: '1px solid', borderColor: 'divider', boxShadow: 1 }),\n }\n : { border: '1px solid', borderColor: styles.borderColor }),\n borderBottomLeftRadius: radius,\n borderBottomRightRadius: radius,\n borderTopLeftRadius: headerInsideBorder || !header ? radius : 0,\n borderTopRightRadius: headerInsideBorder || !header ? radius : 0,\n overflow: 'hidden',\n width: '100%',\n }}\n >\n {/* Header inside the border for the `default` table variant. */}\n {headerInsideBorder && (\n <>\n {headerBlock}\n <Divider />\n </>\n )}\n {rowsBlock}\n {footerBlock}\n </Stack>\n </Stack>\n )\n}\n\nexport default TransactionListCard\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { buildDynamicCopy as _ } from "../../../../../core/utils/Localization.es.js";
1
+ import { buildDynamicCopy as u } from "../../../../../core/utils/Localization.es.js";
2
2
  import { useCategoryStore as b, useEvent as L, useGlobalCopyStore as E, useTransactionStore as N } from "../../../../../common/context/hooks.es.js";
3
3
  import O from "../../../../../common/components/dialog/Dialog.es.js";
4
4
  import { ANALYTICS_EVENTS as R } from "../../../../../common/constants/Analytics.es.js";
@@ -24,12 +24,12 @@ var de = ({ transaction: e }) => {
24
24
  }), o && await g(a, e), n(""), c(R.TRANSACTION_DETAILS_CLICK_CATEGORY, { transaction_guid: e.guid });
25
25
  }, I = (o) => {
26
26
  if (e.is_manual && !e.guid) {
27
- const u = s.find((v) => v.guid === o);
27
+ const _ = s.find((v) => v.guid === o);
28
28
  T({
29
29
  ...e,
30
- category: u?.name,
30
+ category: _?.name,
31
31
  category_guid: o,
32
- top_level_category_guid: u?.parent_guid || o
32
+ top_level_category_guid: _?.parent_guid || o
33
33
  });
34
34
  } else n(o);
35
35
  p();
@@ -51,7 +51,8 @@ var de = ({ transaction: e }) => {
51
51
  variant: "rounded",
52
52
  children: /* @__PURE__ */ t(P, {
53
53
  categoryGuid: e.top_level_category_guid,
54
- size: 24,
54
+ icon_ratio: 1,
55
+ size: 20,
55
56
  sx: { color: "text.primary" },
56
57
  variant: K.Transparent
57
58
  })
@@ -84,7 +85,7 @@ var de = ({ transaction: e }) => {
84
85
  title: r.actions_select_a_category
85
86
  }),
86
87
  /* @__PURE__ */ t(O, {
87
- copy: { title: _(r.actions_apply_to_all_transaction_types, e.description) },
88
+ copy: { title: u(r.actions_apply_to_all_transaction_types, e.description) },
88
89
  isOpen: !!a,
89
90
  onClose: () => n(""),
90
91
  onPrimaryAction: () => d(!0),
@@ -94,7 +95,7 @@ var de = ({ transaction: e }) => {
94
95
  secondaryText: r.actions_this_time_only,
95
96
  children: /* @__PURE__ */ t(V, {
96
97
  variant: "subtitle1",
97
- children: _(r.actions_all_past_and_future, e.description, x?.name)
98
+ children: u(r.actions_all_past_and_future, e.description, x?.name)
98
99
  })
99
100
  })
100
101
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"CategoryAction.es.js","names":[],"sources":["../../../../../../src/transactions/components/shared/transactiondetails/actions/CategoryAction.tsx"],"sourcesContent":["import React from 'react'\n\nimport Avatar from '@mui/material/Avatar'\nimport ListItem from '@mui/material/ListItem'\nimport ListItemAvatar from '@mui/material/ListItemAvatar'\nimport ListItemButton from '@mui/material/ListItemButton'\nimport ListItemIcon from '@mui/material/ListItemIcon'\nimport ListItemText from '@mui/material/ListItemText'\nimport { useTheme } from '@mui/material/styles'\n\nimport { CategoryIcon, CategoryIconVariants, P, Text } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\nimport { CategorySelectorDrawer } from '../../../../../categories'\n\nimport {\n ANALYTICS_EVENTS,\n Dialog,\n useCategoryStore,\n useGlobalCopyStore,\n} from '../../../../../common'\nimport type { Transaction } from '../../../../../core'\n\nimport { ON_CLICK_EVENTS } from '../../../../constants/OnClickEvents'\nimport { useTransactionsUiStore } from '../../../../context/hooks'\nimport { useEvent, useTransactionStore } from '../../../../../common'\nimport { buildDynamicCopy } from '../../../../../core/utils/Localization'\n\ninterface CategoryActionProps {\n transaction: Transaction\n}\n\nconst CategoryAction: React.FC<CategoryActionProps> = ({ transaction }) => {\n const { addOrUpdateTransactionRule, updateTransaction } = useTransactionStore()\n const { categories } = useCategoryStore()\n const { onEvent } = useEvent()\n const { setShouldDisableDrawerScroll, updateManualTransaction } = useTransactionsUiStore()\n const { transactions: copy } = useGlobalCopyStore()\n\n const theme = useTheme()\n\n const categoryRowRef = React.useRef<HTMLDivElement>(null)\n const [open, setOpen] = React.useState(false)\n const [selectedGuid, setSelectedGuid] = React.useState('')\n\n const handleCategoryChange = async (applyToAll: boolean) => {\n await updateTransaction({ ...transaction, category_guid: selectedGuid })\n if (applyToAll) {\n await addOrUpdateTransactionRule(selectedGuid, transaction)\n }\n setSelectedGuid('')\n onEvent(ANALYTICS_EVENTS.TRANSACTION_DETAILS_CLICK_CATEGORY, {\n transaction_guid: transaction.guid,\n })\n }\n\n const handleSelected = (guid: string) => {\n if (transaction.is_manual && !transaction.guid) {\n const category = categories.find((c) => c.guid === guid)\n updateManualTransaction({\n ...transaction,\n category: category?.name,\n category_guid: guid,\n top_level_category_guid: category?.parent_guid || guid,\n })\n } else {\n setSelectedGuid(guid)\n }\n\n handleCloseDrawer()\n }\n\n const handleCloseDrawer = () => {\n setOpen(false)\n setShouldDisableDrawerScroll(false)\n }\n\n const category = React.useMemo(\n () => categories.find((item) => item.guid === selectedGuid),\n [selectedGuid],\n )\n\n const bgColor = theme.palette.mode === 'dark' ? 'grey.800' : 'grey.100'\n\n return (\n <ListItem disableGutters={true} disablePadding={true}>\n <ListItemButton\n ref={categoryRowRef}\n onClick={() => {\n onEvent(ON_CLICK_EVENTS.ON_TRANSACTION_CATEGORY_CLICK)\n setOpen(true)\n }}\n >\n <ListItemAvatar>\n <Avatar sx={{ bgcolor: bgColor }} variant=\"rounded\">\n <CategoryIcon\n categoryGuid={transaction.top_level_category_guid}\n size={24}\n sx={{ color: 'text.primary' }}\n variant={CategoryIconVariants.Transparent}\n />\n </Avatar>\n </ListItemAvatar>\n <ListItemText\n primary={copy.category_title}\n secondary={\n <Text bold={true} sx={{ color: 'text.primary' }} variant=\"body1\">\n {transaction.category ?? copy.actions_select_a_category}\n </Text>\n }\n slotProps={{ primary: { variant: 'caption', fontSize: 11, fontWeight: 'normal' } }}\n />\n <ListItemIcon>\n <Icon name=\"chevron_right\" sx={{ color: 'text.primary' }} />\n </ListItemIcon>\n </ListItemButton>\n\n <CategorySelectorDrawer\n initialSelected={transaction.category_guid}\n onClose={handleCloseDrawer}\n onSelect={handleSelected}\n showDrawer={open}\n title={copy.actions_select_a_category}\n />\n\n <Dialog\n copy={{\n title: buildDynamicCopy(\n copy.actions_apply_to_all_transaction_types,\n transaction.description,\n ) as string,\n }}\n isOpen={Boolean(selectedGuid)}\n onClose={() => setSelectedGuid('')}\n onPrimaryAction={() => handleCategoryChange(true)}\n onSecondaryAction={() => handleCategoryChange(false)}\n primaryText={copy.actions_apply_to_all}\n returnFocusTo={categoryRowRef}\n secondaryText={copy.actions_this_time_only}\n >\n <P variant=\"subtitle1\">\n {\n buildDynamicCopy(\n copy.actions_all_past_and_future,\n transaction.description,\n category?.name,\n ) as string\n }\n </P>\n </Dialog>\n </ListItem>\n )\n}\n\nexport default CategoryAction\n"],"mappings":"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"}
1
+ {"version":3,"file":"CategoryAction.es.js","names":[],"sources":["../../../../../../src/transactions/components/shared/transactiondetails/actions/CategoryAction.tsx"],"sourcesContent":["import React from 'react'\n\nimport Avatar from '@mui/material/Avatar'\nimport ListItem from '@mui/material/ListItem'\nimport ListItemAvatar from '@mui/material/ListItemAvatar'\nimport ListItemButton from '@mui/material/ListItemButton'\nimport ListItemIcon from '@mui/material/ListItemIcon'\nimport ListItemText from '@mui/material/ListItemText'\nimport { useTheme } from '@mui/material/styles'\n\nimport { CategoryIcon, CategoryIconVariants, P, Text } from '@mxenabled/mxui'\nimport { Icon } from '@mxenabled/mx-icons'\nimport { CategorySelectorDrawer } from '../../../../../categories'\n\nimport {\n ANALYTICS_EVENTS,\n Dialog,\n useCategoryStore,\n useGlobalCopyStore,\n} from '../../../../../common'\nimport type { Transaction } from '../../../../../core'\n\nimport { ON_CLICK_EVENTS } from '../../../../constants/OnClickEvents'\nimport { useTransactionsUiStore } from '../../../../context/hooks'\nimport { useEvent, useTransactionStore } from '../../../../../common'\nimport { buildDynamicCopy } from '../../../../../core/utils/Localization'\n\ninterface CategoryActionProps {\n transaction: Transaction\n}\n\nconst CategoryAction: React.FC<CategoryActionProps> = ({ transaction }) => {\n const { addOrUpdateTransactionRule, updateTransaction } = useTransactionStore()\n const { categories } = useCategoryStore()\n const { onEvent } = useEvent()\n const { setShouldDisableDrawerScroll, updateManualTransaction } = useTransactionsUiStore()\n const { transactions: copy } = useGlobalCopyStore()\n\n const theme = useTheme()\n\n const categoryRowRef = React.useRef<HTMLDivElement>(null)\n const [open, setOpen] = React.useState(false)\n const [selectedGuid, setSelectedGuid] = React.useState('')\n\n const handleCategoryChange = async (applyToAll: boolean) => {\n await updateTransaction({ ...transaction, category_guid: selectedGuid })\n if (applyToAll) {\n await addOrUpdateTransactionRule(selectedGuid, transaction)\n }\n setSelectedGuid('')\n onEvent(ANALYTICS_EVENTS.TRANSACTION_DETAILS_CLICK_CATEGORY, {\n transaction_guid: transaction.guid,\n })\n }\n\n const handleSelected = (guid: string) => {\n if (transaction.is_manual && !transaction.guid) {\n const category = categories.find((c) => c.guid === guid)\n updateManualTransaction({\n ...transaction,\n category: category?.name,\n category_guid: guid,\n top_level_category_guid: category?.parent_guid || guid,\n })\n } else {\n setSelectedGuid(guid)\n }\n\n handleCloseDrawer()\n }\n\n const handleCloseDrawer = () => {\n setOpen(false)\n setShouldDisableDrawerScroll(false)\n }\n\n const category = React.useMemo(\n () => categories.find((item) => item.guid === selectedGuid),\n [selectedGuid],\n )\n\n const bgColor = theme.palette.mode === 'dark' ? 'grey.800' : 'grey.100'\n\n return (\n <ListItem disableGutters={true} disablePadding={true}>\n <ListItemButton\n ref={categoryRowRef}\n onClick={() => {\n onEvent(ON_CLICK_EVENTS.ON_TRANSACTION_CATEGORY_CLICK)\n setOpen(true)\n }}\n >\n <ListItemAvatar>\n <Avatar sx={{ bgcolor: bgColor }} variant=\"rounded\">\n <CategoryIcon\n categoryGuid={transaction.top_level_category_guid}\n icon_ratio={1}\n size={20}\n sx={{ color: 'text.primary' }}\n variant={CategoryIconVariants.Transparent}\n />\n </Avatar>\n </ListItemAvatar>\n <ListItemText\n primary={copy.category_title}\n secondary={\n <Text bold={true} sx={{ color: 'text.primary' }} variant=\"body1\">\n {transaction.category ?? copy.actions_select_a_category}\n </Text>\n }\n slotProps={{ primary: { variant: 'caption', fontSize: 11, fontWeight: 'normal' } }}\n />\n <ListItemIcon>\n <Icon name=\"chevron_right\" sx={{ color: 'text.primary' }} />\n </ListItemIcon>\n </ListItemButton>\n\n <CategorySelectorDrawer\n initialSelected={transaction.category_guid}\n onClose={handleCloseDrawer}\n onSelect={handleSelected}\n showDrawer={open}\n title={copy.actions_select_a_category}\n />\n\n <Dialog\n copy={{\n title: buildDynamicCopy(\n copy.actions_apply_to_all_transaction_types,\n transaction.description,\n ) as string,\n }}\n isOpen={Boolean(selectedGuid)}\n onClose={() => setSelectedGuid('')}\n onPrimaryAction={() => handleCategoryChange(true)}\n onSecondaryAction={() => handleCategoryChange(false)}\n primaryText={copy.actions_apply_to_all}\n returnFocusTo={categoryRowRef}\n secondaryText={copy.actions_this_time_only}\n >\n <P variant=\"subtitle1\">\n {\n buildDynamicCopy(\n copy.actions_all_past_and_future,\n transaction.description,\n category?.name,\n ) as string\n }\n </P>\n </Dialog>\n </ListItem>\n )\n}\n\nexport default CategoryAction\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-cartographer/experiences",
3
- "version": "9.7.93",
3
+ "version": "9.7.95",
4
4
  "description": "Library containing experience widgets",
5
5
  "author": "MX",
6
6
  "license": "MIT",